Upgrade bundled PCRE to 8.41
authorAnatol Belski <ab@php.net>
Tue, 11 Jul 2017 14:34:45 +0000 (16:34 +0200)
committerAnatol Belski <ab@php.net>
Tue, 11 Jul 2017 15:01:59 +0000 (17:01 +0200)
HEADSUP! With PCRE 8.39 the JIT related code was changed in the way,
that additional valgrind options became almost unavoidable. Valgrind
had it already sometimes hard with JIT, now there are seem to be more
cases requiring special valgrind options.

For this reason, the new configure option --with-pcre-valgrind was
introduced. The option is development/debugging only and turns on the
Valgrind related pieces in PCRE, so then false positives are avoided
to the big part. In addition, run-tests.php was added a new valgrind
option, when the leak check is enabled and the test filepath contains
pcre.

Thus, to debug the code related to PCRE with JIT enabled, two things
would likely make sense

  - configure --with-pcre-valgrind
  - valgrind option --smc-check=all if run-tests.php is not used

The checks so far reveal no new issues.

76 files changed:
ext/pcre/config0.m4
ext/pcre/pcrelib/AUTHORS
ext/pcre/pcrelib/ChangeLog
ext/pcre/pcrelib/LICENCE
ext/pcre/pcrelib/NEWS
ext/pcre/pcrelib/README
ext/pcre/pcrelib/config.h
ext/pcre/pcrelib/dftables.c
ext/pcre/pcrelib/doc/pcre.txt
ext/pcre/pcrelib/pcre.h
ext/pcre/pcrelib/pcre_compile.c
ext/pcre/pcrelib/pcre_config.c
ext/pcre/pcrelib/pcre_exec.c
ext/pcre/pcrelib/pcre_fullinfo.c
ext/pcre/pcrelib/pcre_get.c
ext/pcre/pcrelib/pcre_globals.c
ext/pcre/pcrelib/pcre_internal.h
ext/pcre/pcrelib/pcre_jit_compile.c
ext/pcre/pcrelib/pcre_maketables.c
ext/pcre/pcrelib/pcre_newline.c
ext/pcre/pcrelib/pcre_ord2utf8.c
ext/pcre/pcrelib/pcre_printint.c
ext/pcre/pcrelib/pcre_refcount.c
ext/pcre/pcrelib/pcre_study.c
ext/pcre/pcrelib/pcre_tables.c
ext/pcre/pcrelib/pcre_ucd.c
ext/pcre/pcrelib/pcre_valid_utf8.c
ext/pcre/pcrelib/pcre_version.c
ext/pcre/pcrelib/pcre_xclass.c
ext/pcre/pcrelib/pcreposix.c
ext/pcre/pcrelib/sljit/sljitConfig.h
ext/pcre/pcrelib/sljit/sljitConfigInternal.h
ext/pcre/pcrelib/sljit/sljitExecAllocator.c
ext/pcre/pcrelib/sljit/sljitLir.c
ext/pcre/pcrelib/sljit/sljitLir.h
ext/pcre/pcrelib/sljit/sljitNativeARM_32.c
ext/pcre/pcrelib/sljit/sljitNativeARM_64.c
ext/pcre/pcrelib/sljit/sljitNativeARM_T2_32.c
ext/pcre/pcrelib/sljit/sljitNativeMIPS_32.c
ext/pcre/pcrelib/sljit/sljitNativeMIPS_64.c
ext/pcre/pcrelib/sljit/sljitNativeMIPS_common.c
ext/pcre/pcrelib/sljit/sljitNativePPC_32.c
ext/pcre/pcrelib/sljit/sljitNativePPC_64.c
ext/pcre/pcrelib/sljit/sljitNativePPC_common.c
ext/pcre/pcrelib/sljit/sljitNativeSPARC_32.c
ext/pcre/pcrelib/sljit/sljitNativeSPARC_common.c
ext/pcre/pcrelib/sljit/sljitNativeTILEGX-encoder.c
ext/pcre/pcrelib/sljit/sljitNativeTILEGX_64.c
ext/pcre/pcrelib/sljit/sljitNativeX86_32.c
ext/pcre/pcrelib/sljit/sljitNativeX86_64.c
ext/pcre/pcrelib/sljit/sljitNativeX86_common.c
ext/pcre/pcrelib/sljit/sljitUtils.c
ext/pcre/pcrelib/testdata/testinput1
ext/pcre/pcrelib/testdata/testinput11
ext/pcre/pcrelib/testdata/testinput12
ext/pcre/pcrelib/testdata/testinput15
ext/pcre/pcrelib/testdata/testinput16
ext/pcre/pcrelib/testdata/testinput19
ext/pcre/pcrelib/testdata/testinput2
ext/pcre/pcrelib/testdata/testinput6
ext/pcre/pcrelib/testdata/testinput7
ext/pcre/pcrelib/testdata/testinput8
ext/pcre/pcrelib/testdata/testoutput1
ext/pcre/pcrelib/testdata/testoutput11-16
ext/pcre/pcrelib/testdata/testoutput11-32
ext/pcre/pcrelib/testdata/testoutput11-8
ext/pcre/pcrelib/testdata/testoutput12
ext/pcre/pcrelib/testdata/testoutput15
ext/pcre/pcrelib/testdata/testoutput16
ext/pcre/pcrelib/testdata/testoutput19
ext/pcre/pcrelib/testdata/testoutput2
ext/pcre/pcrelib/testdata/testoutput6
ext/pcre/pcrelib/testdata/testoutput7
ext/pcre/pcrelib/testdata/testoutput8
ext/pcre/php_pcre.c
run-tests.php

index 35fc585d51117b721bf196093eb19ff980909863..6d5b2577911666d9fa2ad0c0563b16c6ec9fb4ed 100644 (file)
@@ -78,3 +78,29 @@ PHP_ARG_WITH(pcre-jit,,[  --with-pcre-jit         Enable PCRE JIT functionality]
     fi
   fi
 
+PHP_ARG_WITH(pcre-valgrind,,[  --with-pcre-valgrind=DIR
+                          Enable PCRE valgrind support. Developers only!], no, no)
+  if test "$PHP_PCRE_REGEX" != "yes" && test "$PHP_PCRE_REGEX" != "no"; then
+    AC_MSG_WARN([PHP is going to be linked with an external PCRE, --with-pcre-valgrind has no effect])
+  else
+    if test "$PHP_PCRE_VALGRIND" != "no"; then
+      PHP_PCRE_VALGRIND_INCDIR=
+      AC_MSG_CHECKING([for Valgrind headers location])
+      for i in $PHP_PCRE_VALGRIND $PHP_PCRE_VALGRIND/include $PHP_PCRE_VALGRIND/local/include /usr/include /usr/local/include; do
+        if test -f $i/valgrind/memcheck.h
+        then
+          PHP_PCRE_VALGRIND_INCDIR=$i
+          break
+        fi
+      done
+      if test -z "$PHP_PCRE_VALGRIND_INCDIR"
+      then
+        AC_MSG_ERROR([Could not find valgrind/memcheck.h])
+      else
+        AC_DEFINE(HAVE_PCRE_VALGRIND_SUPPORT, 1, [ ])
+        PHP_ADD_INCLUDE($PHP_PCRE_VALGRIND_INCDIR)
+        AC_MSG_RESULT([$PHP_PCRE_VALGRIND_INCDIR])
+      fi
+    fi
+  fi
+
index d33723f198a836d094709c868dce2ec6bab2de0b..291657caef10a10c4cd89871b7e666e5979ea47c 100644 (file)
@@ -8,7 +8,7 @@ Email domain:     cam.ac.uk
 University of Cambridge Computing Service,
 Cambridge, England.
 
-Copyright (c) 1997-2015 University of Cambridge
+Copyright (c) 1997-2017 University of Cambridge
 All rights reserved
 
 
@@ -19,7 +19,7 @@ Written by:       Zoltan Herczeg
 Email local part: hzmester
 Emain domain:     freemail.hu
 
-Copyright(c) 2010-2015 Zoltan Herczeg
+Copyright(c) 2010-2017 Zoltan Herczeg
 All rights reserved.
 
 
@@ -30,7 +30,7 @@ Written by:       Zoltan Herczeg
 Email local part: hzmester
 Emain domain:     freemail.hu
 
-Copyright(c) 2009-2015 Zoltan Herczeg
+Copyright(c) 2009-2017 Zoltan Herczeg
 All rights reserved.
 
 
index 5e5bf188cea00c055c4e3216fbb512025214b683..590a7542885b3c4f5118de1fdfc500d43a600518 100644 (file)
@@ -4,12 +4,198 @@ ChangeLog for PCRE
 Note that the PCRE 8.xx series (PCRE1) is now in a bugfix-only state. All
 development is happening in the PCRE2 10.xx series.
 
+Version 8.41 05-July-2017
+-------------------------
+
+1.  Fixed typo in CMakeLists.txt (wrong number of arguments for
+PCRE_STATIC_RUNTIME (affects MSVC only).
+
+2.  Issue 1 for 8.40 below was not correctly fixed. If pcregrep in multiline
+mode with --only-matching matched several lines, it restarted scanning at the
+next line instead of moving on to the end of the matched string, which can be
+several lines after the start.
+
+3.  Fix a missing else in the JIT compiler reported by 'idaifish'.
+
+4.  A (?# style comment is now ignored between a basic quantifier and a
+following '+' or '?' (example: /X+(?#comment)?Y/.
+
+5.  Avoid use of a potentially overflowing buffer in pcregrep (patch by Petr
+Pisar).
+
+6.  Fuzzers have reported issues in pcretest. These are NOT serious (it is,
+after all, just a test program). However, to stop the reports, some easy ones
+are fixed:
+
+    (a) Check for values < 256 when calling isprint() in pcretest.
+    (b) Give an error for too big a number after \O.
+
+7.  In the 32-bit library in non-UTF mode, an attempt to find a Unicode
+property for a character with a code point greater than 0x10ffff (the Unicode
+maximum) caused a crash.
+
+8. The alternative matching function, pcre_dfa_exec() misbehaved if it
+encountered a character class with a possessive repeat, for example [a-f]{3}+.
+
+9. When pcretest called pcre_copy_substring() in 32-bit mode, it set the buffer
+length incorrectly, which could result in buffer overflow.
+
+10. Remove redundant line of code (accidentally left in ages ago).
+
+11. Applied C++ patch from Irfan Adilovic to guard 'using std::' directives
+with namespace pcrecpp (Bugzilla #2084).
+
+12. Remove a duplication typo in pcre_tables.c.
+
+13. Fix returned offsets from regexec() when REG_STARTEND is used with a
+starting offset greater than zero.
+
+
+Version 8.40 11-January-2017
+----------------------------
+
+1.  Using -o with -M in pcregrep could cause unnecessary repeated output when
+    the match extended over a line boundary.
+
+2.  Applied Chris Wilson's second patch (Bugzilla #1681) to CMakeLists.txt for
+    MSVC static compilation, putting the first patch under a new option.
+
+3.  Fix register overwite in JIT when SSE2 acceleration is enabled.
+
+4.  Ignore "show all captures" (/=) for DFA matching.
+
+5.  Fix JIT unaligned accesses on x86. Patch by Marc Mutz.
+
+6.  In any wide-character mode (8-bit UTF or any 16-bit or 32-bit mode),
+    without PCRE_UCP set, a negative character type such as \D in a positive
+    class should cause all characters greater than 255 to match, whatever else
+    is in the class. There was a bug that caused this not to happen if a
+    Unicode property item was added to such a class, for example [\D\P{Nd}] or
+    [\W\pL].
+
+7.  When pcretest was outputing information from a callout, the caret indicator
+    for the current position in the subject line was incorrect if it was after
+    an escape sequence for a character whose code point was greater than
+    \x{ff}.
+
+8.  A pattern such as (?<RA>abc)(?(R)xyz) was incorrectly compiled such that
+    the conditional was interpreted as a reference to capturing group 1 instead
+    of a test for recursion. Any group whose name began with R was
+    misinterpreted in this way. (The reference interpretation should only
+    happen if the group's name is precisely "R".)
+
+9.  A number of bugs have been mended relating to match start-up optimizations
+    when the first thing in a pattern is a positive lookahead. These all
+    applied only when PCRE_NO_START_OPTIMIZE was *not* set:
+
+    (a) A pattern such as (?=.*X)X$ was incorrectly optimized as if it needed
+        both an initial 'X' and a following 'X'.
+    (b) Some patterns starting with an assertion that started with .* were
+        incorrectly optimized as having to match at the start of the subject or
+        after a newline. There are cases where this is not true, for example,
+        (?=.*[A-Z])(?=.{8,16})(?!.*[\s]) matches after the start in lines that
+        start with spaces. Starting .* in an assertion is no longer taken as an
+        indication of matching at the start (or after a newline).
+
+
+Version 8.39 14-June-2016
+-------------------------
+
+1.  If PCRE_AUTO_CALLOUT was set on a pattern that had a (?# comment between
+    an item and its qualifier (for example, A(?#comment)?B) pcre_compile()
+    misbehaved. This bug was found by the LLVM fuzzer.
+
+2.  Similar to the above, if an isolated \E was present between an item and its
+    qualifier when PCRE_AUTO_CALLOUT was set, pcre_compile() misbehaved. This
+    bug was found by the LLVM fuzzer.
+
+3.  Further to 8.38/46, negated classes such as [^[:^ascii:]\d] were also not
+    working correctly in UCP mode.
+
+4.  The POSIX wrapper function regexec() crashed if the option REG_STARTEND
+    was set when the pmatch argument was NULL. It now returns REG_INVARG.
+
+5.  Allow for up to 32-bit numbers in the ordin() function in pcregrep.
+
+6.  An empty \Q\E sequence between an item and its qualifier caused
+    pcre_compile() to misbehave when auto callouts were enabled. This bug was
+    found by the LLVM fuzzer.
+
+7.  If a pattern that was compiled with PCRE_EXTENDED started with white
+    space or a #-type comment that was followed by (?-x), which turns off
+    PCRE_EXTENDED, and there was no subsequent (?x) to turn it on again,
+    pcre_compile() assumed that (?-x) applied to the whole pattern and
+    consequently mis-compiled it. This bug was found by the LLVM fuzzer.
+
+8.  A call of pcre_copy_named_substring() for a named substring whose number
+    was greater than the space in the ovector could cause a crash.
+
+9.  Yet another buffer overflow bug involved duplicate named groups with a
+    group that reset capture numbers (compare 8.38/7 below). Once again, I have
+    just allowed for more memory, even if not needed. (A proper fix is
+    implemented in PCRE2, but it involves a lot of refactoring.)
+
+10. pcre_get_substring_list() crashed if the use of \K in a match caused the
+    start of the match to be earlier than the end.
+
+11. Migrating appropriate PCRE2 JIT improvements to PCRE.
+
+12. A pattern such as /(?<=((?C)0))/, which has a callout inside a lookbehind
+    assertion, caused pcretest to generate incorrect output, and also to read
+    uninitialized memory (detected by ASAN or valgrind).
+
+13. A pattern that included (*ACCEPT) in the middle of a sufficiently deeply
+    nested set of parentheses of sufficient size caused an overflow of the
+    compiling workspace (which was diagnosed, but of course is not desirable).
+
+14. And yet another buffer overflow bug involving duplicate named groups, this
+    time nested, with a nested back reference. Yet again, I have just allowed
+    for more memory, because anything more needs all the refactoring that has
+    been done for PCRE2. An example pattern that provoked this bug is:
+    /((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/ and the bug was
+    registered as CVE-2016-1283.
+
+15. pcretest went into a loop if global matching was requested with an ovector
+    size less than 2. It now gives an error message. This bug was found by
+    afl-fuzz.
+
+16. An invalid pattern fragment such as (?(?C)0 was not diagnosing an error
+    ("assertion expected") when (?(?C) was not followed by an opening
+    parenthesis.
+
+17. Fixed typo ("&&" for "&") in pcre_study(). Fortunately, this could not
+    actually affect anything, by sheer luck.
+
+18. Applied Chris Wilson's patch (Bugzilla #1681) to CMakeLists.txt for MSVC
+    static compilation.
+
+19. Modified the RunTest script to incorporate a valgrind suppressions file so
+    that certain errors, provoked by the SSE2 instruction set when JIT is used,
+    are ignored.
+
+20. A racing condition is fixed in JIT reported by Mozilla.
+
+21. Minor code refactor to avoid "array subscript is below array bounds"
+    compiler warning.
+
+22. Minor code refactor to avoid "left shift of negative number" warning.
+
+23. Fix typo causing compile error when 16- or 32-bit JIT is compiled without
+    UCP support.
+
+24. Refactor to avoid compiler warnings in pcrecpp.cc.
+
+25. Refactor to fix a typo in pcre_jit_test.c
+
+26. Patch to support compiling pcrecpp.cc with Intel compiler.
+
+
 Version 8.38 23-November-2015
 -----------------------------
 
 1.  If a group that contained a recursive back reference also contained a
     forward reference subroutine call followed by a non-forward-reference
-    subroutine call, for example /.((?2)(?R)\1)()/, pcre2_compile() failed to
+    subroutine call, for example /.((?2)(?R)\1)()/, pcre_compile() failed to
     compile correct code, leading to undefined behaviour or an internally
     detected error. This bug was discovered by the LLVM fuzzer.
 
index 9f6f98e477f474520aad41ac52c54797ca614ad2..dd9071a8dd8192f7d734352e29b9395da2ded229 100644 (file)
@@ -25,7 +25,7 @@ Email domain:     cam.ac.uk
 University of Cambridge Computing Service,
 Cambridge, England.
 
-Copyright (c) 1997-2015 University of Cambridge
+Copyright (c) 1997-2017 University of Cambridge
 All rights reserved.
 
 
@@ -36,7 +36,7 @@ Written by:       Zoltan Herczeg
 Email local part: hzmester
 Emain domain:     freemail.hu
 
-Copyright(c) 2010-2015 Zoltan Herczeg
+Copyright(c) 2010-2017 Zoltan Herczeg
 All rights reserved.
 
 
@@ -47,7 +47,7 @@ Written by:       Zoltan Herczeg
 Email local part: hzmester
 Emain domain:     freemail.hu
 
-Copyright(c) 2009-2015 Zoltan Herczeg
+Copyright(c) 2009-2017 Zoltan Herczeg
 All rights reserved.
 
 
index 7e42dcb3603fa49c4f5b6a37f904e9a9c1e545ee..36be07cb8803147b2b427dd9d2e6c70e55607bda 100644 (file)
@@ -1,6 +1,27 @@
 News about PCRE releases
 ------------------------
 
+Release 8.41 13-June-2017
+-------------------------
+
+This is a bug-fix release.
+
+
+Release 8.40 11-January-2017
+----------------------------
+
+This is a bug-fix release.
+
+
+Release 8.39 14-June-2016
+-------------------------
+
+Some appropriate PCRE2 JIT improvements have been retro-fitted to PCRE1. Apart
+from that, this is another bug-fix release. Note that this library (now called
+PCRE1) is now being maintained for bug fixes only. New projects are advised to
+use the new PCRE2 libraries.
+
+
 Release 8.38 23-November-2015
 -----------------------------
 
index c0f3c865efd7a1a51b3fafed5c5f26a56dd8e981..4887ebf350e7e6f7881b54f0e1e0077d1091adda 100644 (file)
@@ -442,7 +442,7 @@ The "configure" script also creates config.status, which is an executable
 script that can be run to recreate the configuration, and config.log, which
 contains compiler output from tests that "configure" runs.
 
-Once "configure" has run, you can run "make". This builds the libraries
+Once "configure" has run, you can run "make". This builds the the libraries
 libpcre, libpcre16 and/or libpcre32, and a test program called pcretest. If you
 enabled JIT support with --enable-jit, a test program called pcre_jit_test is
 built as well.
index e3ed14819079ecfaf2319fa3a8f569e34fcda44d..844844023319dbf823ec78ca3a3e5f216a4bb06d 100644 (file)
@@ -316,7 +316,7 @@ them both to 0; an emulation function will be used. */
 #define PACKAGE_NAME "PCRE"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "PCRE 8.38"
+#define PACKAGE_STRING "PCRE 8.41"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "pcre"
@@ -325,7 +325,7 @@ them both to 0; an emulation function will be used. */
 #define PACKAGE_URL ""
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "8.38"
+#define PACKAGE_VERSION "8.41"
 
 /* to make a symbol visible */
 /* #undef PCRECPP_EXP_DECL */
@@ -439,11 +439,13 @@ them both to 0; an emulation function will be used. */
 /* #undef SUPPORT_UTF8 */
 
 /* Valgrind support to find invalid memory reads. */
-/* #undef SUPPORT_VALGRIND */
+#if HAVE_PCRE_VALGRIND_SUPPORT
+#define SUPPORT_VALGRIND 1
+#endif
 
 /* Version number of package */
 #ifndef VERSION
-#define VERSION "8.38"
+#define VERSION "8.41"
 #endif
 
 /* Define to empty if `const' does not conform to ANSI C. */
index 4ec32883cf0f12aafa6978f4c99a61fc47c6253d..1fdc8e0f23182e1573f1343edf3c8a1aec0b008d 100644 (file)
@@ -43,7 +43,9 @@ character tables for PCRE. The tables are built according to the current
 locale. Now that pcre_maketables is a function visible to the outside world, we
 make use of its code from here in order to be consistent. */
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include <ctype.h>
 #include <stdio.h>
index 76a47c79eff8dbbad644b033799858ca19d1b749..c027538f500bd74bab566178f92210868f84d7c3 100644 (file)
@@ -1814,84 +1814,83 @@ PCRE API OVERVIEW
        ments  that  have  limited stacks. Because of the greater use of memory
        management, it runs more slowly. Separate  functions  are  provided  so
        that  special-purpose  external  code  can  be used for this case. When
-       used, these functions are always called in a  stack-like  manner  (last
-       obtained,  first freed), and always for memory blocks of the same size.
-       There is a discussion about PCRE's stack usage in the  pcrestack  docu-
+       used, these functions always allocate memory blocks of the  same  size.
+       There  is  a discussion about PCRE's stack usage in the pcrestack docu-
        mentation.
 
        The global variable pcre_callout initially contains NULL. It can be set
-       by the caller to a "callout" function, which PCRE  will  then  call  at
-       specified  points during a matching operation. Details are given in the
+       by  the  caller  to  a "callout" function, which PCRE will then call at
+       specified points during a matching operation. Details are given in  the
        pcrecallout documentation.
 
        The global variable pcre_stack_guard initially contains NULL. It can be
-       set  by  the  caller  to  a function that is called by PCRE whenever it
-       starts to compile a parenthesized part of a pattern.  When  parentheses
+       set by the caller to a function that is  called  by  PCRE  whenever  it
+       starts  to  compile a parenthesized part of a pattern. When parentheses
        are nested, PCRE uses recursive function calls, which use up the system
-       stack. This function is provided so that applications  with  restricted
-       stacks  can  force a compilation error if the stack runs out. The func-
+       stack.  This  function is provided so that applications with restricted
+       stacks can force a compilation error if the stack runs out.  The  func-
        tion should return zero if all is well, or non-zero to force an error.
 
 
 NEWLINES
 
-       PCRE supports five different conventions for indicating line breaks  in
-       strings:  a  single  CR (carriage return) character, a single LF (line-
+       PCRE  supports five different conventions for indicating line breaks in
+       strings: a single CR (carriage return) character, a  single  LF  (line-
        feed) character, the two-character sequence CRLF, any of the three pre-
-       ceding,  or any Unicode newline sequence. The Unicode newline sequences
-       are the three just mentioned, plus the single characters  VT  (vertical
+       ceding, or any Unicode newline sequence. The Unicode newline  sequences
+       are  the  three just mentioned, plus the single characters VT (vertical
        tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line
        separator, U+2028), and PS (paragraph separator, U+2029).
 
-       Each of the first three conventions is used by at least  one  operating
-       system  as its standard newline sequence. When PCRE is built, a default
-       can be specified.  The default default is LF, which is the  Unix  stan-
-       dard.  When  PCRE  is run, the default can be overridden, either when a
+       Each  of  the first three conventions is used by at least one operating
+       system as its standard newline sequence. When PCRE is built, a  default
+       can  be  specified.  The default default is LF, which is the Unix stan-
+       dard. When PCRE is run, the default can be overridden,  either  when  a
        pattern is compiled, or when it is matched.
 
        At compile time, the newline convention can be specified by the options
-       argument  of  pcre_compile(), or it can be specified by special text at
+       argument of pcre_compile(), or it can be specified by special  text  at
        the start of the pattern itself; this overrides any other settings. See
        the pcrepattern page for details of the special character sequences.
 
        In the PCRE documentation the word "newline" is used to mean "the char-
-       acter or pair of characters that indicate a line break". The choice  of
-       newline  convention  affects  the  handling of the dot, circumflex, and
+       acter  or pair of characters that indicate a line break". The choice of
+       newline convention affects the handling of  the  dot,  circumflex,  and
        dollar metacharacters, the handling of #-comments in /x mode, and, when
-       CRLF  is a recognized line ending sequence, the match position advance-
+       CRLF is a recognized line ending sequence, the match position  advance-
        ment for a non-anchored pattern. There is more detail about this in the
        section on pcre_exec() options below.
 
-       The  choice of newline convention does not affect the interpretation of
-       the \n or \r escape sequences, nor does  it  affect  what  \R  matches,
+       The choice of newline convention does not affect the interpretation  of
+       the  \n  or  \r  escape  sequences, nor does it affect what \R matches,
        which is controlled in a similar way, but by separate options.
 
 
 MULTITHREADING
 
-       The  PCRE  functions  can be used in multi-threading applications, with
+       The PCRE functions can be used in  multi-threading  applications,  with
        the  proviso  that  the  memory  management  functions  pointed  to  by
        pcre_malloc, pcre_free, pcre_stack_malloc, and pcre_stack_free, and the
-       callout and stack-checking functions pointed  to  by  pcre_callout  and
+       callout  and  stack-checking  functions  pointed to by pcre_callout and
        pcre_stack_guard, are shared by all threads.
 
-       The  compiled form of a regular expression is not altered during match-
+       The compiled form of a regular expression is not altered during  match-
        ing, so the same compiled pattern can safely be used by several threads
        at once.
 
-       If  the just-in-time optimization feature is being used, it needs sepa-
-       rate memory stack areas for each thread. See the pcrejit  documentation
+       If the just-in-time optimization feature is being used, it needs  sepa-
+       rate  memory stack areas for each thread. See the pcrejit documentation
        for more details.
 
 
 SAVING PRECOMPILED PATTERNS FOR LATER USE
 
        The compiled form of a regular expression can be saved and re-used at a
-       later time, possibly by a different program, and even on a  host  other
-       than  the  one  on  which  it  was  compiled.  Details are given in the
-       pcreprecompile documentation,  which  includes  a  description  of  the
-       pcre_pattern_to_host_byte_order()  function. However, compiling a regu-
-       lar expression with one version of PCRE for use with a  different  ver-
+       later  time,  possibly by a different program, and even on a host other
+       than the one on which  it  was  compiled.  Details  are  given  in  the
+       pcreprecompile  documentation,  which  includes  a  description  of the
+       pcre_pattern_to_host_byte_order() function. However, compiling a  regu-
+       lar  expression  with one version of PCRE for use with a different ver-
        sion is not guaranteed to work and may cause crashes.
 
 
@@ -1899,45 +1898,45 @@ CHECKING BUILD-TIME OPTIONS
 
        int pcre_config(int what, void *where);
 
-       The  function pcre_config() makes it possible for a PCRE client to dis-
+       The function pcre_config() makes it possible for a PCRE client to  dis-
        cover which optional features have been compiled into the PCRE library.
-       The  pcrebuild documentation has more details about these optional fea-
+       The pcrebuild documentation has more details about these optional  fea-
        tures.
 
-       The first argument for pcre_config() is an  integer,  specifying  which
+       The  first  argument  for pcre_config() is an integer, specifying which
        information is required; the second argument is a pointer to a variable
-       into which the information is placed. The returned  value  is  zero  on
-       success,  or  the negative error code PCRE_ERROR_BADOPTION if the value
-       in the first argument is not recognized. The following  information  is
+       into  which  the  information  is placed. The returned value is zero on
+       success, or the negative error code PCRE_ERROR_BADOPTION if  the  value
+       in  the  first argument is not recognized. The following information is
        available:
 
          PCRE_CONFIG_UTF8
 
-       The  output is an integer that is set to one if UTF-8 support is avail-
-       able; otherwise it is set to zero. This value should normally be  given
+       The output is an integer that is set to one if UTF-8 support is  avail-
+       able;  otherwise it is set to zero. This value should normally be given
        to the 8-bit version of this function, pcre_config(). If it is given to
-       the  16-bit  or  32-bit  version  of  this  function,  the  result   is
+       the   16-bit  or  32-bit  version  of  this  function,  the  result  is
        PCRE_ERROR_BADOPTION.
 
          PCRE_CONFIG_UTF16
 
        The output is an integer that is set to one if UTF-16 support is avail-
-       able; otherwise it is set to zero. This value should normally be  given
+       able;  otherwise it is set to zero. This value should normally be given
        to the 16-bit version of this function, pcre16_config(). If it is given
-       to the 8-bit  or  32-bit  version  of  this  function,  the  result  is
+       to  the  8-bit  or  32-bit  version  of  this  function,  the result is
        PCRE_ERROR_BADOPTION.
 
          PCRE_CONFIG_UTF32
 
        The output is an integer that is set to one if UTF-32 support is avail-
-       able; otherwise it is set to zero. This value should normally be  given
+       able;  otherwise it is set to zero. This value should normally be given
        to the 32-bit version of this function, pcre32_config(). If it is given
-       to the 8-bit  or  16-bit  version  of  this  function,  the  result  is
+       to  the  8-bit  or  16-bit  version  of  this  function,  the result is
        PCRE_ERROR_BADOPTION.
 
          PCRE_CONFIG_UNICODE_PROPERTIES
 
-       The  output  is  an  integer  that is set to one if support for Unicode
+       The output is an integer that is set to  one  if  support  for  Unicode
        character properties is available; otherwise it is set to zero.
 
          PCRE_CONFIG_JIT
@@ -1947,80 +1946,80 @@ CHECKING BUILD-TIME OPTIONS
 
          PCRE_CONFIG_JITTARGET
 
-       The  output is a pointer to a zero-terminated "const char *" string. If
+       The output is a pointer to a zero-terminated "const char *" string.  If
        JIT support is available, the string contains the name of the architec-
-       ture  for  which the JIT compiler is configured, for example "x86 32bit
-       (little endian + unaligned)". If JIT  support  is  not  available,  the
+       ture for which the JIT compiler is configured, for example  "x86  32bit
+       (little  endian  +  unaligned)".  If  JIT support is not available, the
        result is NULL.
 
          PCRE_CONFIG_NEWLINE
 
-       The  output  is  an integer whose value specifies the default character
-       sequence that is recognized as meaning "newline". The values  that  are
+       The output is an integer whose value specifies  the  default  character
+       sequence  that  is recognized as meaning "newline". The values that are
        supported in ASCII/Unicode environments are: 10 for LF, 13 for CR, 3338
-       for CRLF, -2 for ANYCRLF, and -1 for ANY. In EBCDIC  environments,  CR,
-       ANYCRLF,  and  ANY  yield the same values. However, the value for LF is
-       normally 21, though some EBCDIC environments use 37. The  corresponding
-       values  for  CRLF are 3349 and 3365. The default should normally corre-
+       for  CRLF,  -2 for ANYCRLF, and -1 for ANY. In EBCDIC environments, CR,
+       ANYCRLF, and ANY yield the same values. However, the value  for  LF  is
+       normally  21, though some EBCDIC environments use 37. The corresponding
+       values for CRLF are 3349 and 3365. The default should  normally  corre-
        spond to the standard sequence for your operating system.
 
          PCRE_CONFIG_BSR
 
        The output is an integer whose value indicates what character sequences
-       the  \R  escape sequence matches by default. A value of 0 means that \R
-       matches any Unicode line ending sequence; a value of 1  means  that  \R
+       the \R escape sequence matches by default. A value of 0 means  that  \R
+       matches  any  Unicode  line ending sequence; a value of 1 means that \R
        matches only CR, LF, or CRLF. The default can be overridden when a pat-
        tern is compiled or matched.
 
          PCRE_CONFIG_LINK_SIZE
 
-       The output is an integer that contains the number  of  bytes  used  for
+       The  output  is  an  integer that contains the number of bytes used for
        internal  linkage  in  compiled  regular  expressions.  For  the  8-bit
        library, the value can be 2, 3, or 4. For the 16-bit library, the value
-       is  either  2  or  4  and  is  still  a number of bytes. For the 32-bit
+       is either 2 or 4 and is  still  a  number  of  bytes.  For  the  32-bit
        library, the value is either 2 or 4 and is still a number of bytes. The
        default value of 2 is sufficient for all but the most massive patterns,
-       since it allows the compiled pattern to be up to 64K  in  size.  Larger
-       values  allow larger regular expressions to be compiled, at the expense
+       since  it  allows  the compiled pattern to be up to 64K in size. Larger
+       values allow larger regular expressions to be compiled, at the  expense
        of slower matching.
 
          PCRE_CONFIG_POSIX_MALLOC_THRESHOLD
 
-       The output is an integer that contains the threshold  above  which  the
-       POSIX  interface  uses malloc() for output vectors. Further details are
+       The  output  is  an integer that contains the threshold above which the
+       POSIX interface uses malloc() for output vectors. Further  details  are
        given in the pcreposix documentation.
 
          PCRE_CONFIG_PARENS_LIMIT
 
        The output is a long integer that gives the maximum depth of nesting of
-       parentheses  (of  any  kind) in a pattern. This limit is imposed to cap
+       parentheses (of any kind) in a pattern. This limit is  imposed  to  cap
        the amount of system stack used when a pattern is compiled. It is spec-
-       ified  when PCRE is built; the default is 250. This limit does not take
+       ified when PCRE is built; the default is 250. This limit does not  take
        into account the stack that may already be used by the calling applica-
-       tion.  For  finer  control  over compilation stack usage, you can set a
+       tion. For finer control over compilation stack usage,  you  can  set  a
        pointer to an external checking function in pcre_stack_guard.
 
          PCRE_CONFIG_MATCH_LIMIT
 
-       The output is a long integer that gives the default limit for the  num-
-       ber  of  internal  matching  function calls in a pcre_exec() execution.
+       The  output is a long integer that gives the default limit for the num-
+       ber of internal matching function calls  in  a  pcre_exec()  execution.
        Further details are given with pcre_exec() below.
 
          PCRE_CONFIG_MATCH_LIMIT_RECURSION
 
        The output is a long integer that gives the default limit for the depth
-       of   recursion  when  calling  the  internal  matching  function  in  a
-       pcre_exec() execution.  Further  details  are  given  with  pcre_exec()
+       of  recursion  when  calling  the  internal  matching  function  in   a
+       pcre_exec()  execution.  Further  details  are  given  with pcre_exec()
        below.
 
          PCRE_CONFIG_STACKRECURSE
 
-       The  output is an integer that is set to one if internal recursion when
+       The output is an integer that is set to one if internal recursion  when
        running pcre_exec() is implemented by recursive function calls that use
-       the  stack  to remember their state. This is the usual way that PCRE is
+       the stack to remember their state. This is the usual way that  PCRE  is
        compiled. The output is zero if PCRE was compiled to use blocks of data
-       on  the  heap  instead  of  recursive  function  calls.  In  this case,
-       pcre_stack_malloc and  pcre_stack_free  are  called  to  manage  memory
+       on the  heap  instead  of  recursive  function  calls.  In  this  case,
+       pcre_stack_malloc  and  pcre_stack_free  are  called  to  manage memory
        blocks on the heap, thus avoiding the use of the stack.
 
 
@@ -2037,67 +2036,67 @@ COMPILING A PATTERN
 
        Either of the functions pcre_compile() or pcre_compile2() can be called
        to compile a pattern into an internal form. The only difference between
-       the  two interfaces is that pcre_compile2() has an additional argument,
-       errorcodeptr, via which a numerical error  code  can  be  returned.  To
-       avoid  too  much repetition, we refer just to pcre_compile() below, but
+       the two interfaces is that pcre_compile2() has an additional  argument,
+       errorcodeptr,  via  which  a  numerical  error code can be returned. To
+       avoid too much repetition, we refer just to pcre_compile()  below,  but
        the information applies equally to pcre_compile2().
 
        The pattern is a C string terminated by a binary zero, and is passed in
-       the  pattern  argument.  A  pointer to a single block of memory that is
-       obtained via pcre_malloc is returned. This contains the  compiled  code
+       the pattern argument. A pointer to a single block  of  memory  that  is
+       obtained  via  pcre_malloc is returned. This contains the compiled code
        and related data. The pcre type is defined for the returned block; this
        is a typedef for a structure whose contents are not externally defined.
        It is up to the caller to free the memory (via pcre_free) when it is no
        longer required.
 
-       Although the compiled code of a PCRE regex is relocatable, that is,  it
+       Although  the compiled code of a PCRE regex is relocatable, that is, it
        does not depend on memory location, the complete pcre data block is not
-       fully relocatable, because it may contain a copy of the tableptr  argu-
+       fully  relocatable, because it may contain a copy of the tableptr argu-
        ment, which is an address (see below).
 
        The options argument contains various bit settings that affect the com-
-       pilation. It should be zero if no options are required.  The  available
-       options  are  described  below. Some of them (in particular, those that
-       are compatible with Perl, but some others as well) can also be set  and
-       unset  from  within  the  pattern  (see the detailed description in the
-       pcrepattern documentation). For those options that can be different  in
-       different  parts  of  the pattern, the contents of the options argument
+       pilation.  It  should be zero if no options are required. The available
+       options are described below. Some of them (in  particular,  those  that
+       are  compatible with Perl, but some others as well) can also be set and
+       unset from within the pattern (see  the  detailed  description  in  the
+       pcrepattern  documentation). For those options that can be different in
+       different parts of the pattern, the contents of  the  options  argument
        specifies their settings at the start of compilation and execution. The
-       PCRE_ANCHORED,  PCRE_BSR_xxx, PCRE_NEWLINE_xxx, PCRE_NO_UTF8_CHECK, and
-       PCRE_NO_START_OPTIMIZE options can be set at the time  of  matching  as
+       PCRE_ANCHORED, PCRE_BSR_xxx, PCRE_NEWLINE_xxx, PCRE_NO_UTF8_CHECK,  and
+       PCRE_NO_START_OPTIMIZE  options  can  be set at the time of matching as
        well as at compile time.
 
        If errptr is NULL, pcre_compile() returns NULL immediately.  Otherwise,
-       if compilation of a pattern fails,  pcre_compile()  returns  NULL,  and
+       if  compilation  of  a  pattern fails, pcre_compile() returns NULL, and
        sets the variable pointed to by errptr to point to a textual error mes-
        sage. This is a static string that is part of the library. You must not
-       try  to  free it. Normally, the offset from the start of the pattern to
+       try to free it. Normally, the offset from the start of the  pattern  to
        the data unit that was being processed when the error was discovered is
-       placed  in the variable pointed to by erroffset, which must not be NULL
-       (if it is, an immediate error is given). However, for an invalid  UTF-8
-       or  UTF-16  string,  the  offset  is that of the first data unit of the
+       placed in the variable pointed to by erroffset, which must not be  NULL
+       (if  it is, an immediate error is given). However, for an invalid UTF-8
+       or UTF-16 string, the offset is that of the  first  data  unit  of  the
        failing character.
 
-       Some errors are not detected until the whole pattern has been  scanned;
-       in  these  cases,  the offset passed back is the length of the pattern.
-       Note that the offset is in data units, not characters, even  in  a  UTF
+       Some  errors are not detected until the whole pattern has been scanned;
+       in these cases, the offset passed back is the length  of  the  pattern.
+       Note  that  the  offset is in data units, not characters, even in a UTF
        mode. It may sometimes point into the middle of a UTF-8 or UTF-16 char-
        acter.
 
-       If pcre_compile2() is used instead of pcre_compile(),  and  the  error-
-       codeptr  argument is not NULL, a non-zero error code number is returned
-       via this argument in the event of an error. This is in addition to  the
+       If  pcre_compile2()  is  used instead of pcre_compile(), and the error-
+       codeptr argument is not NULL, a non-zero error code number is  returned
+       via  this argument in the event of an error. This is in addition to the
        textual error message. Error codes and messages are listed below.
 
-       If  the  final  argument, tableptr, is NULL, PCRE uses a default set of
-       character tables that are  built  when  PCRE  is  compiled,  using  the
-       default  C  locale.  Otherwise, tableptr must be an address that is the
-       result of a call to pcre_maketables(). This value is  stored  with  the
-       compiled  pattern,  and  used  again by pcre_exec() and pcre_dfa_exec()
-       when the pattern is matched. For more discussion, see  the  section  on
+       If the final argument, tableptr, is NULL, PCRE uses a  default  set  of
+       character  tables  that  are  built  when  PCRE  is compiled, using the
+       default C locale. Otherwise, tableptr must be an address  that  is  the
+       result  of  a  call to pcre_maketables(). This value is stored with the
+       compiled pattern, and used again  by  pcre_exec()  and  pcre_dfa_exec()
+       when  the  pattern  is matched. For more discussion, see the section on
        locale support below.
 
-       This  code  fragment  shows a typical straightforward call to pcre_com-
+       This code fragment shows a typical straightforward  call  to  pcre_com-
        pile():
 
          pcre *re;
@@ -2110,181 +2109,181 @@ COMPILING A PATTERN
            &erroffset,       /* for error offset */
            NULL);            /* use default character tables */
 
-       The following names for option bits are defined in  the  pcre.h  header
+       The  following  names  for option bits are defined in the pcre.h header
        file:
 
          PCRE_ANCHORED
 
        If this bit is set, the pattern is forced to be "anchored", that is, it
-       is constrained to match only at the first matching point in the  string
-       that  is being searched (the "subject string"). This effect can also be
-       achieved by appropriate constructs in the pattern itself, which is  the
+       is  constrained to match only at the first matching point in the string
+       that is being searched (the "subject string"). This effect can also  be
+       achieved  by appropriate constructs in the pattern itself, which is the
        only way to do it in Perl.
 
          PCRE_AUTO_CALLOUT
 
        If this bit is set, pcre_compile() automatically inserts callout items,
-       all with number 255, before each pattern item. For  discussion  of  the
+       all  with  number  255, before each pattern item. For discussion of the
        callout facility, see the pcrecallout documentation.
 
          PCRE_BSR_ANYCRLF
          PCRE_BSR_UNICODE
 
        These options (which are mutually exclusive) control what the \R escape
-       sequence matches. The choice is either to match only CR, LF,  or  CRLF,
+       sequence  matches.  The choice is either to match only CR, LF, or CRLF,
        or to match any Unicode newline sequence. The default is specified when
        PCRE is built. It can be overridden from within the pattern, or by set-
        ting an option when a compiled pattern is matched.
 
          PCRE_CASELESS
 
-       If  this  bit is set, letters in the pattern match both upper and lower
-       case letters. It is equivalent to Perl's  /i  option,  and  it  can  be
-       changed  within a pattern by a (?i) option setting. In UTF-8 mode, PCRE
-       always understands the concept of case for characters whose values  are
-       less  than 128, so caseless matching is always possible. For characters
-       with higher values, the concept of case is supported if  PCRE  is  com-
-       piled  with Unicode property support, but not otherwise. If you want to
-       use caseless matching for characters 128 and  above,  you  must  ensure
-       that  PCRE  is  compiled  with Unicode property support as well as with
+       If this bit is set, letters in the pattern match both upper  and  lower
+       case  letters.  It  is  equivalent  to  Perl's /i option, and it can be
+       changed within a pattern by a (?i) option setting. In UTF-8 mode,  PCRE
+       always  understands the concept of case for characters whose values are
+       less than 128, so caseless matching is always possible. For  characters
+       with  higher  values,  the concept of case is supported if PCRE is com-
+       piled with Unicode property support, but not otherwise. If you want  to
+       use  caseless  matching  for  characters 128 and above, you must ensure
+       that PCRE is compiled with Unicode property support  as  well  as  with
        UTF-8 support.
 
          PCRE_DOLLAR_ENDONLY
 
-       If this bit is set, a dollar metacharacter in the pattern matches  only
-       at  the  end  of the subject string. Without this option, a dollar also
-       matches immediately before a newline at the end of the string (but  not
-       before  any  other newlines). The PCRE_DOLLAR_ENDONLY option is ignored
-       if PCRE_MULTILINE is set.  There is no equivalent  to  this  option  in
+       If  this bit is set, a dollar metacharacter in the pattern matches only
+       at the end of the subject string. Without this option,  a  dollar  also
+       matches  immediately before a newline at the end of the string (but not
+       before any other newlines). The PCRE_DOLLAR_ENDONLY option  is  ignored
+       if  PCRE_MULTILINE  is  set.   There is no equivalent to this option in
        Perl, and no way to set it within a pattern.
 
          PCRE_DOTALL
 
-       If  this bit is set, a dot metacharacter in the pattern matches a char-
+       If this bit is set, a dot metacharacter in the pattern matches a  char-
        acter of any value, including one that indicates a newline. However, it
-       only  ever  matches  one character, even if newlines are coded as CRLF.
-       Without this option, a dot does not match when the current position  is
+       only ever matches one character, even if newlines are  coded  as  CRLF.
+       Without  this option, a dot does not match when the current position is
        at a newline. This option is equivalent to Perl's /s option, and it can
-       be changed within a pattern by a (?s) option setting. A negative  class
+       be  changed within a pattern by a (?s) option setting. A negative class
        such as [^a] always matches newline characters, independent of the set-
        ting of this option.
 
          PCRE_DUPNAMES
 
-       If this bit is set, names used to identify capturing  subpatterns  need
+       If  this  bit is set, names used to identify capturing subpatterns need
        not be unique. This can be helpful for certain types of pattern when it
-       is known that only one instance of the named  subpattern  can  ever  be
-       matched.  There  are  more details of named subpatterns below; see also
+       is  known  that  only  one instance of the named subpattern can ever be
+       matched. There are more details of named subpatterns  below;  see  also
        the pcrepattern documentation.
 
          PCRE_EXTENDED
 
-       If this bit is set, most white space  characters  in  the  pattern  are
-       totally  ignored  except when escaped or inside a character class. How-
-       ever, white space is not allowed within  sequences  such  as  (?>  that
-       introduce  various  parenthesized  subpatterns,  nor within a numerical
-       quantifier such as {1,3}.  However, ignorable white space is  permitted
+       If  this  bit  is  set,  most white space characters in the pattern are
+       totally ignored except when escaped or inside a character  class.  How-
+       ever,  white  space  is  not  allowed within sequences such as (?> that
+       introduce various parenthesized subpatterns,  nor  within  a  numerical
+       quantifier  such as {1,3}.  However, ignorable white space is permitted
        between an item and a following quantifier and between a quantifier and
        a following + that indicates possessiveness.
 
        White space did not used to include the VT character (code 11), because
        Perl did not treat this character as white space. However, Perl changed
-       at release 5.18, so PCRE followed  at  release  8.34,  and  VT  is  now
+       at  release  5.18,  so  PCRE  followed  at  release 8.34, and VT is now
        treated as white space.
 
-       PCRE_EXTENDED  also  causes characters between an unescaped # outside a
-       character class  and  the  next  newline,  inclusive,  to  be  ignored.
-       PCRE_EXTENDED  is equivalent to Perl's /x option, and it can be changed
+       PCRE_EXTENDED also causes characters between an unescaped #  outside  a
+       character  class  and  the  next  newline,  inclusive,  to  be ignored.
+       PCRE_EXTENDED is equivalent to Perl's /x option, and it can be  changed
        within a pattern by a (?x) option setting.
 
-       Which characters are interpreted  as  newlines  is  controlled  by  the
-       options  passed to pcre_compile() or by a special sequence at the start
-       of the pattern, as described in the section entitled  "Newline  conven-
+       Which  characters  are  interpreted  as  newlines  is controlled by the
+       options passed to pcre_compile() or by a special sequence at the  start
+       of  the  pattern, as described in the section entitled "Newline conven-
        tions" in the pcrepattern documentation. Note that the end of this type
-       of comment is  a  literal  newline  sequence  in  the  pattern;  escape
+       of  comment  is  a  literal  newline  sequence  in  the pattern; escape
        sequences that happen to represent a newline do not count.
 
-       This  option  makes  it possible to include comments inside complicated
-       patterns.  Note, however, that this applies only  to  data  characters.
-       White  space  characters  may  never  appear  within  special character
+       This option makes it possible to include  comments  inside  complicated
+       patterns.   Note,  however,  that this applies only to data characters.
+       White space  characters  may  never  appear  within  special  character
        sequences in a pattern, for example within the sequence (?( that intro-
        duces a conditional subpattern.
 
          PCRE_EXTRA
 
-       This  option  was invented in order to turn on additional functionality
-       of PCRE that is incompatible with Perl, but it  is  currently  of  very
-       little  use. When set, any backslash in a pattern that is followed by a
-       letter that has no special meaning  causes  an  error,  thus  reserving
-       these  combinations  for  future  expansion.  By default, as in Perl, a
-       backslash followed by a letter with no special meaning is treated as  a
+       This option was invented in order to turn on  additional  functionality
+       of  PCRE  that  is  incompatible with Perl, but it is currently of very
+       little use. When set, any backslash in a pattern that is followed by  a
+       letter  that  has  no  special  meaning causes an error, thus reserving
+       these combinations for future expansion. By  default,  as  in  Perl,  a
+       backslash  followed by a letter with no special meaning is treated as a
        literal. (Perl can, however, be persuaded to give an error for this, by
-       running it with the -w option.) There are at present no other  features
-       controlled  by this option. It can also be set by a (?X) option setting
+       running  it with the -w option.) There are at present no other features
+       controlled by this option. It can also be set by a (?X) option  setting
        within a pattern.
 
          PCRE_FIRSTLINE
 
-       If this option is set, an  unanchored  pattern  is  required  to  match
-       before  or  at  the  first  newline  in  the subject string, though the
+       If  this  option  is  set,  an  unanchored pattern is required to match
+       before or at the first  newline  in  the  subject  string,  though  the
        matched text may continue over the newline.
 
          PCRE_JAVASCRIPT_COMPAT
 
        If this option is set, PCRE's behaviour is changed in some ways so that
-       it  is  compatible with JavaScript rather than Perl. The changes are as
+       it is compatible with JavaScript rather than Perl. The changes  are  as
        follows:
 
-       (1) A lone closing square bracket in a pattern  causes  a  compile-time
-       error,  because this is illegal in JavaScript (by default it is treated
+       (1)  A  lone  closing square bracket in a pattern causes a compile-time
+       error, because this is illegal in JavaScript (by default it is  treated
        as a data character). Thus, the pattern AB]CD becomes illegal when this
        option is set.
 
-       (2)  At run time, a back reference to an unset subpattern group matches
-       an empty string (by default this causes the current  matching  alterna-
-       tive  to  fail). A pattern such as (\1)(a) succeeds when this option is
-       set (assuming it can find an "a" in the subject), whereas it  fails  by
+       (2) At run time, a back reference to an unset subpattern group  matches
+       an  empty  string (by default this causes the current matching alterna-
+       tive to fail). A pattern such as (\1)(a) succeeds when this  option  is
+       set  (assuming  it can find an "a" in the subject), whereas it fails by
        default, for Perl compatibility.
 
        (3) \U matches an upper case "U" character; by default \U causes a com-
        pile time error (Perl uses \U to upper case subsequent characters).
 
        (4) \u matches a lower case "u" character unless it is followed by four
-       hexadecimal  digits,  in  which case the hexadecimal number defines the
-       code point to match. By default, \u causes a compile time  error  (Perl
+       hexadecimal digits, in which case the hexadecimal  number  defines  the
+       code  point  to match. By default, \u causes a compile time error (Perl
        uses it to upper case the following character).
 
-       (5)  \x matches a lower case "x" character unless it is followed by two
-       hexadecimal digits, in which case the hexadecimal  number  defines  the
-       code  point  to  match. By default, as in Perl, a hexadecimal number is
+       (5) \x matches a lower case "x" character unless it is followed by  two
+       hexadecimal  digits,  in  which case the hexadecimal number defines the
+       code point to match. By default, as in Perl, a  hexadecimal  number  is
        always expected after \x, but it may have zero, one, or two digits (so,
        for example, \xz matches a binary zero character followed by z).
 
          PCRE_MULTILINE
 
-       By  default,  for  the purposes of matching "start of line" and "end of
+       By default, for the purposes of matching "start of line"  and  "end  of
        line", PCRE treats the subject string as consisting of a single line of
-       characters,  even if it actually contains newlines. The "start of line"
+       characters, even if it actually contains newlines. The "start of  line"
        metacharacter (^) matches only at the start of the string, and the "end
-       of  line"  metacharacter  ($) matches only at the end of the string, or
-       before a terminating newline (except when PCRE_DOLLAR_ENDONLY is  set).
-       Note,  however,  that  unless  PCRE_DOTALL  is set, the "any character"
-       metacharacter (.) does not match at a newline. This behaviour  (for  ^,
+       of line" metacharacter ($) matches only at the end of  the  string,  or
+       before  a terminating newline (except when PCRE_DOLLAR_ENDONLY is set).
+       Note, however, that unless PCRE_DOTALL  is  set,  the  "any  character"
+       metacharacter  (.)  does not match at a newline. This behaviour (for ^,
        $, and dot) is the same as Perl.
 
-       When  PCRE_MULTILINE  it  is set, the "start of line" and "end of line"
-       constructs match immediately following or immediately  before  internal
-       newlines  in  the  subject string, respectively, as well as at the very
-       start and end. This is equivalent to Perl's /m option, and  it  can  be
+       When PCRE_MULTILINE it is set, the "start of line" and  "end  of  line"
+       constructs  match  immediately following or immediately before internal
+       newlines in the subject string, respectively, as well as  at  the  very
+       start  and  end.  This is equivalent to Perl's /m option, and it can be
        changed within a pattern by a (?m) option setting. If there are no new-
-       lines in a subject string, or no occurrences of ^ or $  in  a  pattern,
+       lines  in  a  subject string, or no occurrences of ^ or $ in a pattern,
        setting PCRE_MULTILINE has no effect.
 
          PCRE_NEVER_UTF
 
        This option locks out interpretation of the pattern as UTF-8 (or UTF-16
-       or UTF-32 in the 16-bit and 32-bit libraries). In particular,  it  pre-
-       vents  the  creator of the pattern from switching to UTF interpretation
+       or  UTF-32  in the 16-bit and 32-bit libraries). In particular, it pre-
+       vents the creator of the pattern from switching to  UTF  interpretation
        by starting the pattern with (*UTF). This may be useful in applications
        that  process  patterns  from  external  sources.  The  combination  of
        PCRE_UTF8 and PCRE_NEVER_UTF also causes an error.
@@ -2295,41 +2294,41 @@ COMPILING A PATTERN
          PCRE_NEWLINE_ANYCRLF
          PCRE_NEWLINE_ANY
 
-       These options override the default newline definition that  was  chosen
-       when  PCRE  was built. Setting the first or the second specifies that a
-       newline is indicated by a single character (CR  or  LF,  respectively).
-       Setting  PCRE_NEWLINE_CRLF specifies that a newline is indicated by the
-       two-character CRLF  sequence.  Setting  PCRE_NEWLINE_ANYCRLF  specifies
+       These  options  override the default newline definition that was chosen
+       when PCRE was built. Setting the first or the second specifies  that  a
+       newline  is  indicated  by a single character (CR or LF, respectively).
+       Setting PCRE_NEWLINE_CRLF specifies that a newline is indicated by  the
+       two-character  CRLF  sequence.  Setting  PCRE_NEWLINE_ANYCRLF specifies
        that any of the three preceding sequences should be recognized. Setting
-       PCRE_NEWLINE_ANY specifies that any Unicode newline sequence should  be
+       PCRE_NEWLINE_ANY  specifies that any Unicode newline sequence should be
        recognized.
 
-       In  an ASCII/Unicode environment, the Unicode newline sequences are the
-       three just mentioned, plus the  single  characters  VT  (vertical  tab,
+       In an ASCII/Unicode environment, the Unicode newline sequences are  the
+       three  just  mentioned,  plus  the  single characters VT (vertical tab,
        U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line sep-
-       arator, U+2028), and PS (paragraph separator, U+2029).  For  the  8-bit
+       arator,  U+2028),  and  PS (paragraph separator, U+2029). For the 8-bit
        library, the last two are recognized only in UTF-8 mode.
 
-       When  PCRE is compiled to run in an EBCDIC (mainframe) environment, the
+       When PCRE is compiled to run in an EBCDIC (mainframe) environment,  the
        code for CR is 0x0d, the same as ASCII. However, the character code for
-       LF  is  normally 0x15, though in some EBCDIC environments 0x25 is used.
-       Whichever of these is not LF is made to  correspond  to  Unicode's  NEL
-       character.  EBCDIC  codes  are all less than 256. For more details, see
+       LF is normally 0x15, though in some EBCDIC environments 0x25  is  used.
+       Whichever  of  these  is  not LF is made to correspond to Unicode's NEL
+       character. EBCDIC codes are all less than 256. For  more  details,  see
        the pcrebuild documentation.
 
-       The newline setting in the  options  word  uses  three  bits  that  are
+       The  newline  setting  in  the  options  word  uses three bits that are
        treated as a number, giving eight possibilities. Currently only six are
-       used (default plus the five values above). This means that if  you  set
-       more  than one newline option, the combination may or may not be sensi-
+       used  (default  plus the five values above). This means that if you set
+       more than one newline option, the combination may or may not be  sensi-
        ble. For example, PCRE_NEWLINE_CR with PCRE_NEWLINE_LF is equivalent to
-       PCRE_NEWLINE_CRLF,  but other combinations may yield unused numbers and
+       PCRE_NEWLINE_CRLF, but other combinations may yield unused numbers  and
        cause an error.
 
-       The only time that a line break in a pattern  is  specially  recognized
-       when  compiling is when PCRE_EXTENDED is set. CR and LF are white space
-       characters, and so are ignored in this mode. Also, an unescaped #  out-
-       side  a  character class indicates a comment that lasts until after the
-       next line break sequence. In other circumstances, line break  sequences
+       The  only  time  that a line break in a pattern is specially recognized
+       when compiling is when PCRE_EXTENDED is set. CR and LF are white  space
+       characters,  and so are ignored in this mode. Also, an unescaped # out-
+       side a character class indicates a comment that lasts until  after  the
+       next  line break sequence. In other circumstances, line break sequences
        in patterns are treated as literal data.
 
        The newline option that is set at compile time becomes the default that
@@ -2338,79 +2337,79 @@ COMPILING A PATTERN
          PCRE_NO_AUTO_CAPTURE
 
        If this option is set, it disables the use of numbered capturing paren-
-       theses  in the pattern. Any opening parenthesis that is not followed by
-       ? behaves as if it were followed by ?: but named parentheses can  still
-       be  used  for  capturing  (and  they acquire numbers in the usual way).
+       theses in the pattern. Any opening parenthesis that is not followed  by
+       ?  behaves as if it were followed by ?: but named parentheses can still
+       be used for capturing (and they acquire  numbers  in  the  usual  way).
        There is no equivalent of this option in Perl.
 
          PCRE_NO_AUTO_POSSESS
 
-       If this option is set, it disables "auto-possessification". This is  an
-       optimization  that,  for example, turns a+b into a++b in order to avoid
-       backtracks into a+ that can never be successful. However,  if  callouts
-       are  in  use,  auto-possessification  means that some of them are never
+       If  this option is set, it disables "auto-possessification". This is an
+       optimization that, for example, turns a+b into a++b in order  to  avoid
+       backtracks  into  a+ that can never be successful. However, if callouts
+       are in use, auto-possessification means that some  of  them  are  never
        taken. You can set this option if you want the matching functions to do
-       a  full  unoptimized  search and run all the callouts, but it is mainly
+       a full unoptimized search and run all the callouts, but  it  is  mainly
        provided for testing purposes.
 
          PCRE_NO_START_OPTIMIZE
 
-       This is an option that acts at matching time; that is, it is really  an
-       option  for  pcre_exec()  or  pcre_dfa_exec().  If it is set at compile
-       time, it is remembered with the compiled pattern and assumed at  match-
-       ing  time.  This is necessary if you want to use JIT execution, because
-       the JIT compiler needs to know whether or not this option is  set.  For
+       This  is an option that acts at matching time; that is, it is really an
+       option for pcre_exec() or pcre_dfa_exec(). If  it  is  set  at  compile
+       time,  it is remembered with the compiled pattern and assumed at match-
+       ing time. This is necessary if you want to use JIT  execution,  because
+       the  JIT  compiler needs to know whether or not this option is set. For
        details see the discussion of PCRE_NO_START_OPTIMIZE below.
 
          PCRE_UCP
 
-       This  option changes the way PCRE processes \B, \b, \D, \d, \S, \s, \W,
-       \w, and some of the POSIX character classes.  By  default,  only  ASCII
-       characters  are  recognized, but if PCRE_UCP is set, Unicode properties
-       are used instead to classify characters. More details are given in  the
-       section  on generic character types in the pcrepattern page. If you set
-       PCRE_UCP, matching one of the items it affects takes much  longer.  The
-       option  is  available only if PCRE has been compiled with Unicode prop-
+       This option changes the way PCRE processes \B, \b, \D, \d, \S, \s,  \W,
+       \w,  and  some  of  the POSIX character classes. By default, only ASCII
+       characters are recognized, but if PCRE_UCP is set,  Unicode  properties
+       are  used instead to classify characters. More details are given in the
+       section on generic character types in the pcrepattern page. If you  set
+       PCRE_UCP,  matching  one of the items it affects takes much longer. The
+       option is available only if PCRE has been compiled with  Unicode  prop-
        erty support.
 
          PCRE_UNGREEDY
 
-       This option inverts the "greediness" of the quantifiers  so  that  they
-       are  not greedy by default, but become greedy if followed by "?". It is
-       not compatible with Perl. It can also be set by a (?U)  option  setting
+       This  option  inverts  the "greediness" of the quantifiers so that they
+       are not greedy by default, but become greedy if followed by "?". It  is
+       not  compatible  with Perl. It can also be set by a (?U) option setting
        within the pattern.
 
          PCRE_UTF8
 
-       This  option  causes PCRE to regard both the pattern and the subject as
+       This option causes PCRE to regard both the pattern and the  subject  as
        strings of UTF-8 characters instead of single-byte strings. However, it
-       is  available  only  when PCRE is built to include UTF support. If not,
-       the use of this option provokes an error. Details of  how  this  option
+       is available only when PCRE is built to include UTF  support.  If  not,
+       the  use  of  this option provokes an error. Details of how this option
        changes the behaviour of PCRE are given in the pcreunicode page.
 
          PCRE_NO_UTF8_CHECK
 
        When PCRE_UTF8 is set, the validity of the pattern as a UTF-8 string is
-       automatically checked. There is a  discussion  about  the  validity  of
-       UTF-8  strings in the pcreunicode page. If an invalid UTF-8 sequence is
-       found, pcre_compile() returns an error. If you already know  that  your
-       pattern  is valid, and you want to skip this check for performance rea-
-       sons, you can set the PCRE_NO_UTF8_CHECK option.  When it is  set,  the
+       automatically  checked.  There  is  a  discussion about the validity of
+       UTF-8 strings in the pcreunicode page. If an invalid UTF-8 sequence  is
+       found,  pcre_compile()  returns an error. If you already know that your
+       pattern is valid, and you want to skip this check for performance  rea-
+       sons,  you  can set the PCRE_NO_UTF8_CHECK option.  When it is set, the
        effect of passing an invalid UTF-8 string as a pattern is undefined. It
        may cause your program to crash or loop. Note that this option can also
-       be  passed to pcre_exec() and pcre_dfa_exec(), to suppress the validity
-       checking of subject strings only. If the same string is  being  matched
-       many  times, the option can be safely set for the second and subsequent
+       be passed to pcre_exec() and pcre_dfa_exec(), to suppress the  validity
+       checking  of  subject strings only. If the same string is being matched
+       many times, the option can be safely set for the second and  subsequent
        matchings to improve performance.
 
 
 COMPILATION ERROR CODES
 
-       The following table lists the error  codes  than  may  be  returned  by
-       pcre_compile2(),  along with the error messages that may be returned by
-       both compiling functions. Note that error  messages  are  always  8-bit
-       ASCII  strings,  even  in 16-bit or 32-bit mode. As PCRE has developed,
-       some error codes have fallen out of use. To avoid confusion, they  have
+       The  following  table  lists  the  error  codes than may be returned by
+       pcre_compile2(), along with the error messages that may be returned  by
+       both  compiling  functions.  Note  that error messages are always 8-bit
+       ASCII strings, even in 16-bit or 32-bit mode. As  PCRE  has  developed,
+       some  error codes have fallen out of use. To avoid confusion, they have
        not been re-used.
 
           0  no error
@@ -2504,7 +2503,7 @@ COMPILATION ERROR CODES
          84  group name must start with a non-digit
          85  parentheses are too deeply nested (stack check)
 
-       The  numbers  32  and 10000 in errors 48 and 49 are defaults; different
+       The numbers 32 and 10000 in errors 48 and 49  are  defaults;  different
        values may be used if the limits were changed when PCRE was built.
 
 
@@ -2513,64 +2512,64 @@ STUDYING A PATTERN
        pcre_extra *pcre_study(const pcre *code, int options,
             const char **errptr);
 
-       If a compiled pattern is going to be used several times,  it  is  worth
+       If  a  compiled  pattern is going to be used several times, it is worth
        spending more time analyzing it in order to speed up the time taken for
-       matching. The function pcre_study() takes a pointer to a compiled  pat-
+       matching.  The function pcre_study() takes a pointer to a compiled pat-
        tern as its first argument. If studying the pattern produces additional
-       information that will help speed up matching,  pcre_study()  returns  a
-       pointer  to a pcre_extra block, in which the study_data field points to
+       information  that  will  help speed up matching, pcre_study() returns a
+       pointer to a pcre_extra block, in which the study_data field points  to
        the results of the study.
 
        The  returned  value  from  pcre_study()  can  be  passed  directly  to
-       pcre_exec()  or  pcre_dfa_exec(). However, a pcre_extra block also con-
-       tains other fields that can be set by the caller before  the  block  is
+       pcre_exec() or pcre_dfa_exec(). However, a pcre_extra block  also  con-
+       tains  other  fields  that can be set by the caller before the block is
        passed; these are described below in the section on matching a pattern.
 
-       If  studying  the  pattern  does  not  produce  any useful information,
-       pcre_study() returns NULL by default.  In  that  circumstance,  if  the
+       If studying the  pattern  does  not  produce  any  useful  information,
+       pcre_study()  returns  NULL  by  default.  In that circumstance, if the
        calling program wants to pass any of the other fields to pcre_exec() or
-       pcre_dfa_exec(), it must set up its own pcre_extra block.  However,  if
-       pcre_study()  is  called  with  the  PCRE_STUDY_EXTRA_NEEDED option, it
+       pcre_dfa_exec(),  it  must set up its own pcre_extra block. However, if
+       pcre_study() is called  with  the  PCRE_STUDY_EXTRA_NEEDED  option,  it
        returns a pcre_extra block even if studying did not find any additional
-       information.  It  may still return NULL, however, if an error occurs in
+       information. It may still return NULL, however, if an error  occurs  in
        pcre_study().
 
-       The second argument of pcre_study() contains  option  bits.  There  are
+       The  second  argument  of  pcre_study() contains option bits. There are
        three further options in addition to PCRE_STUDY_EXTRA_NEEDED:
 
          PCRE_STUDY_JIT_COMPILE
          PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
          PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
 
-       If  any  of  these are set, and the just-in-time compiler is available,
-       the pattern is further compiled into machine code  that  executes  much
-       faster  than  the  pcre_exec()  interpretive  matching function. If the
-       just-in-time compiler is not available, these options are ignored.  All
+       If any of these are set, and the just-in-time  compiler  is  available,
+       the  pattern  is  further compiled into machine code that executes much
+       faster than the pcre_exec()  interpretive  matching  function.  If  the
+       just-in-time  compiler is not available, these options are ignored. All
        undefined bits in the options argument must be zero.
 
-       JIT  compilation  is  a heavyweight optimization. It can take some time
-       for patterns to be analyzed, and for one-off matches  and  simple  pat-
-       terns  the benefit of faster execution might be offset by a much slower
+       JIT compilation is a heavyweight optimization. It can  take  some  time
+       for  patterns  to  be analyzed, and for one-off matches and simple pat-
+       terns the benefit of faster execution might be offset by a much  slower
        study time.  Not all patterns can be optimized by the JIT compiler. For
-       those  that cannot be handled, matching automatically falls back to the
-       pcre_exec() interpreter. For more details, see the  pcrejit  documenta-
+       those that cannot be handled, matching automatically falls back to  the
+       pcre_exec()  interpreter.  For more details, see the pcrejit documenta-
        tion.
 
-       The  third argument for pcre_study() is a pointer for an error message.
-       If studying succeeds (even if no data is  returned),  the  variable  it
-       points  to  is  set  to NULL. Otherwise it is set to point to a textual
+       The third argument for pcre_study() is a pointer for an error  message.
+       If  studying  succeeds  (even  if no data is returned), the variable it
+       points to is set to NULL. Otherwise it is set to  point  to  a  textual
        error message. This is a static string that is part of the library. You
-       must  not  try  to  free it. You should test the error pointer for NULL
+       must not try to free it. You should test the  error  pointer  for  NULL
        after calling pcre_study(), to be sure that it has run successfully.
 
-       When you are finished with a pattern, you can free the memory used  for
+       When  you are finished with a pattern, you can free the memory used for
        the study data by calling pcre_free_study(). This function was added to
-       the API for release 8.20. For earlier versions,  the  memory  could  be
-       freed  with  pcre_free(), just like the pattern itself. This will still
-       work in cases where JIT optimization is not used, but it  is  advisable
+       the  API  for  release  8.20. For earlier versions, the memory could be
+       freed with pcre_free(), just like the pattern itself. This  will  still
+       work  in  cases where JIT optimization is not used, but it is advisable
        to change to the new function when convenient.
 
-       This  is  a typical way in which pcre_study() is used (except that in a
+       This is a typical way in which pcre_study() is used (except that  in  a
        real application there should be tests for errors):
 
          int rc;
@@ -2590,29 +2589,29 @@ STUDYING A PATTERN
        Studying a pattern does two things: first, a lower bound for the length
        of subject string that is needed to match the pattern is computed. This
        does not mean that there are any strings of that length that match, but
-       it  does  guarantee that no shorter strings match. The value is used to
+       it does guarantee that no shorter strings match. The value is  used  to
        avoid wasting time by trying to match strings that are shorter than the
-       lower  bound.  You  can find out the value in a calling program via the
+       lower bound. You can find out the value in a calling  program  via  the
        pcre_fullinfo() function.
 
        Studying a pattern is also useful for non-anchored patterns that do not
-       have  a  single fixed starting character. A bitmap of possible starting
-       bytes is created. This speeds up finding a position in the  subject  at
+       have a single fixed starting character. A bitmap of  possible  starting
+       bytes  is  created. This speeds up finding a position in the subject at
        which to start matching. (In 16-bit mode, the bitmap is used for 16-bit
-       values less than 256.  In 32-bit mode, the bitmap is  used  for  32-bit
+       values  less  than  256.  In 32-bit mode, the bitmap is used for 32-bit
        values less than 256.)
 
-       These  two optimizations apply to both pcre_exec() and pcre_dfa_exec(),
-       and the information is also used by the JIT  compiler.   The  optimiza-
-       tions  can  be  disabled  by setting the PCRE_NO_START_OPTIMIZE option.
-       You might want to do this if your pattern contains callouts or  (*MARK)
-       and  you  want  to make use of these facilities in cases where matching
+       These two optimizations apply to both pcre_exec() and  pcre_dfa_exec(),
+       and  the  information  is also used by the JIT compiler.  The optimiza-
+       tions can be disabled by  setting  the  PCRE_NO_START_OPTIMIZE  option.
+       You  might want to do this if your pattern contains callouts or (*MARK)
+       and you want to make use of these facilities in  cases  where  matching
        fails.
 
-       PCRE_NO_START_OPTIMIZE can be specified at either compile time or  exe-
-       cution   time.   However,   if   PCRE_NO_START_OPTIMIZE  is  passed  to
+       PCRE_NO_START_OPTIMIZE  can be specified at either compile time or exe-
+       cution  time.  However,  if   PCRE_NO_START_OPTIMIZE   is   passed   to
        pcre_exec(), (that is, after any JIT compilation has happened) JIT exe-
-       cution  is disabled. For JIT execution to work with PCRE_NO_START_OPTI-
+       cution is disabled. For JIT execution to work with  PCRE_NO_START_OPTI-
        MIZE, the option must be set at compile time.
 
        There is a longer discussion of PCRE_NO_START_OPTIMIZE below.
@@ -2620,65 +2619,65 @@ STUDYING A PATTERN
 
 LOCALE SUPPORT
 
-       PCRE handles caseless matching, and determines whether  characters  are
-       letters,  digits, or whatever, by reference to a set of tables, indexed
-       by character code point. When running in UTF-8 mode, or in the  16-  or
+       PCRE  handles  caseless matching, and determines whether characters are
+       letters, digits, or whatever, by reference to a set of tables,  indexed
+       by  character  code point. When running in UTF-8 mode, or in the 16- or
        32-bit libraries, this applies only to characters with code points less
-       than 256. By default, higher-valued code  points  never  match  escapes
-       such  as \w or \d. However, if PCRE is built with Unicode property sup-
-       port, all characters can be tested with \p and \P,  or,  alternatively,
-       the  PCRE_UCP option can be set when a pattern is compiled; this causes
-       \w and friends to use Unicode property support instead of the  built-in
+       than  256.  By  default,  higher-valued code points never match escapes
+       such as \w or \d. However, if PCRE is built with Unicode property  sup-
+       port,  all  characters can be tested with \p and \P, or, alternatively,
+       the PCRE_UCP option can be set when a pattern is compiled; this  causes
+       \w  and friends to use Unicode property support instead of the built-in
        tables.
 
-       The  use  of  locales  with Unicode is discouraged. If you are handling
-       characters with code points greater than 128,  you  should  either  use
+       The use of locales with Unicode is discouraged.  If  you  are  handling
+       characters  with  code  points  greater than 128, you should either use
        Unicode support, or use locales, but not try to mix the two.
 
-       PCRE  contains  an  internal set of tables that are used when the final
-       argument of pcre_compile() is  NULL.  These  are  sufficient  for  many
+       PCRE contains an internal set of tables that are used  when  the  final
+       argument  of  pcre_compile()  is  NULL.  These  are sufficient for many
        applications.  Normally, the internal tables recognize only ASCII char-
        acters. However, when PCRE is built, it is possible to cause the inter-
        nal tables to be rebuilt in the default "C" locale of the local system,
        which may cause them to be different.
 
-       The internal tables can always be overridden by tables supplied by  the
+       The  internal tables can always be overridden by tables supplied by the
        application that calls PCRE. These may be created in a different locale
-       from the default. As more and more applications change  to  using  Uni-
+       from  the  default.  As more and more applications change to using Uni-
        code, the need for this locale support is expected to die away.
 
-       External  tables  are  built by calling the pcre_maketables() function,
-       which has no arguments, in the relevant locale. The result can then  be
-       passed  to  pcre_compile() as often as necessary. For example, to build
-       and use tables that  are  appropriate  for  the  French  locale  (where
-       accented  characters  with  values greater than 128 are treated as let-
+       External tables are built by calling  the  pcre_maketables()  function,
+       which  has no arguments, in the relevant locale. The result can then be
+       passed to pcre_compile() as often as necessary. For example,  to  build
+       and  use  tables  that  are  appropriate  for  the French locale (where
+       accented characters with values greater than 128 are  treated  as  let-
        ters), the following code could be used:
 
          setlocale(LC_CTYPE, "fr_FR");
          tables = pcre_maketables();
          re = pcre_compile(..., tables);
 
-       The locale name "fr_FR" is used on Linux and other  Unix-like  systems;
+       The  locale  name "fr_FR" is used on Linux and other Unix-like systems;
        if you are using Windows, the name for the French locale is "french".
 
-       When  pcre_maketables()  runs,  the  tables are built in memory that is
-       obtained via pcre_malloc. It is the caller's responsibility  to  ensure
-       that  the memory containing the tables remains available for as long as
+       When pcre_maketables() runs, the tables are built  in  memory  that  is
+       obtained  via  pcre_malloc. It is the caller's responsibility to ensure
+       that the memory containing the tables remains available for as long  as
        it is needed.
 
        The pointer that is passed to pcre_compile() is saved with the compiled
-       pattern,  and the same tables are used via this pointer by pcre_study()
-       and also by pcre_exec() and pcre_dfa_exec(). Thus, for any single  pat-
+       pattern, and the same tables are used via this pointer by  pcre_study()
+       and  also by pcre_exec() and pcre_dfa_exec(). Thus, for any single pat-
        tern, compilation, studying and matching all happen in the same locale,
        but different patterns can be processed in different locales.
 
-       It is possible to pass a table pointer or NULL (indicating the  use  of
+       It  is  possible to pass a table pointer or NULL (indicating the use of
        the internal tables) to pcre_exec() or pcre_dfa_exec() (see the discus-
        sion below in the section on matching a pattern). This facility is pro-
-       vided  for  use  with  pre-compiled  patterns  that have been saved and
-       reloaded.  Character tables are not saved with patterns, so if  a  non-
+       vided for use with pre-compiled  patterns  that  have  been  saved  and
+       reloaded.   Character  tables are not saved with patterns, so if a non-
        standard table was used at compile time, it must be provided again when
-       the reloaded pattern is matched. Attempting to  use  this  facility  to
+       the  reloaded  pattern  is  matched. Attempting to use this facility to
        match a pattern in a different locale from the one in which it was com-
        piled is likely to lead to anomalous (usually incorrect) results.
 
@@ -2688,15 +2687,15 @@ INFORMATION ABOUT A PATTERN
        int pcre_fullinfo(const pcre *code, const pcre_extra *extra,
             int what, void *where);
 
-       The pcre_fullinfo() function returns information about a compiled  pat-
-       tern.  It replaces the pcre_info() function, which was removed from the
+       The  pcre_fullinfo() function returns information about a compiled pat-
+       tern. It replaces the pcre_info() function, which was removed from  the
        library at version 8.30, after more than 10 years of obsolescence.
 
-       The first argument for pcre_fullinfo() is a  pointer  to  the  compiled
-       pattern.  The second argument is the result of pcre_study(), or NULL if
-       the pattern was not studied. The third argument specifies  which  piece
-       of  information  is required, and the fourth argument is a pointer to a
-       variable to receive the data. The yield of the  function  is  zero  for
+       The  first  argument  for  pcre_fullinfo() is a pointer to the compiled
+       pattern. The second argument is the result of pcre_study(), or NULL  if
+       the  pattern  was not studied. The third argument specifies which piece
+       of information is required, and the fourth argument is a pointer  to  a
+       variable  to  receive  the  data. The yield of the function is zero for
        success, or one of the following negative numbers:
 
          PCRE_ERROR_NULL           the argument code was NULL
@@ -2707,10 +2706,10 @@ INFORMATION ABOUT A PATTERN
          PCRE_ERROR_BADOPTION      the value of what was invalid
          PCRE_ERROR_UNSET          the requested field is not set
 
-       The  "magic  number" is placed at the start of each compiled pattern as
-       an simple check against passing an arbitrary memory pointer. The  endi-
+       The "magic number" is placed at the start of each compiled  pattern  as
+       an  simple check against passing an arbitrary memory pointer. The endi-
        anness error can occur if a compiled pattern is saved and reloaded on a
-       different host. Here is a typical call of  pcre_fullinfo(),  to  obtain
+       different  host.  Here  is a typical call of pcre_fullinfo(), to obtain
        the length of the compiled pattern:
 
          int rc;
@@ -2721,81 +2720,81 @@ INFORMATION ABOUT A PATTERN
            PCRE_INFO_SIZE,   /* what is required */
            &length);         /* where to put the data */
 
-       The  possible  values for the third argument are defined in pcre.h, and
+       The possible values for the third argument are defined in  pcre.h,  and
        are as follows:
 
          PCRE_INFO_BACKREFMAX
 
-       Return the number of the highest back reference  in  the  pattern.  The
-       fourth  argument  should  point to an int variable. Zero is returned if
+       Return  the  number  of  the highest back reference in the pattern. The
+       fourth argument should point to an int variable. Zero  is  returned  if
        there are no back references.
 
          PCRE_INFO_CAPTURECOUNT
 
-       Return the number of capturing subpatterns in the pattern.  The  fourth
+       Return  the  number of capturing subpatterns in the pattern. The fourth
        argument should point to an int variable.
 
          PCRE_INFO_DEFAULT_TABLES
 
-       Return  a pointer to the internal default character tables within PCRE.
-       The fourth argument should point to an unsigned char *  variable.  This
+       Return a pointer to the internal default character tables within  PCRE.
+       The  fourth  argument should point to an unsigned char * variable. This
        information call is provided for internal use by the pcre_study() func-
-       tion. External callers can cause PCRE to use  its  internal  tables  by
+       tion.  External  callers  can  cause PCRE to use its internal tables by
        passing a NULL table pointer.
 
          PCRE_INFO_FIRSTBYTE (deprecated)
 
        Return information about the first data unit of any matched string, for
-       a non-anchored pattern. The name of this option  refers  to  the  8-bit
-       library,  where  data units are bytes. The fourth argument should point
-       to an int variable. Negative values are used for  special  cases.  How-
-       ever,  this  means  that when the 32-bit library is in non-UTF-32 mode,
-       the full 32-bit range of characters cannot be returned. For  this  rea-
-       son,  this  value  is deprecated; use PCRE_INFO_FIRSTCHARACTERFLAGS and
+       a  non-anchored  pattern.  The  name of this option refers to the 8-bit
+       library, where data units are bytes. The fourth argument  should  point
+       to  an  int  variable. Negative values are used for special cases. How-
+       ever, this means that when the 32-bit library is  in  non-UTF-32  mode,
+       the  full  32-bit range of characters cannot be returned. For this rea-
+       son, this value is deprecated;  use  PCRE_INFO_FIRSTCHARACTERFLAGS  and
        PCRE_INFO_FIRSTCHARACTER instead.
 
-       If there is a fixed first value, for example, the  letter  "c"  from  a
-       pattern  such  as (cat|cow|coyote), its value is returned. In the 8-bit
-       library, the value is always less than 256. In the 16-bit  library  the
+       If  there  is  a  fixed first value, for example, the letter "c" from a
+       pattern such as (cat|cow|coyote), its value is returned. In  the  8-bit
+       library,  the  value is always less than 256. In the 16-bit library the
        value can be up to 0xffff. In the 32-bit library the value can be up to
        0x10ffff.
 
        If there is no fixed first value, and if either
 
-       (a) the pattern was compiled with the PCRE_MULTILINE option, and  every
+       (a)  the pattern was compiled with the PCRE_MULTILINE option, and every
        branch starts with "^", or
 
        (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not
        set (if it were set, the pattern would be anchored),
 
-       -1 is returned, indicating that the pattern matches only at  the  start
-       of  a  subject string or after any newline within the string. Otherwise
+       -1  is  returned, indicating that the pattern matches only at the start
+       of a subject string or after any newline within the  string.  Otherwise
        -2 is returned. For anchored patterns, -2 is returned.
 
          PCRE_INFO_FIRSTCHARACTER
 
-       Return the value of the first data  unit  (non-UTF  character)  of  any
-       matched  string  in  the  situation where PCRE_INFO_FIRSTCHARACTERFLAGS
-       returns 1; otherwise return 0. The fourth argument should point  to  an
+       Return  the  value  of  the  first data unit (non-UTF character) of any
+       matched string in  the  situation  where  PCRE_INFO_FIRSTCHARACTERFLAGS
+       returns  1;  otherwise return 0. The fourth argument should point to an
        uint_t variable.
 
-       In  the 8-bit library, the value is always less than 256. In the 16-bit
-       library the value can be up to 0xffff. In the 32-bit library in  UTF-32
-       mode  the  value  can  be up to 0x10ffff, and up to 0xffffffff when not
+       In the 8-bit library, the value is always less than 256. In the  16-bit
+       library  the value can be up to 0xffff. In the 32-bit library in UTF-32
+       mode the value can be up to 0x10ffff, and up  to  0xffffffff  when  not
        using UTF-32 mode.
 
          PCRE_INFO_FIRSTCHARACTERFLAGS
 
        Return information about the first data unit of any matched string, for
-       a  non-anchored  pattern.  The  fourth  argument should point to an int
+       a non-anchored pattern. The fourth argument  should  point  to  an  int
        variable.
 
-       If there is a fixed first value, for example, the  letter  "c"  from  a
-       pattern  such  as  (cat|cow|coyote),  1  is returned, and the character
-       value can be retrieved using PCRE_INFO_FIRSTCHARACTER. If there  is  no
+       If  there  is  a  fixed first value, for example, the letter "c" from a
+       pattern such as (cat|cow|coyote), 1  is  returned,  and  the  character
+       value  can  be retrieved using PCRE_INFO_FIRSTCHARACTER. If there is no
        fixed first value, and if either
 
-       (a)  the pattern was compiled with the PCRE_MULTILINE option, and every
+       (a) the pattern was compiled with the PCRE_MULTILINE option, and  every
        branch starts with "^", or
 
        (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not
@@ -2807,139 +2806,139 @@ INFORMATION ABOUT A PATTERN
 
          PCRE_INFO_FIRSTTABLE
 
-       If  the pattern was studied, and this resulted in the construction of a
-       256-bit table indicating a fixed set of values for the first data  unit
-       in  any  matching string, a pointer to the table is returned. Otherwise
-       NULL is returned. The fourth argument should point to an unsigned  char
+       If the pattern was studied, and this resulted in the construction of  a
+       256-bit  table indicating a fixed set of values for the first data unit
+       in any matching string, a pointer to the table is  returned.  Otherwise
+       NULL  is returned. The fourth argument should point to an unsigned char
        * variable.
 
          PCRE_INFO_HASCRORLF
 
-       Return  1  if  the  pattern  contains any explicit matches for CR or LF
-       characters, otherwise 0. The fourth argument should  point  to  an  int
-       variable.  An explicit match is either a literal CR or LF character, or
+       Return 1 if the pattern contains any explicit  matches  for  CR  or  LF
+       characters,  otherwise  0.  The  fourth argument should point to an int
+       variable. An explicit match is either a literal CR or LF character,  or
        \r or \n.
 
          PCRE_INFO_JCHANGED
 
-       Return 1 if the (?J) or (?-J) option setting is used  in  the  pattern,
-       otherwise  0. The fourth argument should point to an int variable. (?J)
+       Return  1  if  the (?J) or (?-J) option setting is used in the pattern,
+       otherwise 0. The fourth argument should point to an int variable.  (?J)
        and (?-J) set and unset the local PCRE_DUPNAMES option, respectively.
 
          PCRE_INFO_JIT
 
-       Return 1 if the pattern was studied with one of the  JIT  options,  and
+       Return  1  if  the pattern was studied with one of the JIT options, and
        just-in-time compiling was successful. The fourth argument should point
-       to an int variable. A return value of 0 means that JIT support  is  not
-       available  in this version of PCRE, or that the pattern was not studied
-       with a JIT option, or that the JIT compiler could not handle this  par-
-       ticular  pattern. See the pcrejit documentation for details of what can
+       to  an  int variable. A return value of 0 means that JIT support is not
+       available in this version of PCRE, or that the pattern was not  studied
+       with  a JIT option, or that the JIT compiler could not handle this par-
+       ticular pattern. See the pcrejit documentation for details of what  can
        and cannot be handled.
 
          PCRE_INFO_JITSIZE
 
-       If the pattern was successfully studied with a JIT option,  return  the
-       size  of the JIT compiled code, otherwise return zero. The fourth argu-
+       If  the  pattern was successfully studied with a JIT option, return the
+       size of the JIT compiled code, otherwise return zero. The fourth  argu-
        ment should point to a size_t variable.
 
          PCRE_INFO_LASTLITERAL
 
-       Return the value of the rightmost literal data unit that must exist  in
-       any  matched  string, other than at its start, if such a value has been
+       Return  the value of the rightmost literal data unit that must exist in
+       any matched string, other than at its start, if such a value  has  been
        recorded. The fourth argument should point to an int variable. If there
        is no such value, -1 is returned. For anchored patterns, a last literal
-       value is recorded only if it follows something of variable length.  For
+       value  is recorded only if it follows something of variable length. For
        example, for the pattern /^a\d+z\d+/ the returned value is "z", but for
        /^a\dz\d/ the returned value is -1.
 
-       Since for the 32-bit library using the non-UTF-32 mode,  this  function
-       is  unable to return the full 32-bit range of characters, this value is
+       Since  for  the 32-bit library using the non-UTF-32 mode, this function
+       is unable to return the full 32-bit range of characters, this value  is
        deprecated;     instead     the     PCRE_INFO_REQUIREDCHARFLAGS     and
        PCRE_INFO_REQUIREDCHAR values should be used.
 
          PCRE_INFO_MATCH_EMPTY
 
-       Return  1  if  the  pattern can match an empty string, otherwise 0. The
+       Return 1 if the pattern can match an empty  string,  otherwise  0.  The
        fourth argument should point to an int variable.
 
          PCRE_INFO_MATCHLIMIT
 
-       If the pattern set a match limit by  including  an  item  of  the  form
-       (*LIMIT_MATCH=nnnn)  at  the  start,  the value is returned. The fourth
-       argument should point to an unsigned 32-bit integer. If no  such  value
-       has   been   set,   the  call  to  pcre_fullinfo()  returns  the  error
+       If  the  pattern  set  a  match  limit by including an item of the form
+       (*LIMIT_MATCH=nnnn) at the start, the value  is  returned.  The  fourth
+       argument  should  point to an unsigned 32-bit integer. If no such value
+       has  been  set,  the  call  to  pcre_fullinfo()   returns   the   error
        PCRE_ERROR_UNSET.
 
          PCRE_INFO_MAXLOOKBEHIND
 
-       Return the number of characters (NB not  data  units)  in  the  longest
-       lookbehind  assertion  in  the pattern. This information is useful when
-       doing multi-segment matching using  the  partial  matching  facilities.
+       Return  the  number  of  characters  (NB not data units) in the longest
+       lookbehind assertion in the pattern. This information  is  useful  when
+       doing  multi-segment  matching  using  the partial matching facilities.
        Note that the simple assertions \b and \B require a one-character look-
-       behind. \A also registers a one-character lookbehind,  though  it  does
-       not  actually inspect the previous character. This is to ensure that at
+       behind.  \A  also  registers a one-character lookbehind, though it does
+       not actually inspect the previous character. This is to ensure that  at
        least one character from the old segment is retained when a new segment
        is processed. Otherwise, if there are no lookbehinds in the pattern, \A
        might match incorrectly at the start of a new segment.
 
          PCRE_INFO_MINLENGTH
 
-       If the pattern was studied and a minimum length  for  matching  subject
-       strings  was  computed,  its  value is returned. Otherwise the returned
+       If  the  pattern  was studied and a minimum length for matching subject
+       strings was computed, its value is  returned.  Otherwise  the  returned
        value is -1. The value is a number of characters, which in UTF mode may
-       be  different from the number of data units. The fourth argument should
-       point to an int variable. A non-negative value is a lower bound to  the
-       length  of  any  matching  string. There may not be any strings of that
-       length that do actually match, but every string that does match  is  at
+       be different from the number of data units. The fourth argument  should
+       point  to an int variable. A non-negative value is a lower bound to the
+       length of any matching string. There may not be  any  strings  of  that
+       length  that  do actually match, but every string that does match is at
        least that long.
 
          PCRE_INFO_NAMECOUNT
          PCRE_INFO_NAMEENTRYSIZE
          PCRE_INFO_NAMETABLE
 
-       PCRE  supports the use of named as well as numbered capturing parenthe-
-       ses. The names are just an additional way of identifying the  parenthe-
+       PCRE supports the use of named as well as numbered capturing  parenthe-
+       ses.  The names are just an additional way of identifying the parenthe-
        ses, which still acquire numbers. Several convenience functions such as
-       pcre_get_named_substring() are provided for  extracting  captured  sub-
-       strings  by  name. It is also possible to extract the data directly, by
-       first converting the name to a number in order to  access  the  correct
+       pcre_get_named_substring()  are  provided  for extracting captured sub-
+       strings by name. It is also possible to extract the data  directly,  by
+       first  converting  the  name to a number in order to access the correct
        pointers in the output vector (described with pcre_exec() below). To do
-       the conversion, you need  to  use  the  name-to-number  map,  which  is
+       the  conversion,  you  need  to  use  the  name-to-number map, which is
        described by these three values.
 
        The map consists of a number of fixed-size entries. PCRE_INFO_NAMECOUNT
        gives the number of entries, and PCRE_INFO_NAMEENTRYSIZE gives the size
-       of  each  entry;  both  of  these  return  an int value. The entry size
-       depends on the length of the longest name. PCRE_INFO_NAMETABLE  returns
+       of each entry; both of these  return  an  int  value.  The  entry  size
+       depends  on the length of the longest name. PCRE_INFO_NAMETABLE returns
        a pointer to the first entry of the table. This is a pointer to char in
        the 8-bit library, where the first two bytes of each entry are the num-
-       ber  of  the capturing parenthesis, most significant byte first. In the
-       16-bit library, the pointer points to 16-bit data units, the  first  of
-       which  contains  the  parenthesis  number.  In  the 32-bit library, the
-       pointer points to 32-bit data units, the first of  which  contains  the
-       parenthesis  number.  The  rest of the entry is the corresponding name,
+       ber of the capturing parenthesis, most significant byte first.  In  the
+       16-bit  library,  the pointer points to 16-bit data units, the first of
+       which contains the parenthesis  number.  In  the  32-bit  library,  the
+       pointer  points  to  32-bit data units, the first of which contains the
+       parenthesis number. The rest of the entry is  the  corresponding  name,
        zero terminated.
 
-       The names are in alphabetical order. If (?| is used to create  multiple
-       groups  with  the same number, as described in the section on duplicate
+       The  names are in alphabetical order. If (?| is used to create multiple
+       groups with the same number, as described in the section  on  duplicate
        subpattern numbers in the pcrepattern page, the groups may be given the
-       same  name,  but  there is only one entry in the table. Different names
-       for groups of the same number are not permitted.  Duplicate  names  for
+       same name, but there is only one entry in the  table.  Different  names
+       for  groups  of the same number are not permitted.  Duplicate names for
        subpatterns with different numbers are permitted, but only if PCRE_DUP-
-       NAMES is set. They appear in the table in the order in which they  were
-       found  in  the  pattern.  In  the  absence  of (?| this is the order of
-       increasing number; when (?| is used this is not  necessarily  the  case
+       NAMES  is set. They appear in the table in the order in which they were
+       found in the pattern. In the absence  of  (?|  this  is  the  order  of
+       increasing  number;  when  (?| is used this is not necessarily the case
        because later subpatterns may have lower numbers.
 
-       As  a  simple  example of the name/number table, consider the following
+       As a simple example of the name/number table,  consider  the  following
        pattern after compilation by the 8-bit library (assume PCRE_EXTENDED is
        set, so white space - including newlines - is ignored):
 
          (?<date> (?<year>(\d\d)?\d\d) -
          (?<month>\d\d) - (?<day>\d\d) )
 
-       There  are  four  named subpatterns, so the table has four entries, and
-       each entry in the table is eight bytes long. The table is  as  follows,
+       There are four named subpatterns, so the table has  four  entries,  and
+       each  entry  in the table is eight bytes long. The table is as follows,
        with non-printing bytes shows in hexadecimal, and undefined bytes shown
        as ??:
 
@@ -2948,31 +2947,31 @@ INFORMATION ABOUT A PATTERN
          00 04 m  o  n  t  h  00
          00 02 y  e  a  r  00 ??
 
-       When writing code to extract data  from  named  subpatterns  using  the
-       name-to-number  map,  remember that the length of the entries is likely
+       When  writing  code  to  extract  data from named subpatterns using the
+       name-to-number map, remember that the length of the entries  is  likely
        to be different for each compiled pattern.
 
          PCRE_INFO_OKPARTIAL
 
-       Return 1  if  the  pattern  can  be  used  for  partial  matching  with
-       pcre_exec(),  otherwise  0.  The fourth argument should point to an int
-       variable. From  release  8.00,  this  always  returns  1,  because  the
-       restrictions  that  previously  applied  to  partial matching have been
-       lifted. The pcrepartial documentation gives details of  partial  match-
+       Return  1  if  the  pattern  can  be  used  for  partial  matching with
+       pcre_exec(), otherwise 0. The fourth argument should point  to  an  int
+       variable.  From  release  8.00,  this  always  returns  1,  because the
+       restrictions that previously applied  to  partial  matching  have  been
+       lifted.  The  pcrepartial documentation gives details of partial match-
        ing.
 
          PCRE_INFO_OPTIONS
 
-       Return  a  copy of the options with which the pattern was compiled. The
-       fourth argument should point to an unsigned long  int  variable.  These
+       Return a copy of the options with which the pattern was  compiled.  The
+       fourth  argument  should  point to an unsigned long int variable. These
        option bits are those specified in the call to pcre_compile(), modified
        by any top-level option settings at the start of the pattern itself. In
-       other  words,  they are the options that will be in force when matching
-       starts. For example, if the pattern /(?im)abc(?-i)d/ is  compiled  with
-       the  PCRE_EXTENDED option, the result is PCRE_CASELESS, PCRE_MULTILINE,
+       other words, they are the options that will be in force  when  matching
+       starts.  For  example, if the pattern /(?im)abc(?-i)d/ is compiled with
+       the PCRE_EXTENDED option, the result is PCRE_CASELESS,  PCRE_MULTILINE,
        and PCRE_EXTENDED.
 
-       A pattern is automatically anchored by PCRE if  all  of  its  top-level
+       A  pattern  is  automatically  anchored by PCRE if all of its top-level
        alternatives begin with one of the following:
 
          ^     unless PCRE_MULTILINE is set
@@ -2986,53 +2985,53 @@ INFORMATION ABOUT A PATTERN
 
          PCRE_INFO_RECURSIONLIMIT
 
-       If the pattern set a recursion limit by including an item of  the  form
+       If  the  pattern set a recursion limit by including an item of the form
        (*LIMIT_RECURSION=nnnn) at the start, the value is returned. The fourth
-       argument should point to an unsigned 32-bit integer. If no  such  value
-       has   been   set,   the  call  to  pcre_fullinfo()  returns  the  error
+       argument  should  point to an unsigned 32-bit integer. If no such value
+       has  been  set,  the  call  to  pcre_fullinfo()   returns   the   error
        PCRE_ERROR_UNSET.
 
          PCRE_INFO_SIZE
 
-       Return the size of  the  compiled  pattern  in  bytes  (for  all  three
+       Return  the  size  of  the  compiled  pattern  in  bytes (for all three
        libraries). The fourth argument should point to a size_t variable. This
-       value does not include the size of the pcre structure that is  returned
-       by  pcre_compile().  The  value  that  is  passed  as  the  argument to
-       pcre_malloc() when pcre_compile() is getting memory in which  to  place
+       value  does not include the size of the pcre structure that is returned
+       by pcre_compile().  The  value  that  is  passed  as  the  argument  to
+       pcre_malloc()  when  pcre_compile() is getting memory in which to place
        the compiled data is the value returned by this option plus the size of
-       the pcre structure. Studying a compiled pattern, with or  without  JIT,
+       the  pcre  structure. Studying a compiled pattern, with or without JIT,
        does not alter the value returned by this option.
 
          PCRE_INFO_STUDYSIZE
 
-       Return  the  size  in bytes (for all three libraries) of the data block
+       Return the size in bytes (for all three libraries) of  the  data  block
        pointed to by the study_data field in a pcre_extra block. If pcre_extra
-       is  NULL, or there is no study data, zero is returned. The fourth argu-
-       ment should point to a size_t variable. The study_data field is set  by
+       is NULL, or there is no study data, zero is returned. The fourth  argu-
+       ment  should point to a size_t variable. The study_data field is set by
        pcre_study() to record information that will speed up matching (see the
-       section entitled  "Studying  a  pattern"  above).  The  format  of  the
-       study_data  block is private, but its length is made available via this
-       option so that it can be saved and  restored  (see  the  pcreprecompile
+       section  entitled  "Studying  a  pattern"  above).  The  format  of the
+       study_data block is private, but its length is made available via  this
+       option  so  that  it  can be saved and restored (see the pcreprecompile
        documentation for details).
 
          PCRE_INFO_REQUIREDCHARFLAGS
 
-       Returns  1 if there is a rightmost literal data unit that must exist in
+       Returns 1 if there is a rightmost literal data unit that must exist  in
        any matched string, other than at its start. The fourth argument should
-       point  to an int variable. If there is no such value, 0 is returned. If
+       point to an int variable. If there is no such value, 0 is returned.  If
        returning  1,  the  character  value  itself  can  be  retrieved  using
        PCRE_INFO_REQUIREDCHAR.
 
        For anchored patterns, a last literal value is recorded only if it fol-
-       lows something  of  variable  length.  For  example,  for  the  pattern
-       /^a\d+z\d+/   the   returned   value   1   (with   "z"   returned  from
+       lows  something  of  variable  length.  For  example,  for  the pattern
+       /^a\d+z\d+/  the   returned   value   1   (with   "z"   returned   from
        PCRE_INFO_REQUIREDCHAR), but for /^a\dz\d/ the returned value is 0.
 
          PCRE_INFO_REQUIREDCHAR
 
-       Return the value of the rightmost literal data unit that must exist  in
-       any  matched  string, other than at its start, if such a value has been
-       recorded. The fourth argument should point to an uint32_t variable.  If
+       Return  the value of the rightmost literal data unit that must exist in
+       any matched string, other than at its start, if such a value  has  been
+       recorded.  The fourth argument should point to an uint32_t variable. If
        there is no such value, 0 is returned.
 
 
@@ -3040,21 +3039,21 @@ REFERENCE COUNTS
 
        int pcre_refcount(pcre *code, int adjust);
 
-       The  pcre_refcount()  function is used to maintain a reference count in
+       The pcre_refcount() function is used to maintain a reference  count  in
        the data block that contains a compiled pattern. It is provided for the
-       benefit  of  applications  that  operate  in an object-oriented manner,
+       benefit of applications that  operate  in  an  object-oriented  manner,
        where different parts of the application may be using the same compiled
        pattern, but you want to free the block when they are all done.
 
        When a pattern is compiled, the reference count field is initialized to
-       zero.  It is changed only by calling this function, whose action is  to
-       add  the  adjust  value  (which may be positive or negative) to it. The
+       zero.   It is changed only by calling this function, whose action is to
+       add the adjust value (which may be positive or  negative)  to  it.  The
        yield of the function is the new value. However, the value of the count
-       is  constrained to lie between 0 and 65535, inclusive. If the new value
+       is constrained to lie between 0 and 65535, inclusive. If the new  value
        is outside these limits, it is forced to the appropriate limit value.
 
-       Except when it is zero, the reference count is not correctly  preserved
-       if  a  pattern  is  compiled on one host and then transferred to a host
+       Except  when it is zero, the reference count is not correctly preserved
+       if a pattern is compiled on one host and then  transferred  to  a  host
        whose byte-order is different. (This seems a highly unlikely scenario.)
 
 
@@ -3064,22 +3063,22 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
             const char *subject, int length, int startoffset,
             int options, int *ovector, int ovecsize);
 
-       The function pcre_exec() is called to match a subject string against  a
-       compiled  pattern, which is passed in the code argument. If the pattern
-       was studied, the result of the study should  be  passed  in  the  extra
-       argument.  You  can call pcre_exec() with the same code and extra argu-
-       ments as many times as you like, in order to  match  different  subject
+       The  function pcre_exec() is called to match a subject string against a
+       compiled pattern, which is passed in the code argument. If the  pattern
+       was  studied,  the  result  of  the study should be passed in the extra
+       argument. You can call pcre_exec() with the same code and  extra  argu-
+       ments  as  many  times as you like, in order to match different subject
        strings with the same pattern.
 
-       This  function  is  the  main  matching facility of the library, and it
-       operates in a Perl-like manner. For specialist use  there  is  also  an
-       alternative  matching function, which is described below in the section
+       This function is the main matching facility  of  the  library,  and  it
+       operates  in  a  Perl-like  manner. For specialist use there is also an
+       alternative matching function, which is described below in the  section
        about the pcre_dfa_exec() function.
 
-       In most applications, the pattern will have been compiled (and  option-
-       ally  studied)  in the same process that calls pcre_exec(). However, it
+       In  most applications, the pattern will have been compiled (and option-
+       ally studied) in the same process that calls pcre_exec().  However,  it
        is possible to save compiled patterns and study data, and then use them
-       later  in  different processes, possibly even on different hosts. For a
+       later in different processes, possibly even on different hosts.  For  a
        discussion about this, see the pcreprecompile documentation.
 
        Here is an example of a simple call to pcre_exec():
@@ -3098,10 +3097,10 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
 
    Extra data for pcre_exec()
 
-       If the extra argument is not NULL, it must point to a  pcre_extra  data
-       block.  The pcre_study() function returns such a block (when it doesn't
-       return NULL), but you can also create one for yourself, and pass  addi-
-       tional  information  in it. The pcre_extra block contains the following
+       If  the  extra argument is not NULL, it must point to a pcre_extra data
+       block. The pcre_study() function returns such a block (when it  doesn't
+       return  NULL), but you can also create one for yourself, and pass addi-
+       tional information in it. The pcre_extra block contains  the  following
        fields (not necessarily in this order):
 
          unsigned long int flags;
@@ -3113,13 +3112,13 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          const unsigned char *tables;
          unsigned char **mark;
 
-       In the 16-bit version of  this  structure,  the  mark  field  has  type
+       In  the  16-bit  version  of  this  structure,  the mark field has type
        "PCRE_UCHAR16 **".
 
-       In  the  32-bit  version  of  this  structure,  the mark field has type
+       In the 32-bit version of  this  structure,  the  mark  field  has  type
        "PCRE_UCHAR32 **".
 
-       The flags field is used to specify which of the other fields  are  set.
+       The  flags  field is used to specify which of the other fields are set.
        The flag bits are:
 
          PCRE_EXTRA_CALLOUT_DATA
@@ -3130,134 +3129,134 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          PCRE_EXTRA_STUDY_DATA
          PCRE_EXTRA_TABLES
 
-       Other  flag  bits should be set to zero. The study_data field and some-
-       times the executable_jit field are set in the pcre_extra block that  is
-       returned  by pcre_study(), together with the appropriate flag bits. You
-       should not set these yourself, but you may add to the block by  setting
+       Other flag bits should be set to zero. The study_data field  and  some-
+       times  the executable_jit field are set in the pcre_extra block that is
+       returned by pcre_study(), together with the appropriate flag bits.  You
+       should  not set these yourself, but you may add to the block by setting
        other fields and their corresponding flag bits.
 
        The match_limit field provides a means of preventing PCRE from using up
-       a vast amount of resources when running patterns that are not going  to
-       match,  but  which  have  a very large number of possibilities in their
-       search trees. The classic example is a pattern that uses nested  unlim-
+       a  vast amount of resources when running patterns that are not going to
+       match, but which have a very large number  of  possibilities  in  their
+       search  trees. The classic example is a pattern that uses nested unlim-
        ited repeats.
 
-       Internally,  pcre_exec() uses a function called match(), which it calls
-       repeatedly (sometimes recursively). The limit  set  by  match_limit  is
-       imposed  on the number of times this function is called during a match,
-       which has the effect of limiting the amount of  backtracking  that  can
+       Internally, pcre_exec() uses a function called match(), which it  calls
+       repeatedly  (sometimes  recursively).  The  limit set by match_limit is
+       imposed on the number of times this function is called during a  match,
+       which  has  the  effect of limiting the amount of backtracking that can
        take place. For patterns that are not anchored, the count restarts from
        zero for each position in the subject string.
 
        When pcre_exec() is called with a pattern that was successfully studied
-       with  a  JIT  option, the way that the matching is executed is entirely
+       with a JIT option, the way that the matching is  executed  is  entirely
        different.  However, there is still the possibility of runaway matching
        that goes on for a very long time, and so the match_limit value is also
        used in this case (but in a different way) to limit how long the match-
        ing can continue.
 
-       The  default  value  for  the  limit can be set when PCRE is built; the
-       default default is 10 million, which handles all but the  most  extreme
-       cases.  You  can  override  the  default by suppling pcre_exec() with a
-       pcre_extra    block    in    which    match_limit    is    set,     and
-       PCRE_EXTRA_MATCH_LIMIT  is  set  in  the  flags  field. If the limit is
+       The default value for the limit can be set  when  PCRE  is  built;  the
+       default  default  is 10 million, which handles all but the most extreme
+       cases. You can override the default  by  suppling  pcre_exec()  with  a
+       pcre_extra     block    in    which    match_limit    is    set,    and
+       PCRE_EXTRA_MATCH_LIMIT is set in the  flags  field.  If  the  limit  is
        exceeded, pcre_exec() returns PCRE_ERROR_MATCHLIMIT.
 
-       A value for the match limit may also be supplied  by  an  item  at  the
+       A  value  for  the  match  limit may also be supplied by an item at the
        start of a pattern of the form
 
          (*LIMIT_MATCH=d)
 
-       where  d is a decimal number. However, such a setting is ignored unless
-       d is less than the limit set by the caller of  pcre_exec()  or,  if  no
+       where d is a decimal number. However, such a setting is ignored  unless
+       d  is  less  than  the limit set by the caller of pcre_exec() or, if no
        such limit is set, less than the default.
 
-       The  match_limit_recursion field is similar to match_limit, but instead
+       The match_limit_recursion field is similar to match_limit, but  instead
        of limiting the total number of times that match() is called, it limits
-       the  depth  of  recursion. The recursion depth is a smaller number than
-       the total number of calls, because not all calls to match() are  recur-
+       the depth of recursion. The recursion depth is a  smaller  number  than
+       the  total number of calls, because not all calls to match() are recur-
        sive.  This limit is of use only if it is set smaller than match_limit.
 
-       Limiting  the  recursion  depth limits the amount of machine stack that
-       can be used, or, when PCRE has been compiled to use memory on the  heap
-       instead  of the stack, the amount of heap memory that can be used. This
-       limit is not relevant, and is ignored, when matching is done using  JIT
+       Limiting the recursion depth limits the amount of  machine  stack  that
+       can  be used, or, when PCRE has been compiled to use memory on the heap
+       instead of the stack, the amount of heap memory that can be used.  This
+       limit  is not relevant, and is ignored, when matching is done using JIT
        compiled code.
 
-       The  default  value  for  match_limit_recursion can be set when PCRE is
-       built; the default default  is  the  same  value  as  the  default  for
-       match_limit.  You can override the default by suppling pcre_exec() with
-       a  pcre_extra  block  in  which  match_limit_recursion  is   set,   and
-       PCRE_EXTRA_MATCH_LIMIT_RECURSION  is  set  in  the  flags field. If the
+       The default value for match_limit_recursion can be  set  when  PCRE  is
+       built;  the  default  default  is  the  same  value  as the default for
+       match_limit. You can override the default by suppling pcre_exec()  with
+       a   pcre_extra   block  in  which  match_limit_recursion  is  set,  and
+       PCRE_EXTRA_MATCH_LIMIT_RECURSION is set in  the  flags  field.  If  the
        limit is exceeded, pcre_exec() returns PCRE_ERROR_RECURSIONLIMIT.
 
-       A value for the recursion limit may also be supplied by an item at  the
+       A  value for the recursion limit may also be supplied by an item at the
        start of a pattern of the form
 
          (*LIMIT_RECURSION=d)
 
-       where  d is a decimal number. However, such a setting is ignored unless
-       d is less than the limit set by the caller of  pcre_exec()  or,  if  no
+       where d is a decimal number. However, such a setting is ignored  unless
+       d  is  less  than  the limit set by the caller of pcre_exec() or, if no
        such limit is set, less than the default.
 
-       The  callout_data  field is used in conjunction with the "callout" fea-
+       The callout_data field is used in conjunction with the  "callout"  fea-
        ture, and is described in the pcrecallout documentation.
 
-       The tables field is provided for use with patterns that have been  pre-
+       The  tables field is provided for use with patterns that have been pre-
        compiled using custom character tables, saved to disc or elsewhere, and
-       then reloaded, because the tables that were used to compile  a  pattern
-       are  not saved with it. See the pcreprecompile documentation for a dis-
-       cussion of saving compiled patterns for later use. If  NULL  is  passed
+       then  reloaded,  because the tables that were used to compile a pattern
+       are not saved with it. See the pcreprecompile documentation for a  dis-
+       cussion  of  saving  compiled patterns for later use. If NULL is passed
        using this mechanism, it forces PCRE's internal tables to be used.
 
-       Warning:  The  tables  that  pcre_exec() uses must be the same as those
-       that were used when the pattern was compiled. If this is not the  case,
+       Warning: The tables that pcre_exec() uses must be  the  same  as  those
+       that  were used when the pattern was compiled. If this is not the case,
        the behaviour of pcre_exec() is undefined. Therefore, when a pattern is
-       compiled and matched in the same process, this field  should  never  be
+       compiled  and  matched  in the same process, this field should never be
        set. In this (the most common) case, the correct table pointer is auto-
-       matically passed with  the  compiled  pattern  from  pcre_compile()  to
+       matically  passed  with  the  compiled  pattern  from pcre_compile() to
        pcre_exec().
 
-       If  PCRE_EXTRA_MARK  is  set in the flags field, the mark field must be
-       set to point to a suitable variable. If the pattern contains any  back-
-       tracking  control verbs such as (*MARK:NAME), and the execution ends up
-       with a name to pass back, a pointer to the  name  string  (zero  termi-
-       nated)  is  placed  in  the  variable pointed to by the mark field. The
-       names are within the compiled pattern; if you wish  to  retain  such  a
-       name  you must copy it before freeing the memory of a compiled pattern.
-       If there is no name to pass back, the variable pointed to by  the  mark
-       field  is  set  to NULL. For details of the backtracking control verbs,
+       If PCRE_EXTRA_MARK is set in the flags field, the mark  field  must  be
+       set  to point to a suitable variable. If the pattern contains any back-
+       tracking control verbs such as (*MARK:NAME), and the execution ends  up
+       with  a  name  to  pass back, a pointer to the name string (zero termi-
+       nated) is placed in the variable pointed to  by  the  mark  field.  The
+       names  are  within  the  compiled pattern; if you wish to retain such a
+       name you must copy it before freeing the memory of a compiled  pattern.
+       If  there  is no name to pass back, the variable pointed to by the mark
+       field is set to NULL. For details of the  backtracking  control  verbs,
        see the section entitled "Backtracking control" in the pcrepattern doc-
        umentation.
 
    Option bits for pcre_exec()
 
-       The  unused  bits of the options argument for pcre_exec() must be zero.
-       The only bits that may  be  set  are  PCRE_ANCHORED,  PCRE_NEWLINE_xxx,
-       PCRE_NOTBOL,    PCRE_NOTEOL,    PCRE_NOTEMPTY,   PCRE_NOTEMPTY_ATSTART,
-       PCRE_NO_START_OPTIMIZE,  PCRE_NO_UTF8_CHECK,   PCRE_PARTIAL_HARD,   and
+       The unused bits of the options argument for pcre_exec() must  be  zero.
+       The  only  bits  that  may  be set are PCRE_ANCHORED, PCRE_NEWLINE_xxx,
+       PCRE_NOTBOL,   PCRE_NOTEOL,    PCRE_NOTEMPTY,    PCRE_NOTEMPTY_ATSTART,
+       PCRE_NO_START_OPTIMIZE,   PCRE_NO_UTF8_CHECK,   PCRE_PARTIAL_HARD,  and
        PCRE_PARTIAL_SOFT.
 
-       If  the  pattern  was successfully studied with one of the just-in-time
+       If the pattern was successfully studied with one  of  the  just-in-time
        (JIT) compile options, the only supported options for JIT execution are
-       PCRE_NO_UTF8_CHECK,     PCRE_NOTBOL,     PCRE_NOTEOL,    PCRE_NOTEMPTY,
-       PCRE_NOTEMPTY_ATSTART, PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT. If  an
-       unsupported  option  is  used, JIT execution is disabled and the normal
+       PCRE_NO_UTF8_CHECK,    PCRE_NOTBOL,     PCRE_NOTEOL,     PCRE_NOTEMPTY,
+       PCRE_NOTEMPTY_ATSTART,  PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT. If an
+       unsupported option is used, JIT execution is disabled  and  the  normal
        interpretive code in pcre_exec() is run.
 
          PCRE_ANCHORED
 
-       The PCRE_ANCHORED option limits pcre_exec() to matching  at  the  first
-       matching  position.  If  a  pattern was compiled with PCRE_ANCHORED, or
-       turned out to be anchored by virtue of its contents, it cannot be  made
+       The  PCRE_ANCHORED  option  limits pcre_exec() to matching at the first
+       matching position. If a pattern was  compiled  with  PCRE_ANCHORED,  or
+       turned  out to be anchored by virtue of its contents, it cannot be made
        unachored at matching time.
 
          PCRE_BSR_ANYCRLF
          PCRE_BSR_UNICODE
 
        These options (which are mutually exclusive) control what the \R escape
-       sequence matches. The choice is either to match only CR, LF,  or  CRLF,
-       or  to  match  any Unicode newline sequence. These options override the
+       sequence  matches.  The choice is either to match only CR, LF, or CRLF,
+       or to match any Unicode newline sequence. These  options  override  the
        choice that was made or defaulted when the pattern was compiled.
 
          PCRE_NEWLINE_CR
@@ -3266,345 +3265,345 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          PCRE_NEWLINE_ANYCRLF
          PCRE_NEWLINE_ANY
 
-       These options override  the  newline  definition  that  was  chosen  or
-       defaulted  when the pattern was compiled. For details, see the descrip-
-       tion of pcre_compile()  above.  During  matching,  the  newline  choice
-       affects  the  behaviour  of the dot, circumflex, and dollar metacharac-
-       ters. It may also alter the way the match position is advanced after  a
+       These  options  override  the  newline  definition  that  was chosen or
+       defaulted when the pattern was compiled. For details, see the  descrip-
+       tion  of  pcre_compile()  above.  During  matching,  the newline choice
+       affects the behaviour of the dot, circumflex,  and  dollar  metacharac-
+       ters.  It may also alter the way the match position is advanced after a
        match failure for an unanchored pattern.
 
-       When  PCRE_NEWLINE_CRLF,  PCRE_NEWLINE_ANYCRLF,  or PCRE_NEWLINE_ANY is
-       set, and a match attempt for an unanchored pattern fails when the  cur-
-       rent  position  is  at  a  CRLF  sequence,  and the pattern contains no
-       explicit matches for  CR  or  LF  characters,  the  match  position  is
+       When PCRE_NEWLINE_CRLF, PCRE_NEWLINE_ANYCRLF,  or  PCRE_NEWLINE_ANY  is
+       set,  and a match attempt for an unanchored pattern fails when the cur-
+       rent position is at a  CRLF  sequence,  and  the  pattern  contains  no
+       explicit  matches  for  CR  or  LF  characters,  the  match position is
        advanced by two characters instead of one, in other words, to after the
        CRLF.
 
        The above rule is a compromise that makes the most common cases work as
-       expected.  For  example,  if  the  pattern  is .+A (and the PCRE_DOTALL
+       expected. For example, if the  pattern  is  .+A  (and  the  PCRE_DOTALL
        option is not set), it does not match the string "\r\nA" because, after
-       failing  at the start, it skips both the CR and the LF before retrying.
-       However, the pattern [\r\n]A does match that string,  because  it  con-
+       failing at the start, it skips both the CR and the LF before  retrying.
+       However,  the  pattern  [\r\n]A does match that string, because it con-
        tains an explicit CR or LF reference, and so advances only by one char-
        acter after the first failure.
 
        An explicit match for CR of LF is either a literal appearance of one of
-       those  characters,  or  one  of the \r or \n escape sequences. Implicit
-       matches such as [^X] do not count, nor does \s (which includes  CR  and
+       those characters, or one of the \r or  \n  escape  sequences.  Implicit
+       matches  such  as [^X] do not count, nor does \s (which includes CR and
        LF in the characters that it matches).
 
-       Notwithstanding  the above, anomalous effects may still occur when CRLF
+       Notwithstanding the above, anomalous effects may still occur when  CRLF
        is a valid newline sequence and explicit \r or \n escapes appear in the
        pattern.
 
          PCRE_NOTBOL
 
        This option specifies that first character of the subject string is not
-       the beginning of a line, so the  circumflex  metacharacter  should  not
-       match  before it. Setting this without PCRE_MULTILINE (at compile time)
-       causes circumflex never to match. This option affects only  the  behav-
+       the  beginning  of  a  line, so the circumflex metacharacter should not
+       match before it. Setting this without PCRE_MULTILINE (at compile  time)
+       causes  circumflex  never to match. This option affects only the behav-
        iour of the circumflex metacharacter. It does not affect \A.
 
          PCRE_NOTEOL
 
        This option specifies that the end of the subject string is not the end
-       of a line, so the dollar metacharacter should not match it nor  (except
-       in  multiline mode) a newline immediately before it. Setting this with-
+       of  a line, so the dollar metacharacter should not match it nor (except
+       in multiline mode) a newline immediately before it. Setting this  with-
        out PCRE_MULTILINE (at compile time) causes dollar never to match. This
-       option  affects only the behaviour of the dollar metacharacter. It does
+       option affects only the behaviour of the dollar metacharacter. It  does
        not affect \Z or \z.
 
          PCRE_NOTEMPTY
 
        An empty string is not considered to be a valid match if this option is
-       set.  If  there are alternatives in the pattern, they are tried. If all
-       the alternatives match the empty string, the entire  match  fails.  For
+       set. If there are alternatives in the pattern, they are tried.  If  all
+       the  alternatives  match  the empty string, the entire match fails. For
        example, if the pattern
 
          a?b?
 
-       is  applied  to  a  string not beginning with "a" or "b", it matches an
-       empty string at the start of the subject. With PCRE_NOTEMPTY set,  this
+       is applied to a string not beginning with "a" or  "b",  it  matches  an
+       empty  string at the start of the subject. With PCRE_NOTEMPTY set, this
        match is not valid, so PCRE searches further into the string for occur-
        rences of "a" or "b".
 
          PCRE_NOTEMPTY_ATSTART
 
-       This is like PCRE_NOTEMPTY, except that an empty string match  that  is
-       not  at  the  start  of  the  subject  is  permitted. If the pattern is
+       This  is  like PCRE_NOTEMPTY, except that an empty string match that is
+       not at the start of  the  subject  is  permitted.  If  the  pattern  is
        anchored, such a match can occur only if the pattern contains \K.
 
-       Perl    has    no    direct    equivalent    of    PCRE_NOTEMPTY     or
-       PCRE_NOTEMPTY_ATSTART,  but  it  does  make a special case of a pattern
-       match of the empty string within its split() function, and  when  using
-       the  /g  modifier.  It  is  possible  to emulate Perl's behaviour after
+       Perl     has    no    direct    equivalent    of    PCRE_NOTEMPTY    or
+       PCRE_NOTEMPTY_ATSTART, but it does make a special  case  of  a  pattern
+       match  of  the empty string within its split() function, and when using
+       the /g modifier. It is  possible  to  emulate  Perl's  behaviour  after
        matching a null string by first trying the match again at the same off-
-       set  with  PCRE_NOTEMPTY_ATSTART  and  PCRE_ANCHORED,  and then if that
+       set with PCRE_NOTEMPTY_ATSTART and  PCRE_ANCHORED,  and  then  if  that
        fails, by advancing the starting offset (see below) and trying an ordi-
-       nary  match  again. There is some code that demonstrates how to do this
-       in the pcredemo sample program. In the most general case, you  have  to
-       check  to  see  if the newline convention recognizes CRLF as a newline,
-       and if so, and the current character is CR followed by LF, advance  the
+       nary match again. There is some code that demonstrates how to  do  this
+       in  the  pcredemo sample program. In the most general case, you have to
+       check to see if the newline convention recognizes CRLF  as  a  newline,
+       and  if so, and the current character is CR followed by LF, advance the
        starting offset by two characters instead of one.
 
          PCRE_NO_START_OPTIMIZE
 
-       There  are a number of optimizations that pcre_exec() uses at the start
-       of a match, in order to speed up the process. For  example,  if  it  is
+       There are a number of optimizations that pcre_exec() uses at the  start
+       of  a  match,  in  order to speed up the process. For example, if it is
        known that an unanchored match must start with a specific character, it
-       searches the subject for that character, and fails  immediately  if  it
-       cannot  find  it,  without actually running the main matching function.
+       searches  the  subject  for that character, and fails immediately if it
+       cannot find it, without actually running the  main  matching  function.
        This means that a special item such as (*COMMIT) at the start of a pat-
-       tern  is  not  considered until after a suitable starting point for the
-       match has been found. Also, when callouts or (*MARK) items are in  use,
+       tern is not considered until after a suitable starting  point  for  the
+       match  has been found. Also, when callouts or (*MARK) items are in use,
        these "start-up" optimizations can cause them to be skipped if the pat-
        tern is never actually used. The start-up optimizations are in effect a
        pre-scan of the subject that takes place before the pattern is run.
 
-       The  PCRE_NO_START_OPTIMIZE option disables the start-up optimizations,
-       possibly causing performance to suffer,  but  ensuring  that  in  cases
-       where  the  result is "no match", the callouts do occur, and that items
+       The PCRE_NO_START_OPTIMIZE option disables the start-up  optimizations,
+       possibly  causing  performance  to  suffer,  but ensuring that in cases
+       where the result is "no match", the callouts do occur, and  that  items
        such as (*COMMIT) and (*MARK) are considered at every possible starting
-       position  in  the  subject  string. If PCRE_NO_START_OPTIMIZE is set at
-       compile time,  it  cannot  be  unset  at  matching  time.  The  use  of
+       position in the subject string. If  PCRE_NO_START_OPTIMIZE  is  set  at
+       compile  time,  it  cannot  be  unset  at  matching  time.  The  use of
        PCRE_NO_START_OPTIMIZE  at  matching  time  (that  is,  passing  it  to
-       pcre_exec()) disables JIT execution; in  this  situation,  matching  is
+       pcre_exec())  disables  JIT  execution;  in this situation, matching is
        always done using interpretively.
 
-       Setting  PCRE_NO_START_OPTIMIZE  can  change  the outcome of a matching
+       Setting PCRE_NO_START_OPTIMIZE can change the  outcome  of  a  matching
        operation.  Consider the pattern
 
          (*COMMIT)ABC
 
-       When this is compiled, PCRE records the fact that a  match  must  start
-       with  the  character  "A".  Suppose the subject string is "DEFABC". The
-       start-up optimization scans along the subject, finds "A" and  runs  the
-       first  match attempt from there. The (*COMMIT) item means that the pat-
-       tern must match the current starting position, which in this  case,  it
-       does.  However,  if  the  same match is run with PCRE_NO_START_OPTIMIZE
-       set, the initial scan along the subject string  does  not  happen.  The
-       first  match  attempt  is  run  starting  from "D" and when this fails,
-       (*COMMIT) prevents any further matches  being  tried,  so  the  overall
-       result  is  "no  match". If the pattern is studied, more start-up opti-
-       mizations may be used. For example, a minimum length  for  the  subject
+       When  this  is  compiled, PCRE records the fact that a match must start
+       with the character "A". Suppose the subject  string  is  "DEFABC".  The
+       start-up  optimization  scans along the subject, finds "A" and runs the
+       first match attempt from there. The (*COMMIT) item means that the  pat-
+       tern  must  match the current starting position, which in this case, it
+       does. However, if the same match  is  run  with  PCRE_NO_START_OPTIMIZE
+       set,  the  initial  scan  along the subject string does not happen. The
+       first match attempt is run starting  from  "D"  and  when  this  fails,
+       (*COMMIT)  prevents  any  further  matches  being tried, so the overall
+       result is "no match". If the pattern is studied,  more  start-up  opti-
+       mizations  may  be  used. For example, a minimum length for the subject
        may be recorded. Consider the pattern
 
          (*MARK:A)(X|Y)
 
-       The  minimum  length  for  a  match is one character. If the subject is
-       "ABC", there will be attempts to  match  "ABC",  "BC",  "C",  and  then
-       finally  an empty string.  If the pattern is studied, the final attempt
-       does not take place, because PCRE knows that the subject is too  short,
-       and  so  the  (*MARK) is never encountered.  In this case, studying the
-       pattern does not affect the overall match result, which  is  still  "no
+       The minimum length for a match is one  character.  If  the  subject  is
+       "ABC",  there  will  be  attempts  to  match "ABC", "BC", "C", and then
+       finally an empty string.  If the pattern is studied, the final  attempt
+       does  not take place, because PCRE knows that the subject is too short,
+       and so the (*MARK) is never encountered.  In this  case,  studying  the
+       pattern  does  not  affect the overall match result, which is still "no
        match", but it does affect the auxiliary information that is returned.
 
          PCRE_NO_UTF8_CHECK
 
        When PCRE_UTF8 is set at compile time, the validity of the subject as a
-       UTF-8 string is automatically checked when pcre_exec() is  subsequently
+       UTF-8  string is automatically checked when pcre_exec() is subsequently
        called.  The entire string is checked before any other processing takes
-       place. The value of startoffset is  also  checked  to  ensure  that  it
-       points  to  the start of a UTF-8 character. There is a discussion about
-       the validity of UTF-8 strings in the pcreunicode page.  If  an  invalid
-       sequence   of   bytes   is   found,   pcre_exec()   returns  the  error
+       place.  The  value  of  startoffset  is  also checked to ensure that it
+       points to the start of a UTF-8 character. There is a  discussion  about
+       the  validity  of  UTF-8 strings in the pcreunicode page. If an invalid
+       sequence  of  bytes   is   found,   pcre_exec()   returns   the   error
        PCRE_ERROR_BADUTF8 or, if PCRE_PARTIAL_HARD is set and the problem is a
        truncated character at the end of the subject, PCRE_ERROR_SHORTUTF8. In
-       both cases, information about the precise nature of the error may  also
-       be  returned (see the descriptions of these errors in the section enti-
-       tled Error return values from pcre_exec() below).  If startoffset  con-
+       both  cases, information about the precise nature of the error may also
+       be returned (see the descriptions of these errors in the section  enti-
+       tled  Error return values from pcre_exec() below).  If startoffset con-
        tains a value that does not point to the start of a UTF-8 character (or
        to the end of the subject), PCRE_ERROR_BADUTF8_OFFSET is returned.
 
-       If you already know that your subject is valid, and you  want  to  skip
-       these    checks    for   performance   reasons,   you   can   set   the
-       PCRE_NO_UTF8_CHECK option when calling pcre_exec(). You might  want  to
-       do  this  for the second and subsequent calls to pcre_exec() if you are
-       making repeated calls to find all  the  matches  in  a  single  subject
-       string.  However,  you  should  be  sure  that the value of startoffset
-       points to the start of a character (or the end of  the  subject).  When
+       If  you  already  know that your subject is valid, and you want to skip
+       these   checks   for   performance   reasons,   you   can    set    the
+       PCRE_NO_UTF8_CHECK  option  when calling pcre_exec(). You might want to
+       do this for the second and subsequent calls to pcre_exec() if  you  are
+       making  repeated  calls  to  find  all  the matches in a single subject
+       string. However, you should be  sure  that  the  value  of  startoffset
+       points  to  the  start of a character (or the end of the subject). When
        PCRE_NO_UTF8_CHECK is set, the effect of passing an invalid string as a
-       subject or an invalid value of startoffset is undefined.  Your  program
+       subject  or  an invalid value of startoffset is undefined. Your program
        may crash or loop.
 
          PCRE_PARTIAL_HARD
          PCRE_PARTIAL_SOFT
 
-       These  options turn on the partial matching feature. For backwards com-
-       patibility, PCRE_PARTIAL is a synonym for PCRE_PARTIAL_SOFT. A  partial
-       match  occurs if the end of the subject string is reached successfully,
-       but there are not enough subject characters to complete the  match.  If
+       These options turn on the partial matching feature. For backwards  com-
+       patibility,  PCRE_PARTIAL is a synonym for PCRE_PARTIAL_SOFT. A partial
+       match occurs if the end of the subject string is reached  successfully,
+       but  there  are not enough subject characters to complete the match. If
        this happens when PCRE_PARTIAL_SOFT (but not PCRE_PARTIAL_HARD) is set,
-       matching continues by testing any remaining alternatives.  Only  if  no
-       complete  match  can be found is PCRE_ERROR_PARTIAL returned instead of
-       PCRE_ERROR_NOMATCH. In other words,  PCRE_PARTIAL_SOFT  says  that  the
-       caller  is  prepared to handle a partial match, but only if no complete
+       matching  continues  by  testing any remaining alternatives. Only if no
+       complete match can be found is PCRE_ERROR_PARTIAL returned  instead  of
+       PCRE_ERROR_NOMATCH.  In  other  words,  PCRE_PARTIAL_SOFT says that the
+       caller is prepared to handle a partial match, but only if  no  complete
        match can be found.
 
-       If PCRE_PARTIAL_HARD is set, it overrides  PCRE_PARTIAL_SOFT.  In  this
-       case,  if  a  partial  match  is found, pcre_exec() immediately returns
-       PCRE_ERROR_PARTIAL, without  considering  any  other  alternatives.  In
-       other  words, when PCRE_PARTIAL_HARD is set, a partial match is consid-
+       If  PCRE_PARTIAL_HARD  is  set, it overrides PCRE_PARTIAL_SOFT. In this
+       case, if a partial match  is  found,  pcre_exec()  immediately  returns
+       PCRE_ERROR_PARTIAL,  without  considering  any  other  alternatives. In
+       other words, when PCRE_PARTIAL_HARD is set, a partial match is  consid-
        ered to be more important that an alternative complete match.
 
-       In both cases, the portion of the string that was  inspected  when  the
+       In  both  cases,  the portion of the string that was inspected when the
        partial match was found is set as the first matching string. There is a
-       more detailed discussion of partial and  multi-segment  matching,  with
+       more  detailed  discussion  of partial and multi-segment matching, with
        examples, in the pcrepartial documentation.
 
    The string to be matched by pcre_exec()
 
-       The  subject string is passed to pcre_exec() as a pointer in subject, a
-       length in length, and a starting offset in startoffset. The  units  for
-       length  and  startoffset  are  bytes for the 8-bit library, 16-bit data
-       items for the 16-bit library, and 32-bit  data  items  for  the  32-bit
+       The subject string is passed to pcre_exec() as a pointer in subject,  a
+       length  in  length, and a starting offset in startoffset. The units for
+       length and startoffset are bytes for the  8-bit  library,  16-bit  data
+       items  for  the  16-bit  library,  and 32-bit data items for the 32-bit
        library.
 
-       If  startoffset  is negative or greater than the length of the subject,
-       pcre_exec() returns PCRE_ERROR_BADOFFSET. When the starting  offset  is
-       zero,  the  search  for a match starts at the beginning of the subject,
-       and this is by far the most common case. In UTF-8 or UTF-16  mode,  the
-       offset  must  point to the start of a character, or the end of the sub-
-       ject (in UTF-32 mode, one data unit equals one character, so  all  off-
-       sets  are  valid).  Unlike  the pattern string, the subject may contain
+       If startoffset is negative or greater than the length of  the  subject,
+       pcre_exec()  returns  PCRE_ERROR_BADOFFSET. When the starting offset is
+       zero, the search for a match starts at the beginning  of  the  subject,
+       and  this  is by far the most common case. In UTF-8 or UTF-16 mode, the
+       offset must point to the start of a character, or the end of  the  sub-
+       ject  (in  UTF-32 mode, one data unit equals one character, so all off-
+       sets are valid). Unlike the pattern string,  the  subject  may  contain
        binary zeroes.
 
-       A non-zero starting offset is useful when searching for  another  match
-       in  the same subject by calling pcre_exec() again after a previous suc-
-       cess.  Setting startoffset differs from just passing over  a  shortened
-       string  and  setting  PCRE_NOTBOL  in the case of a pattern that begins
+       A  non-zero  starting offset is useful when searching for another match
+       in the same subject by calling pcre_exec() again after a previous  suc-
+       cess.   Setting  startoffset differs from just passing over a shortened
+       string and setting PCRE_NOTBOL in the case of  a  pattern  that  begins
        with any kind of lookbehind. For example, consider the pattern
 
          \Biss\B
 
-       which finds occurrences of "iss" in the middle of  words.  (\B  matches
-       only  if  the  current position in the subject is not a word boundary.)
-       When applied to the string "Mississipi" the first call  to  pcre_exec()
-       finds  the  first  occurrence. If pcre_exec() is called again with just
-       the remainder of the subject,  namely  "issipi",  it  does  not  match,
+       which  finds  occurrences  of "iss" in the middle of words. (\B matches
+       only if the current position in the subject is not  a  word  boundary.)
+       When  applied  to the string "Mississipi" the first call to pcre_exec()
+       finds the first occurrence. If pcre_exec() is called  again  with  just
+       the  remainder  of  the  subject,  namely  "issipi", it does not match,
        because \B is always false at the start of the subject, which is deemed
-       to be a word boundary. However, if pcre_exec()  is  passed  the  entire
+       to  be  a  word  boundary. However, if pcre_exec() is passed the entire
        string again, but with startoffset set to 4, it finds the second occur-
-       rence of "iss" because it is able to look behind the starting point  to
+       rence  of "iss" because it is able to look behind the starting point to
        discover that it is preceded by a letter.
 
-       Finding  all  the  matches  in a subject is tricky when the pattern can
+       Finding all the matches in a subject is tricky  when  the  pattern  can
        match an empty string. It is possible to emulate Perl's /g behaviour by
-       first   trying   the   match   again  at  the  same  offset,  with  the
-       PCRE_NOTEMPTY_ATSTART and  PCRE_ANCHORED  options,  and  then  if  that
-       fails,  advancing  the  starting  offset  and  trying an ordinary match
+       first  trying  the  match  again  at  the   same   offset,   with   the
+       PCRE_NOTEMPTY_ATSTART  and  PCRE_ANCHORED  options,  and  then  if that
+       fails, advancing the starting  offset  and  trying  an  ordinary  match
        again. There is some code that demonstrates how to do this in the pcre-
        demo sample program. In the most general case, you have to check to see
-       if the newline convention recognizes CRLF as a newline, and if so,  and
+       if  the newline convention recognizes CRLF as a newline, and if so, and
        the current character is CR followed by LF, advance the starting offset
        by two characters instead of one.
 
-       If a non-zero starting offset is passed when the pattern  is  anchored,
+       If  a  non-zero starting offset is passed when the pattern is anchored,
        one attempt to match at the given offset is made. This can only succeed
-       if the pattern does not require the match to be at  the  start  of  the
+       if  the  pattern  does  not require the match to be at the start of the
        subject.
 
    How pcre_exec() returns captured substrings
 
-       In  general, a pattern matches a certain portion of the subject, and in
-       addition, further substrings from the subject  may  be  picked  out  by
-       parts  of  the  pattern.  Following the usage in Jeffrey Friedl's book,
-       this is called "capturing" in what follows, and the  phrase  "capturing
-       subpattern"  is  used for a fragment of a pattern that picks out a sub-
-       string. PCRE supports several other kinds of  parenthesized  subpattern
+       In general, a pattern matches a certain portion of the subject, and  in
+       addition,  further  substrings  from  the  subject may be picked out by
+       parts of the pattern. Following the usage  in  Jeffrey  Friedl's  book,
+       this  is  called "capturing" in what follows, and the phrase "capturing
+       subpattern" is used for a fragment of a pattern that picks out  a  sub-
+       string.  PCRE  supports several other kinds of parenthesized subpattern
        that do not cause substrings to be captured.
 
        Captured substrings are returned to the caller via a vector of integers
-       whose address is passed in ovector. The number of elements in the  vec-
-       tor  is  passed in ovecsize, which must be a non-negative number. Note:
+       whose  address is passed in ovector. The number of elements in the vec-
+       tor is passed in ovecsize, which must be a non-negative  number.  Note:
        this argument is NOT the size of ovector in bytes.
 
-       The first two-thirds of the vector is used to pass back  captured  sub-
-       strings,  each  substring using a pair of integers. The remaining third
-       of the vector is used as workspace by pcre_exec() while  matching  cap-
-       turing  subpatterns, and is not available for passing back information.
-       The number passed in ovecsize should always be a multiple of three.  If
+       The  first  two-thirds of the vector is used to pass back captured sub-
+       strings, each substring using a pair of integers. The  remaining  third
+       of  the  vector is used as workspace by pcre_exec() while matching cap-
+       turing subpatterns, and is not available for passing back  information.
+       The  number passed in ovecsize should always be a multiple of three. If
        it is not, it is rounded down.
 
-       When  a  match  is successful, information about captured substrings is
-       returned in pairs of integers, starting at the  beginning  of  ovector,
-       and  continuing  up  to two-thirds of its length at the most. The first
-       element of each pair is set to the offset of the first character  in  a
-       substring,  and  the second is set to the offset of the first character
-       after the end of a substring. These values are always  data  unit  off-
-       sets,  even  in  UTF  mode. They are byte offsets in the 8-bit library,
-       16-bit data item offsets in the 16-bit library, and  32-bit  data  item
+       When a match is successful, information about  captured  substrings  is
+       returned  in  pairs  of integers, starting at the beginning of ovector,
+       and continuing up to two-thirds of its length at the  most.  The  first
+       element  of  each pair is set to the offset of the first character in a
+       substring, and the second is set to the offset of the  first  character
+       after  the  end  of a substring. These values are always data unit off-
+       sets, even in UTF mode. They are byte offsets  in  the  8-bit  library,
+       16-bit  data  item  offsets in the 16-bit library, and 32-bit data item
        offsets in the 32-bit library. Note: they are not character counts.
 
-       The  first  pair  of  integers, ovector[0] and ovector[1], identify the
-       portion of the subject string matched by the entire pattern.  The  next
-       pair  is  used for the first capturing subpattern, and so on. The value
+       The first pair of integers, ovector[0]  and  ovector[1],  identify  the
+       portion  of  the subject string matched by the entire pattern. The next
+       pair is used for the first capturing subpattern, and so on.  The  value
        returned by pcre_exec() is one more than the highest numbered pair that
-       has  been  set.  For example, if two substrings have been captured, the
-       returned value is 3. If there are no capturing subpatterns, the  return
+       has been set.  For example, if two substrings have been  captured,  the
+       returned  value is 3. If there are no capturing subpatterns, the return
        value from a successful match is 1, indicating that just the first pair
        of offsets has been set.
 
        If a capturing subpattern is matched repeatedly, it is the last portion
        of the string that it matched that is returned.
 
-       If  the vector is too small to hold all the captured substring offsets,
+       If the vector is too small to hold all the captured substring  offsets,
        it is used as far as possible (up to two-thirds of its length), and the
-       function  returns a value of zero. If neither the actual string matched
-       nor any captured substrings are of interest, pcre_exec() may be  called
-       with  ovector passed as NULL and ovecsize as zero. However, if the pat-
-       tern contains back references and the ovector  is  not  big  enough  to
-       remember  the related substrings, PCRE has to get additional memory for
-       use during matching. Thus it is usually advisable to supply an  ovector
+       function returns a value of zero. If neither the actual string  matched
+       nor  any captured substrings are of interest, pcre_exec() may be called
+       with ovector passed as NULL and ovecsize as zero. However, if the  pat-
+       tern  contains  back  references  and  the ovector is not big enough to
+       remember the related substrings, PCRE has to get additional memory  for
+       use  during matching. Thus it is usually advisable to supply an ovector
        of reasonable size.
 
-       There  are  some  cases where zero is returned (indicating vector over-
-       flow) when in fact the vector is exactly the right size for  the  final
+       There are some cases where zero is returned  (indicating  vector  over-
+       flow)  when  in fact the vector is exactly the right size for the final
        match. For example, consider the pattern
 
          (a)(?:(b)c|bd)
 
-       If  a  vector of 6 elements (allowing for only 1 captured substring) is
+       If a vector of 6 elements (allowing for only 1 captured  substring)  is
        given with subject string "abd", pcre_exec() will try to set the second
        captured string, thereby recording a vector overflow, before failing to
-       match "c" and backing up  to  try  the  second  alternative.  The  zero
-       return,  however,  does  correctly  indicate that the maximum number of
+       match  "c"  and  backing  up  to  try  the second alternative. The zero
+       return, however, does correctly indicate that  the  maximum  number  of
        slots (namely 2) have been filled. In similar cases where there is tem-
-       porary  overflow,  but  the final number of used slots is actually less
+       porary overflow, but the final number of used slots  is  actually  less
        than the maximum, a non-zero value is returned.
 
        The pcre_fullinfo() function can be used to find out how many capturing
-       subpatterns  there  are  in  a  compiled pattern. The smallest size for
-       ovector that will allow for n captured substrings, in addition  to  the
+       subpatterns there are in a compiled  pattern.  The  smallest  size  for
+       ovector  that  will allow for n captured substrings, in addition to the
        offsets of the substring matched by the whole pattern, is (n+1)*3.
 
-       It  is  possible for capturing subpattern number n+1 to match some part
+       It is possible for capturing subpattern number n+1 to match  some  part
        of the subject when subpattern n has not been used at all. For example,
-       if  the  string  "abc"  is  matched against the pattern (a|(z))(bc) the
+       if the string "abc" is matched  against  the  pattern  (a|(z))(bc)  the
        return from the function is 4, and subpatterns 1 and 3 are matched, but
-       2  is  not.  When  this happens, both values in the offset pairs corre-
+       2 is not. When this happens, both values in  the  offset  pairs  corre-
        sponding to unused subpatterns are set to -1.
 
-       Offset values that correspond to unused subpatterns at the end  of  the
-       expression  are  also  set  to  -1. For example, if the string "abc" is
-       matched against the pattern (abc)(x(yz)?)? subpatterns 2 and 3 are  not
-       matched.  The  return  from the function is 2, because the highest used
-       capturing subpattern number is 1, and the offsets for  for  the  second
-       and  third  capturing subpatterns (assuming the vector is large enough,
+       Offset  values  that correspond to unused subpatterns at the end of the
+       expression are also set to -1. For example,  if  the  string  "abc"  is
+       matched  against the pattern (abc)(x(yz)?)? subpatterns 2 and 3 are not
+       matched. The return from the function is 2, because  the  highest  used
+       capturing  subpattern  number  is 1, and the offsets for for the second
+       and third capturing subpatterns (assuming the vector is  large  enough,
        of course) are set to -1.
 
-       Note: Elements in the first two-thirds of ovector that  do  not  corre-
-       spond  to  capturing parentheses in the pattern are never changed. That
-       is, if a pattern contains n capturing parentheses, no more  than  ovec-
-       tor[0]  to ovector[2n+1] are set by pcre_exec(). The other elements (in
+       Note:  Elements  in  the first two-thirds of ovector that do not corre-
+       spond to capturing parentheses in the pattern are never  changed.  That
+       is,  if  a pattern contains n capturing parentheses, no more than ovec-
+       tor[0] to ovector[2n+1] are set by pcre_exec(). The other elements  (in
        the first two-thirds) retain whatever values they previously had.
 
-       Some convenience functions are provided  for  extracting  the  captured
+       Some  convenience  functions  are  provided for extracting the captured
        substrings as separate strings. These are described below.
 
    Error return values from pcre_exec()
 
-       If  pcre_exec()  fails, it returns a negative number. The following are
+       If pcre_exec() fails, it returns a negative number. The  following  are
        defined in the header file:
 
          PCRE_ERROR_NOMATCH        (-1)
@@ -3613,7 +3612,7 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
 
          PCRE_ERROR_NULL           (-2)
 
-       Either code or subject was passed as NULL,  or  ovector  was  NULL  and
+       Either  code  or  subject  was  passed as NULL, or ovector was NULL and
        ovecsize was not zero.
 
          PCRE_ERROR_BADOPTION      (-3)
@@ -3622,82 +3621,82 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
 
          PCRE_ERROR_BADMAGIC       (-4)
 
-       PCRE  stores a 4-byte "magic number" at the start of the compiled code,
+       PCRE stores a 4-byte "magic number" at the start of the compiled  code,
        to catch the case when it is passed a junk pointer and to detect when a
        pattern that was compiled in an environment of one endianness is run in
-       an environment with the other endianness. This is the error  that  PCRE
+       an  environment  with the other endianness. This is the error that PCRE
        gives when the magic number is not present.
 
          PCRE_ERROR_UNKNOWN_OPCODE (-5)
 
        While running the pattern match, an unknown item was encountered in the
-       compiled pattern. This error could be caused by a bug  in  PCRE  or  by
+       compiled  pattern.  This  error  could be caused by a bug in PCRE or by
        overwriting of the compiled pattern.
 
          PCRE_ERROR_NOMEMORY       (-6)
 
-       If  a  pattern contains back references, but the ovector that is passed
+       If a pattern contains back references, but the ovector that  is  passed
        to pcre_exec() is not big enough to remember the referenced substrings,
-       PCRE  gets  a  block of memory at the start of matching to use for this
-       purpose. If the call via pcre_malloc() fails, this error is given.  The
+       PCRE gets a block of memory at the start of matching to  use  for  this
+       purpose.  If the call via pcre_malloc() fails, this error is given. The
        memory is automatically freed at the end of matching.
 
-       This  error  is also given if pcre_stack_malloc() fails in pcre_exec().
-       This can happen only when PCRE has been compiled with  --disable-stack-
+       This error is also given if pcre_stack_malloc() fails  in  pcre_exec().
+       This  can happen only when PCRE has been compiled with --disable-stack-
        for-recursion.
 
          PCRE_ERROR_NOSUBSTRING    (-7)
 
-       This  error is used by the pcre_copy_substring(), pcre_get_substring(),
+       This error is used by the pcre_copy_substring(),  pcre_get_substring(),
        and  pcre_get_substring_list()  functions  (see  below).  It  is  never
        returned by pcre_exec().
 
          PCRE_ERROR_MATCHLIMIT     (-8)
 
-       The  backtracking  limit,  as  specified  by the match_limit field in a
-       pcre_extra structure (or defaulted) was reached.  See  the  description
+       The backtracking limit, as specified by  the  match_limit  field  in  a
+       pcre_extra  structure  (or  defaulted) was reached. See the description
        above.
 
          PCRE_ERROR_CALLOUT        (-9)
 
        This error is never generated by pcre_exec() itself. It is provided for
-       use by callout functions that want to yield a distinctive  error  code.
+       use  by  callout functions that want to yield a distinctive error code.
        See the pcrecallout documentation for details.
 
          PCRE_ERROR_BADUTF8        (-10)
 
-       A  string  that contains an invalid UTF-8 byte sequence was passed as a
-       subject, and the PCRE_NO_UTF8_CHECK option was not set. If the size  of
-       the  output  vector  (ovecsize)  is  at least 2, the byte offset to the
-       start of the the invalid UTF-8 character is placed in  the  first  ele-
-       ment,  and  a  reason  code is placed in the second element. The reason
+       A string that contains an invalid UTF-8 byte sequence was passed  as  a
+       subject,  and the PCRE_NO_UTF8_CHECK option was not set. If the size of
+       the output vector (ovecsize) is at least 2,  the  byte  offset  to  the
+       start  of  the  the invalid UTF-8 character is placed in the first ele-
+       ment, and a reason code is placed in the  second  element.  The  reason
        codes are listed in the following section.  For backward compatibility,
-       if  PCRE_PARTIAL_HARD is set and the problem is a truncated UTF-8 char-
-       acter  at  the  end  of  the   subject   (reason   codes   1   to   5),
+       if PCRE_PARTIAL_HARD is set and the problem is a truncated UTF-8  char-
+       acter   at   the   end   of   the   subject  (reason  codes  1  to  5),
        PCRE_ERROR_SHORTUTF8 is returned instead of PCRE_ERROR_BADUTF8.
 
          PCRE_ERROR_BADUTF8_OFFSET (-11)
 
-       The  UTF-8  byte  sequence that was passed as a subject was checked and
-       found to be valid (the PCRE_NO_UTF8_CHECK option was not set), but  the
-       value  of startoffset did not point to the beginning of a UTF-8 charac-
+       The UTF-8 byte sequence that was passed as a subject  was  checked  and
+       found  to be valid (the PCRE_NO_UTF8_CHECK option was not set), but the
+       value of startoffset did not point to the beginning of a UTF-8  charac-
        ter or the end of the subject.
 
          PCRE_ERROR_PARTIAL        (-12)
 
-       The subject string did not match, but it did match partially.  See  the
+       The  subject  string did not match, but it did match partially. See the
        pcrepartial documentation for details of partial matching.
 
          PCRE_ERROR_BADPARTIAL     (-13)
 
-       This  code  is  no  longer  in  use.  It was formerly returned when the
-       PCRE_PARTIAL option was used with a compiled pattern  containing  items
-       that  were  not  supported  for  partial  matching.  From  release 8.00
+       This code is no longer in  use.  It  was  formerly  returned  when  the
+       PCRE_PARTIAL  option  was used with a compiled pattern containing items
+       that were  not  supported  for  partial  matching.  From  release  8.00
        onwards, there are no restrictions on partial matching.
 
          PCRE_ERROR_INTERNAL       (-14)
 
-       An unexpected internal error has occurred. This error could  be  caused
+       An  unexpected  internal error has occurred. This error could be caused
        by a bug in PCRE or by overwriting of the compiled pattern.
 
          PCRE_ERROR_BADCOUNT       (-15)
@@ -3707,7 +3706,7 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          PCRE_ERROR_RECURSIONLIMIT (-21)
 
        The internal recursion limit, as specified by the match_limit_recursion
-       field in a pcre_extra structure (or defaulted)  was  reached.  See  the
+       field  in  a  pcre_extra  structure (or defaulted) was reached. See the
        description above.
 
          PCRE_ERROR_BADNEWLINE     (-23)
@@ -3721,29 +3720,29 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
 
          PCRE_ERROR_SHORTUTF8      (-25)
 
-       This error is returned instead of PCRE_ERROR_BADUTF8 when  the  subject
-       string  ends with a truncated UTF-8 character and the PCRE_PARTIAL_HARD
-       option is set.  Information  about  the  failure  is  returned  as  for
-       PCRE_ERROR_BADUTF8.  It  is in fact sufficient to detect this case, but
-       this special error code for PCRE_PARTIAL_HARD precedes the  implementa-
-       tion  of returned information; it is retained for backwards compatibil-
+       This  error  is returned instead of PCRE_ERROR_BADUTF8 when the subject
+       string ends with a truncated UTF-8 character and the  PCRE_PARTIAL_HARD
+       option  is  set.   Information  about  the  failure  is returned as for
+       PCRE_ERROR_BADUTF8. It is in fact sufficient to detect this  case,  but
+       this  special error code for PCRE_PARTIAL_HARD precedes the implementa-
+       tion of returned information; it is retained for backwards  compatibil-
        ity.
 
          PCRE_ERROR_RECURSELOOP    (-26)
 
        This error is returned when pcre_exec() detects a recursion loop within
-       the  pattern. Specifically, it means that either the whole pattern or a
-       subpattern has been called recursively for the second time at the  same
+       the pattern. Specifically, it means that either the whole pattern or  a
+       subpattern  has been called recursively for the second time at the same
        position in the subject string. Some simple patterns that might do this
-       are detected and faulted at compile time, but more  complicated  cases,
+       are  detected  and faulted at compile time, but more complicated cases,
        in particular mutual recursions between two different subpatterns, can-
        not be detected until run time.
 
          PCRE_ERROR_JIT_STACKLIMIT (-27)
 
-       This error is returned when a pattern  that  was  successfully  studied
-       using  a  JIT compile option is being matched, but the memory available
-       for the just-in-time processing stack is  not  large  enough.  See  the
+       This  error  is  returned  when a pattern that was successfully studied
+       using a JIT compile option is being matched, but the  memory  available
+       for  the  just-in-time  processing  stack  is not large enough. See the
        pcrejit documentation for more details.
 
          PCRE_ERROR_BADMODE        (-28)
@@ -3753,38 +3752,38 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
 
          PCRE_ERROR_BADENDIANNESS  (-29)
 
-       This error is given if  a  pattern  that  was  compiled  and  saved  is
-       reloaded  on  a  host  with  different endianness. The utility function
+       This  error  is  given  if  a  pattern  that  was compiled and saved is
+       reloaded on a host with  different  endianness.  The  utility  function
        pcre_pattern_to_host_byte_order() can be used to convert such a pattern
        so that it runs on the new host.
 
          PCRE_ERROR_JIT_BADOPTION
 
-       This  error  is  returned  when a pattern that was successfully studied
-       using a JIT compile option is being  matched,  but  the  matching  mode
-       (partial  or complete match) does not correspond to any JIT compilation
-       mode. When the JIT fast path function is used, this error may  be  also
-       given  for  invalid  options.  See  the  pcrejit documentation for more
+       This error is returned when a pattern  that  was  successfully  studied
+       using  a  JIT  compile  option  is being matched, but the matching mode
+       (partial or complete match) does not correspond to any JIT  compilation
+       mode.  When  the JIT fast path function is used, this error may be also
+       given for invalid options.  See  the  pcrejit  documentation  for  more
        details.
 
          PCRE_ERROR_BADLENGTH      (-32)
 
-       This error is given if pcre_exec() is called with a negative value  for
+       This  error is given if pcre_exec() is called with a negative value for
        the length argument.
 
        Error numbers -16 to -20, -22, and 30 are not used by pcre_exec().
 
    Reason codes for invalid UTF-8 strings
 
-       This  section  applies  only  to  the  8-bit library. The corresponding
-       information for the 16-bit and 32-bit libraries is given in the  pcre16
+       This section applies only  to  the  8-bit  library.  The  corresponding
+       information  for the 16-bit and 32-bit libraries is given in the pcre16
        and pcre32 pages.
 
        When pcre_exec() returns either PCRE_ERROR_BADUTF8 or PCRE_ERROR_SHORT-
-       UTF8, and the size of the output vector (ovecsize) is at least  2,  the
-       offset  of  the  start  of the invalid UTF-8 character is placed in the
+       UTF8,  and  the size of the output vector (ovecsize) is at least 2, the
+       offset of the start of the invalid UTF-8 character  is  placed  in  the
        first output vector element (ovector[0]) and a reason code is placed in
-       the  second  element  (ovector[1]). The reason codes are given names in
+       the second element (ovector[1]). The reason codes are  given  names  in
        the pcre.h header file:
 
          PCRE_UTF8_ERR1
@@ -3793,10 +3792,10 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          PCRE_UTF8_ERR4
          PCRE_UTF8_ERR5
 
-       The string ends with a truncated UTF-8 character;  the  code  specifies
-       how  many bytes are missing (1 to 5). Although RFC 3629 restricts UTF-8
-       characters to be no longer than 4 bytes, the  encoding  scheme  (origi-
-       nally  defined  by  RFC  2279)  allows  for  up to 6 bytes, and this is
+       The  string  ends  with a truncated UTF-8 character; the code specifies
+       how many bytes are missing (1 to 5). Although RFC 3629 restricts  UTF-8
+       characters  to  be  no longer than 4 bytes, the encoding scheme (origi-
+       nally defined by RFC 2279) allows for  up  to  6  bytes,  and  this  is
        checked first; hence the possibility of 4 or 5 missing bytes.
 
          PCRE_UTF8_ERR6
@@ -3806,24 +3805,24 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          PCRE_UTF8_ERR10
 
        The two most significant bits of the 2nd, 3rd, 4th, 5th, or 6th byte of
-       the  character  do  not have the binary value 0b10 (that is, either the
+       the character do not have the binary value 0b10 (that  is,  either  the
        most significant bit is 0, or the next bit is 1).
 
          PCRE_UTF8_ERR11
          PCRE_UTF8_ERR12
 
-       A character that is valid by the RFC 2279 rules is either 5 or 6  bytes
+       A  character that is valid by the RFC 2279 rules is either 5 or 6 bytes
        long; these code points are excluded by RFC 3629.
 
          PCRE_UTF8_ERR13
 
-       A  4-byte character has a value greater than 0x10fff; these code points
+       A 4-byte character has a value greater than 0x10fff; these code  points
        are excluded by RFC 3629.
 
          PCRE_UTF8_ERR14
 
-       A 3-byte character has a value in the  range  0xd800  to  0xdfff;  this
-       range  of code points are reserved by RFC 3629 for use with UTF-16, and
+       A  3-byte  character  has  a  value in the range 0xd800 to 0xdfff; this
+       range of code points are reserved by RFC 3629 for use with UTF-16,  and
        so are excluded from UTF-8.
 
          PCRE_UTF8_ERR15
@@ -3832,28 +3831,28 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          PCRE_UTF8_ERR18
          PCRE_UTF8_ERR19
 
-       A 2-, 3-, 4-, 5-, or 6-byte character is "overlong", that is, it  codes
-       for  a  value that can be represented by fewer bytes, which is invalid.
-       For example, the two bytes 0xc0, 0xae give the value 0x2e,  whose  cor-
+       A  2-, 3-, 4-, 5-, or 6-byte character is "overlong", that is, it codes
+       for a value that can be represented by fewer bytes, which  is  invalid.
+       For  example,  the two bytes 0xc0, 0xae give the value 0x2e, whose cor-
        rect coding uses just one byte.
 
          PCRE_UTF8_ERR20
 
        The two most significant bits of the first byte of a character have the
-       binary value 0b10 (that is, the most significant bit is 1 and the  sec-
-       ond  is  0). Such a byte can only validly occur as the second or subse-
+       binary  value 0b10 (that is, the most significant bit is 1 and the sec-
+       ond is 0). Such a byte can only validly occur as the second  or  subse-
        quent byte of a multi-byte character.
 
          PCRE_UTF8_ERR21
 
-       The first byte of a character has the value 0xfe or 0xff. These  values
+       The  first byte of a character has the value 0xfe or 0xff. These values
        can never occur in a valid UTF-8 string.
 
          PCRE_UTF8_ERR22
 
-       This  error  code  was  formerly  used when the presence of a so-called
-       "non-character" caused an error. Unicode corrigendum #9 makes it  clear
-       that  such  characters should not cause a string to be rejected, and so
+       This error code was formerly used when  the  presence  of  a  so-called
+       "non-character"  caused an error. Unicode corrigendum #9 makes it clear
+       that such characters should not cause a string to be rejected,  and  so
        this code is no longer in use and is never returned.
 
 
@@ -3870,78 +3869,78 @@ EXTRACTING CAPTURED SUBSTRINGS BY NUMBER
        int pcre_get_substring_list(const char *subject,
             int *ovector, int stringcount, const char ***listptr);
 
-       Captured substrings can be  accessed  directly  by  using  the  offsets
-       returned  by  pcre_exec()  in  ovector.  For convenience, the functions
+       Captured  substrings  can  be  accessed  directly  by using the offsets
+       returned by pcre_exec() in  ovector.  For  convenience,  the  functions
        pcre_copy_substring(),    pcre_get_substring(),    and    pcre_get_sub-
-       string_list()  are  provided for extracting captured substrings as new,
-       separate, zero-terminated strings. These functions identify  substrings
-       by  number.  The  next section describes functions for extracting named
+       string_list() are provided for extracting captured substrings  as  new,
+       separate,  zero-terminated strings. These functions identify substrings
+       by number. The next section describes functions  for  extracting  named
        substrings.
 
-       A substring that contains a binary zero is correctly extracted and  has
-       a  further zero added on the end, but the result is not, of course, a C
-       string.  However, you can process such a string  by  referring  to  the
-       length  that  is  returned  by  pcre_copy_substring() and pcre_get_sub-
+       A  substring that contains a binary zero is correctly extracted and has
+       a further zero added on the end, but the result is not, of course, a  C
+       string.   However,  you  can  process such a string by referring to the
+       length that is  returned  by  pcre_copy_substring()  and  pcre_get_sub-
        string().  Unfortunately, the interface to pcre_get_substring_list() is
-       not  adequate for handling strings containing binary zeros, because the
+       not adequate for handling strings containing binary zeros, because  the
        end of the final string is not independently indicated.
 
-       The first three arguments are the same for all  three  of  these  func-
-       tions:  subject  is  the subject string that has just been successfully
+       The  first  three  arguments  are the same for all three of these func-
+       tions: subject is the subject string that has  just  been  successfully
        matched, ovector is a pointer to the vector of integer offsets that was
        passed to pcre_exec(), and stringcount is the number of substrings that
-       were captured by the match, including the substring  that  matched  the
+       were  captured  by  the match, including the substring that matched the
        entire regular expression. This is the value returned by pcre_exec() if
-       it is greater than zero. If pcre_exec() returned zero, indicating  that
-       it  ran out of space in ovector, the value passed as stringcount should
+       it  is greater than zero. If pcre_exec() returned zero, indicating that
+       it ran out of space in ovector, the value passed as stringcount  should
        be the number of elements in the vector divided by three.
 
-       The functions pcre_copy_substring() and pcre_get_substring() extract  a
-       single  substring,  whose  number  is given as stringnumber. A value of
-       zero extracts the substring that matched the  entire  pattern,  whereas
-       higher  values  extract  the  captured  substrings.  For pcre_copy_sub-
-       string(), the string is placed in buffer,  whose  length  is  given  by
-       buffersize,  while  for  pcre_get_substring()  a new block of memory is
-       obtained via pcre_malloc, and its address is  returned  via  stringptr.
-       The  yield  of  the function is the length of the string, not including
+       The  functions pcre_copy_substring() and pcre_get_substring() extract a
+       single substring, whose number is given as  stringnumber.  A  value  of
+       zero  extracts  the  substring that matched the entire pattern, whereas
+       higher values  extract  the  captured  substrings.  For  pcre_copy_sub-
+       string(),  the  string  is  placed  in buffer, whose length is given by
+       buffersize, while for pcre_get_substring() a new  block  of  memory  is
+       obtained  via  pcre_malloc,  and its address is returned via stringptr.
+       The yield of the function is the length of the  string,  not  including
        the terminating zero, or one of these error codes:
 
          PCRE_ERROR_NOMEMORY       (-6)
 
-       The buffer was too small for pcre_copy_substring(), or the  attempt  to
+       The  buffer  was too small for pcre_copy_substring(), or the attempt to
        get memory failed for pcre_get_substring().
 
          PCRE_ERROR_NOSUBSTRING    (-7)
 
        There is no substring whose number is stringnumber.
 
-       The  pcre_get_substring_list()  function  extracts  all  available sub-
-       strings and builds a list of pointers to them. All this is  done  in  a
+       The pcre_get_substring_list()  function  extracts  all  available  sub-
+       strings  and  builds  a list of pointers to them. All this is done in a
        single block of memory that is obtained via pcre_malloc. The address of
-       the memory block is returned via listptr, which is also  the  start  of
-       the  list  of  string pointers. The end of the list is marked by a NULL
-       pointer. The yield of the function is zero if all  went  well,  or  the
+       the  memory  block  is returned via listptr, which is also the start of
+       the list of string pointers. The end of the list is marked  by  a  NULL
+       pointer.  The  yield  of  the function is zero if all went well, or the
        error code
 
          PCRE_ERROR_NOMEMORY       (-6)
 
        if the attempt to get the memory block failed.
 
-       When  any of these functions encounter a substring that is unset, which
-       can happen when capturing subpattern number n+1 matches  some  part  of
-       the  subject, but subpattern n has not been used at all, they return an
+       When any of these functions encounter a substring that is unset,  which
+       can  happen  when  capturing subpattern number n+1 matches some part of
+       the subject, but subpattern n has not been used at all, they return  an
        empty string. This can be distinguished from a genuine zero-length sub-
-       string  by inspecting the appropriate offset in ovector, which is nega-
+       string by inspecting the appropriate offset in ovector, which is  nega-
        tive for unset substrings.
 
-       The two convenience functions pcre_free_substring() and  pcre_free_sub-
-       string_list()  can  be  used  to free the memory returned by a previous
+       The  two convenience functions pcre_free_substring() and pcre_free_sub-
+       string_list() can be used to free the memory  returned  by  a  previous
        call  of  pcre_get_substring()  or  pcre_get_substring_list(),  respec-
-       tively.  They  do  nothing  more  than  call the function pointed to by
-       pcre_free, which of course could be called directly from a  C  program.
-       However,  PCRE is used in some situations where it is linked via a spe-
-       cial  interface  to  another  programming  language  that  cannot   use
-       pcre_free  directly;  it is for these cases that the functions are pro-
+       tively. They do nothing more than  call  the  function  pointed  to  by
+       pcre_free,  which  of course could be called directly from a C program.
+       However, PCRE is used in some situations where it is linked via a  spe-
+       cial   interface  to  another  programming  language  that  cannot  use
+       pcre_free directly; it is for these cases that the functions  are  pro-
        vided.
 
 
@@ -3960,7 +3959,7 @@ EXTRACTING CAPTURED SUBSTRINGS BY NAME
             int stringcount, const char *stringname,
             const char **stringptr);
 
-       To extract a substring by name, you first have to find associated  num-
+       To  extract a substring by name, you first have to find associated num-
        ber.  For example, for this pattern
 
          (a+)b(?<xxx>\d+)...
@@ -3969,35 +3968,35 @@ EXTRACTING CAPTURED SUBSTRINGS BY NAME
        be unique (PCRE_DUPNAMES was not set), you can find the number from the
        name by calling pcre_get_stringnumber(). The first argument is the com-
        piled pattern, and the second is the name. The yield of the function is
-       the  subpattern  number,  or PCRE_ERROR_NOSUBSTRING (-7) if there is no
+       the subpattern number, or PCRE_ERROR_NOSUBSTRING (-7) if  there  is  no
        subpattern of that name.
 
        Given the number, you can extract the substring directly, or use one of
        the functions described in the previous section. For convenience, there
        are also two functions that do the whole job.
 
-       Most   of   the   arguments    of    pcre_copy_named_substring()    and
-       pcre_get_named_substring()  are  the  same  as  those for the similarly
-       named functions that extract by number. As these are described  in  the
-       previous  section,  they  are not re-described here. There are just two
+       Most    of    the    arguments   of   pcre_copy_named_substring()   and
+       pcre_get_named_substring() are the same  as  those  for  the  similarly
+       named  functions  that extract by number. As these are described in the
+       previous section, they are not re-described here. There  are  just  two
        differences:
 
-       First, instead of a substring number, a substring name is  given.  Sec-
+       First,  instead  of a substring number, a substring name is given. Sec-
        ond, there is an extra argument, given at the start, which is a pointer
-       to the compiled pattern. This is needed in order to gain access to  the
+       to  the compiled pattern. This is needed in order to gain access to the
        name-to-number translation table.
 
-       These  functions call pcre_get_stringnumber(), and if it succeeds, they
-       then call pcre_copy_substring() or pcre_get_substring(),  as  appropri-
-       ate.  NOTE:  If PCRE_DUPNAMES is set and there are duplicate names, the
+       These functions call pcre_get_stringnumber(), and if it succeeds,  they
+       then  call  pcre_copy_substring() or pcre_get_substring(), as appropri-
+       ate. NOTE: If PCRE_DUPNAMES is set and there are duplicate  names,  the
        behaviour may not be what you want (see the next section).
 
        Warning: If the pattern uses the (?| feature to set up multiple subpat-
-       terns  with  the  same number, as described in the section on duplicate
-       subpattern numbers in the pcrepattern page, you  cannot  use  names  to
-       distinguish  the  different subpatterns, because names are not included
-       in the compiled code. The matching process uses only numbers. For  this
-       reason,  the  use of different names for subpatterns of the same number
+       terns with the same number, as described in the  section  on  duplicate
+       subpattern  numbers  in  the  pcrepattern page, you cannot use names to
+       distinguish the different subpatterns, because names are  not  included
+       in  the compiled code. The matching process uses only numbers. For this
+       reason, the use of different names for subpatterns of the  same  number
        causes an error at compile time.
 
 
@@ -4006,76 +4005,76 @@ DUPLICATE SUBPATTERN NAMES
        int pcre_get_stringtable_entries(const pcre *code,
             const char *name, char **first, char **last);
 
-       When a pattern is compiled with the  PCRE_DUPNAMES  option,  names  for
-       subpatterns  are not required to be unique. (Duplicate names are always
-       allowed for subpatterns with the same number, created by using the  (?|
-       feature.  Indeed,  if  such subpatterns are named, they are required to
+       When  a  pattern  is  compiled with the PCRE_DUPNAMES option, names for
+       subpatterns are not required to be unique. (Duplicate names are  always
+       allowed  for subpatterns with the same number, created by using the (?|
+       feature. Indeed, if such subpatterns are named, they  are  required  to
        use the same names.)
 
        Normally, patterns with duplicate names are such that in any one match,
-       only  one of the named subpatterns participates. An example is shown in
+       only one of the named subpatterns participates. An example is shown  in
        the pcrepattern documentation.
 
-       When   duplicates   are   present,   pcre_copy_named_substring()    and
-       pcre_get_named_substring()  return the first substring corresponding to
-       the given name that is set. If  none  are  set,  PCRE_ERROR_NOSUBSTRING
-       (-7)  is  returned;  no  data  is returned. The pcre_get_stringnumber()
-       function returns one of the numbers that are associated with the  name,
+       When    duplicates   are   present,   pcre_copy_named_substring()   and
+       pcre_get_named_substring() return the first substring corresponding  to
+       the  given  name  that  is set. If none are set, PCRE_ERROR_NOSUBSTRING
+       (-7) is returned; no  data  is  returned.  The  pcre_get_stringnumber()
+       function  returns one of the numbers that are associated with the name,
        but it is not defined which it is.
 
-       If  you want to get full details of all captured substrings for a given
-       name, you must use  the  pcre_get_stringtable_entries()  function.  The
+       If you want to get full details of all captured substrings for a  given
+       name,  you  must  use  the pcre_get_stringtable_entries() function. The
        first argument is the compiled pattern, and the second is the name. The
-       third and fourth are pointers to variables which  are  updated  by  the
+       third  and  fourth  are  pointers to variables which are updated by the
        function. After it has run, they point to the first and last entries in
-       the name-to-number table  for  the  given  name.  The  function  itself
-       returns  the  length  of  each entry, or PCRE_ERROR_NOSUBSTRING (-7) if
-       there are none. The format of the table is described above in the  sec-
-       tion  entitled  Information about a pattern above.  Given all the rele-
-       vant entries for the name, you can extract each of their  numbers,  and
+       the  name-to-number  table  for  the  given  name.  The function itself
+       returns the length of each entry,  or  PCRE_ERROR_NOSUBSTRING  (-7)  if
+       there  are none. The format of the table is described above in the sec-
+       tion entitled Information about a pattern above.  Given all  the  rele-
+       vant  entries  for the name, you can extract each of their numbers, and
        hence the captured data, if any.
 
 
 FINDING ALL POSSIBLE MATCHES
 
-       The  traditional  matching  function  uses a similar algorithm to Perl,
+       The traditional matching function uses a  similar  algorithm  to  Perl,
        which stops when it finds the first match, starting at a given point in
-       the  subject.  If you want to find all possible matches, or the longest
-       possible match, consider using the alternative matching  function  (see
-       below)  instead.  If you cannot use the alternative function, but still
-       need to find all possible matches, you can kludge it up by  making  use
+       the subject. If you want to find all possible matches, or  the  longest
+       possible  match,  consider using the alternative matching function (see
+       below) instead. If you cannot use the alternative function,  but  still
+       need  to  find all possible matches, you can kludge it up by making use
        of the callout facility, which is described in the pcrecallout documen-
        tation.
 
        What you have to do is to insert a callout right at the end of the pat-
-       tern.   When your callout function is called, extract and save the cur-
-       rent matched substring. Then return  1,  which  forces  pcre_exec()  to
-       backtrack  and  try other alternatives. Ultimately, when it runs out of
+       tern.  When your callout function is called, extract and save the  cur-
+       rent  matched  substring.  Then  return  1, which forces pcre_exec() to
+       backtrack and try other alternatives. Ultimately, when it runs  out  of
        matches, pcre_exec() will yield PCRE_ERROR_NOMATCH.
 
 
 OBTAINING AN ESTIMATE OF STACK USAGE
 
-       Matching certain patterns using pcre_exec() can use a  lot  of  process
-       stack,  which  in  certain  environments can be rather limited in size.
-       Some users find it helpful to have an estimate of the amount  of  stack
-       that  is  used  by  pcre_exec(),  to help them set recursion limits, as
-       described in the pcrestack documentation. The estimate that  is  output
+       Matching  certain  patterns  using pcre_exec() can use a lot of process
+       stack, which in certain environments can be  rather  limited  in  size.
+       Some  users  find it helpful to have an estimate of the amount of stack
+       that is used by pcre_exec(), to help  them  set  recursion  limits,  as
+       described  in  the pcrestack documentation. The estimate that is output
        by pcretest when called with the -m and -C options is obtained by call-
-       ing pcre_exec with the values NULL, NULL, NULL, -999, and -999 for  its
+       ing  pcre_exec with the values NULL, NULL, NULL, -999, and -999 for its
        first five arguments.
 
-       Normally,  if  its  first  argument  is  NULL,  pcre_exec() immediately
-       returns the negative error code PCRE_ERROR_NULL, but with this  special
-       combination  of  arguments,  it returns instead a negative number whose
-       absolute value is the approximate stack frame size in bytes.  (A  nega-
-       tive  number  is  used so that it is clear that no match has happened.)
-       The value is approximate because in  some  cases,  recursive  calls  to
+       Normally, if  its  first  argument  is  NULL,  pcre_exec()  immediately
+       returns  the negative error code PCRE_ERROR_NULL, but with this special
+       combination of arguments, it returns instead a  negative  number  whose
+       absolute  value  is the approximate stack frame size in bytes. (A nega-
+       tive number is used so that it is clear that no  match  has  happened.)
+       The  value  is  approximate  because  in some cases, recursive calls to
        pcre_exec() occur when there are one or two additional variables on the
        stack.
 
-       If PCRE has been compiled to use the heap  instead  of  the  stack  for
-       recursion,  the  value  returned  is  the  size  of  each block that is
+       If  PCRE  has  been  compiled  to use the heap instead of the stack for
+       recursion, the value returned  is  the  size  of  each  block  that  is
        obtained from the heap.
 
 
@@ -4086,26 +4085,26 @@ MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
             int options, int *ovector, int ovecsize,
             int *workspace, int wscount);
 
-       The function pcre_dfa_exec()  is  called  to  match  a  subject  string
-       against  a  compiled pattern, using a matching algorithm that scans the
-       subject string just once, and does not backtrack.  This  has  different
-       characteristics  to  the  normal  algorithm, and is not compatible with
-       Perl. Some of the features of PCRE patterns are not  supported.  Never-
-       theless,  there are times when this kind of matching can be useful. For
-       a discussion of the two matching algorithms, and  a  list  of  features
-       that  pcre_dfa_exec() does not support, see the pcrematching documenta-
+       The  function  pcre_dfa_exec()  is  called  to  match  a subject string
+       against a compiled pattern, using a matching algorithm that  scans  the
+       subject  string  just  once, and does not backtrack. This has different
+       characteristics to the normal algorithm, and  is  not  compatible  with
+       Perl.  Some  of the features of PCRE patterns are not supported. Never-
+       theless, there are times when this kind of matching can be useful.  For
+       a  discussion  of  the  two matching algorithms, and a list of features
+       that pcre_dfa_exec() does not support, see the pcrematching  documenta-
        tion.
 
-       The arguments for the pcre_dfa_exec() function  are  the  same  as  for
+       The  arguments  for  the  pcre_dfa_exec()  function are the same as for
        pcre_exec(), plus two extras. The ovector argument is used in a differ-
-       ent way, and this is described below. The other  common  arguments  are
-       used  in  the  same way as for pcre_exec(), so their description is not
+       ent  way,  and  this is described below. The other common arguments are
+       used in the same way as for pcre_exec(), so their  description  is  not
        repeated here.
 
-       The two additional arguments provide workspace for  the  function.  The
-       workspace  vector  should  contain at least 20 elements. It is used for
+       The  two  additional  arguments provide workspace for the function. The
+       workspace vector should contain at least 20 elements. It  is  used  for
        keeping  track  of  multiple  paths  through  the  pattern  tree.  More
-       workspace  will  be  needed for patterns and subjects where there are a
+       workspace will be needed for patterns and subjects where  there  are  a
        lot of potential matches.
 
        Here is an example of a simple call to pcre_dfa_exec():
@@ -4127,55 +4126,55 @@ MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
 
    Option bits for pcre_dfa_exec()
 
-       The unused bits of the options argument  for  pcre_dfa_exec()  must  be
-       zero.  The  only  bits  that  may  be  set are PCRE_ANCHORED, PCRE_NEW-
+       The  unused  bits  of  the options argument for pcre_dfa_exec() must be
+       zero. The only bits  that  may  be  set  are  PCRE_ANCHORED,  PCRE_NEW-
        LINE_xxx,        PCRE_NOTBOL,        PCRE_NOTEOL,        PCRE_NOTEMPTY,
-       PCRE_NOTEMPTY_ATSTART,       PCRE_NO_UTF8_CHECK,      PCRE_BSR_ANYCRLF,
-       PCRE_BSR_UNICODE, PCRE_NO_START_OPTIMIZE, PCRE_PARTIAL_HARD,  PCRE_PAR-
-       TIAL_SOFT,  PCRE_DFA_SHORTEST,  and PCRE_DFA_RESTART.  All but the last
-       four of these are  exactly  the  same  as  for  pcre_exec(),  so  their
+       PCRE_NOTEMPTY_ATSTART,      PCRE_NO_UTF8_CHECK,       PCRE_BSR_ANYCRLF,
+       PCRE_BSR_UNICODE,  PCRE_NO_START_OPTIMIZE, PCRE_PARTIAL_HARD, PCRE_PAR-
+       TIAL_SOFT, PCRE_DFA_SHORTEST, and PCRE_DFA_RESTART.  All but  the  last
+       four  of  these  are  exactly  the  same  as  for pcre_exec(), so their
        description is not repeated here.
 
          PCRE_PARTIAL_HARD
          PCRE_PARTIAL_SOFT
 
-       These  have the same general effect as they do for pcre_exec(), but the
-       details are slightly  different.  When  PCRE_PARTIAL_HARD  is  set  for
-       pcre_dfa_exec(),  it  returns PCRE_ERROR_PARTIAL if the end of the sub-
-       ject is reached and there is still at least  one  matching  possibility
+       These have the same general effect as they do for pcre_exec(), but  the
+       details  are  slightly  different.  When  PCRE_PARTIAL_HARD  is set for
+       pcre_dfa_exec(), it returns PCRE_ERROR_PARTIAL if the end of  the  sub-
+       ject  is  reached  and there is still at least one matching possibility
        that requires additional characters. This happens even if some complete
        matches have also been found. When PCRE_PARTIAL_SOFT is set, the return
        code PCRE_ERROR_NOMATCH is converted into PCRE_ERROR_PARTIAL if the end
-       of the subject is reached, there have been  no  complete  matches,  but
-       there  is  still  at least one matching possibility. The portion of the
-       string that was inspected when the longest partial match was  found  is
-       set  as  the  first  matching  string  in  both cases.  There is a more
-       detailed discussion of partial and multi-segment matching,  with  exam-
+       of  the  subject  is  reached, there have been no complete matches, but
+       there is still at least one matching possibility. The  portion  of  the
+       string  that  was inspected when the longest partial match was found is
+       set as the first matching string  in  both  cases.   There  is  a  more
+       detailed  discussion  of partial and multi-segment matching, with exam-
        ples, in the pcrepartial documentation.
 
          PCRE_DFA_SHORTEST
 
-       Setting  the  PCRE_DFA_SHORTEST option causes the matching algorithm to
+       Setting the PCRE_DFA_SHORTEST option causes the matching  algorithm  to
        stop as soon as it has found one match. Because of the way the alterna-
-       tive  algorithm  works, this is necessarily the shortest possible match
+       tive algorithm works, this is necessarily the shortest  possible  match
        at the first possible matching point in the subject string.
 
          PCRE_DFA_RESTART
 
        When pcre_dfa_exec() returns a partial match, it is possible to call it
-       again,  with  additional  subject characters, and have it continue with
-       the same match. The PCRE_DFA_RESTART option requests this action;  when
-       it  is  set,  the workspace and wscount options must reference the same
-       vector as before because data about the match so far is  left  in  them
+       again, with additional subject characters, and have  it  continue  with
+       the  same match. The PCRE_DFA_RESTART option requests this action; when
+       it is set, the workspace and wscount options must  reference  the  same
+       vector  as  before  because data about the match so far is left in them
        after a partial match. There is more discussion of this facility in the
        pcrepartial documentation.
 
    Successful returns from pcre_dfa_exec()
 
-       When pcre_dfa_exec() succeeds, it may have matched more than  one  sub-
+       When  pcre_dfa_exec()  succeeds, it may have matched more than one sub-
        string in the subject. Note, however, that all the matches from one run
-       of the function start at the same point in  the  subject.  The  shorter
-       matches  are all initial substrings of the longer matches. For example,
+       of  the  function  start  at the same point in the subject. The shorter
+       matches are all initial substrings of the longer matches. For  example,
        if the pattern
 
          <.*>
@@ -4190,79 +4189,79 @@ MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
          <something> <something else>
          <something> <something else> <something further>
 
-       On success, the yield of the function is a number  greater  than  zero,
-       which  is  the  number of matched substrings. The substrings themselves
-       are returned in ovector. Each string uses two elements;  the  first  is
-       the  offset  to  the start, and the second is the offset to the end. In
-       fact, all the strings have the same start  offset.  (Space  could  have
-       been  saved by giving this only once, but it was decided to retain some
-       compatibility with the way pcre_exec() returns data,  even  though  the
+       On  success,  the  yield of the function is a number greater than zero,
+       which is the number of matched substrings.  The  substrings  themselves
+       are  returned  in  ovector. Each string uses two elements; the first is
+       the offset to the start, and the second is the offset to  the  end.  In
+       fact,  all  the  strings  have the same start offset. (Space could have
+       been saved by giving this only once, but it was decided to retain  some
+       compatibility  with  the  way pcre_exec() returns data, even though the
        meaning of the strings is different.)
 
        The strings are returned in reverse order of length; that is, the long-
-       est matching string is given first. If there were too many  matches  to
-       fit  into ovector, the yield of the function is zero, and the vector is
-       filled with the longest matches.  Unlike  pcre_exec(),  pcre_dfa_exec()
+       est  matching  string is given first. If there were too many matches to
+       fit into ovector, the yield of the function is zero, and the vector  is
+       filled  with  the  longest matches. Unlike pcre_exec(), pcre_dfa_exec()
        can use the entire ovector for returning matched strings.
 
-       NOTE:  PCRE's  "auto-possessification"  optimization usually applies to
-       character repeats at the end of a pattern (as well as internally).  For
-       example,  the  pattern "a\d+" is compiled as if it were "a\d++" because
+       NOTE: PCRE's "auto-possessification" optimization  usually  applies  to
+       character  repeats at the end of a pattern (as well as internally). For
+       example, the pattern "a\d+" is compiled as if it were  "a\d++"  because
        there is no point even considering the possibility of backtracking into
-       the  repeated digits. For DFA matching, this means that only one possi-
-       ble match is found. If you really do  want  multiple  matches  in  such
-       cases,   either   use   an   ungreedy   repeat  ("a\d+?")  or  set  the
+       the repeated digits. For DFA matching, this means that only one  possi-
+       ble  match  is  found.  If  you really do want multiple matches in such
+       cases,  either  use  an  ungreedy   repeat   ("a\d+?")   or   set   the
        PCRE_NO_AUTO_POSSESS option when compiling.
 
    Error returns from pcre_dfa_exec()
 
-       The pcre_dfa_exec() function returns a negative number when  it  fails.
-       Many  of  the  errors  are  the  same as for pcre_exec(), and these are
-       described above.  There are in addition the following errors  that  are
+       The  pcre_dfa_exec()  function returns a negative number when it fails.
+       Many of the errors are the same  as  for  pcre_exec(),  and  these  are
+       described  above.   There are in addition the following errors that are
        specific to pcre_dfa_exec():
 
          PCRE_ERROR_DFA_UITEM      (-16)
 
-       This  return is given if pcre_dfa_exec() encounters an item in the pat-
-       tern that it does not support, for instance, the use of \C  or  a  back
+       This return is given if pcre_dfa_exec() encounters an item in the  pat-
+       tern  that  it  does not support, for instance, the use of \C or a back
        reference.
 
          PCRE_ERROR_DFA_UCOND      (-17)
 
-       This  return  is  given  if pcre_dfa_exec() encounters a condition item
-       that uses a back reference for the condition, or a test  for  recursion
+       This return is given if pcre_dfa_exec()  encounters  a  condition  item
+       that  uses  a back reference for the condition, or a test for recursion
        in a specific group. These are not supported.
 
          PCRE_ERROR_DFA_UMLIMIT    (-18)
 
-       This  return  is given if pcre_dfa_exec() is called with an extra block
-       that contains a setting of  the  match_limit  or  match_limit_recursion
-       fields.  This  is  not  supported (these fields are meaningless for DFA
+       This return is given if pcre_dfa_exec() is called with an  extra  block
+       that  contains  a  setting  of the match_limit or match_limit_recursion
+       fields. This is not supported (these fields  are  meaningless  for  DFA
        matching).
 
          PCRE_ERROR_DFA_WSSIZE     (-19)
 
-       This return is given if  pcre_dfa_exec()  runs  out  of  space  in  the
+       This  return  is  given  if  pcre_dfa_exec()  runs  out of space in the
        workspace vector.
 
          PCRE_ERROR_DFA_RECURSE    (-20)
 
-       When  a  recursive subpattern is processed, the matching function calls
-       itself recursively, using private vectors for  ovector  and  workspace.
-       This  error  is  given  if  the output vector is not large enough. This
+       When a recursive subpattern is processed, the matching  function  calls
+       itself  recursively,  using  private vectors for ovector and workspace.
+       This error is given if the output vector  is  not  large  enough.  This
        should be extremely rare, as a vector of size 1000 is used.
 
          PCRE_ERROR_DFA_BADRESTART (-30)
 
-       When pcre_dfa_exec() is called with the PCRE_DFA_RESTART  option,  some
-       plausibility  checks  are  made on the contents of the workspace, which
-       should contain data about the previous partial match. If any  of  these
+       When  pcre_dfa_exec()  is called with the PCRE_DFA_RESTART option, some
+       plausibility checks are made on the contents of  the  workspace,  which
+       should  contain  data about the previous partial match. If any of these
        checks fail, this error is given.
 
 
 SEE ALSO
 
-       pcre16(3),   pcre32(3),  pcrebuild(3),  pcrecallout(3),  pcrecpp(3)(3),
+       pcre16(3),  pcre32(3),  pcrebuild(3),  pcrecallout(3),   pcrecpp(3)(3),
        pcrematching(3), pcrepartial(3), pcreposix(3), pcreprecompile(3), pcre-
        sample(3), pcrestack(3).
 
@@ -4276,8 +4275,8 @@ AUTHOR
 
 REVISION
 
-       Last updated: 09 February 2014
-       Copyright (c) 1997-2014 University of Cambridge.
+       Last updated: 18 December 2015
+       Copyright (c) 1997-2015 University of Cambridge.
 ------------------------------------------------------------------------------
 
 
@@ -4641,7 +4640,7 @@ DIFFERENCES BETWEEN PCRE AND PERL
        pattern names is not as general as Perl's. This is a consequence of the
        fact the PCRE works internally just with numbers, using an external ta-
        ble to translate between numbers and names. In  particular,  a  pattern
-       such  as  (?|(?<a>A)|(?<b)B),  where the two capturing parentheses have
+       such  as  (?|(?<a>A)|(?<b>B),  where the two capturing parentheses have
        the same number but different names, is not supported,  and  causes  an
        error  at compile time. If it were allowed, it would not be possible to
        distinguish which parentheses matched, because both names map  to  cap-
@@ -5029,55 +5028,56 @@ BACKSLASH
        ate the appropriate EBCDIC code values. The \c escape is  processed  as
        specified for Perl in the perlebcdic document. The only characters that
        are allowed after \c are A-Z, a-z, or one of @, [, \, ], ^,  _,  or  ?.
-       Any  other  character  provokes  a  compile-time error. The sequence \@
-       encodes character code 0; the letters (in either case)  encode  charac-
-       ters 1-26 (hex 01 to hex 1A); [, \, ], ^, and _ encode characters 27-31
-       (hex 1B to hex 1F), and \? becomes either 255 (hex FF) or 95 (hex 5F).
-
-       Thus, apart from \?, these escapes generate  the  same  character  code
-       values  as  they do in an ASCII environment, though the meanings of the
-       values mostly differ. For example, \G always generates  code  value  7,
+       Any  other  character  provokes  a compile-time error. The sequence \c@
+       encodes character code 0; after \c the letters (in either case)  encode
+       characters 1-26 (hex 01 to hex 1A); [, \, ], ^, and _ encode characters
+       27-31 (hex 1B to hex 1F), and \c? becomes either 255  (hex  FF)  or  95
+       (hex 5F).
+
+       Thus,  apart  from  \c?, these escapes generate the same character code
+       values as they do in an ASCII environment, though the meanings  of  the
+       values  mostly  differ. For example, \cG always generates code value 7,
        which is BEL in ASCII but DEL in EBCDIC.
 
-       The  sequence  \?  generates DEL (127, hex 7F) in an ASCII environment,
-       but because 127 is not a control character in  EBCDIC,  Perl  makes  it
-       generate  the  APC character. Unfortunately, there are several variants
-       of EBCDIC. In most of them the APC character has  the  value  255  (hex
-       FF),  but  in  the one Perl calls POSIX-BC its value is 95 (hex 5F). If
-       certain other characters have POSIX-BC values, PCRE makes  \?  generate
+       The sequence \c? generates DEL (127, hex 7F) in an  ASCII  environment,
+       but  because  127  is  not a control character in EBCDIC, Perl makes it
+       generate the APC character. Unfortunately, there are  several  variants
+       of  EBCDIC.  In  most  of them the APC character has the value 255 (hex
+       FF), but in the one Perl calls POSIX-BC its value is 95  (hex  5F).  If
+       certain  other characters have POSIX-BC values, PCRE makes \c? generate
        95; otherwise it generates 255.
 
-       After  \0  up  to two further octal digits are read. If there are fewer
-       than two digits, just  those  that  are  present  are  used.  Thus  the
+       After \0 up to two further octal digits are read. If  there  are  fewer
+       than  two  digits,  just  those  that  are  present  are used. Thus the
        sequence \0\x\015 specifies two binary zeros followed by a CR character
        (code value 13). Make sure you supply two digits after the initial zero
        if the pattern character that follows is itself an octal digit.
 
-       The  escape \o must be followed by a sequence of octal digits, enclosed
-       in braces. An error occurs if this is not the case. This  escape  is  a
-       recent  addition  to Perl; it provides way of specifying character code
-       points as octal numbers greater than 0777, and  it  also  allows  octal
+       The escape \o must be followed by a sequence of octal digits,  enclosed
+       in  braces.  An  error occurs if this is not the case. This escape is a
+       recent addition to Perl; it provides way of specifying  character  code
+       points  as  octal  numbers  greater than 0777, and it also allows octal
        numbers and back references to be unambiguously specified.
 
        For greater clarity and unambiguity, it is best to avoid following \ by
        a digit greater than zero. Instead, use \o{} or \x{} to specify charac-
-       ter  numbers,  and \g{} to specify back references. The following para-
+       ter numbers, and \g{} to specify back references. The  following  para-
        graphs describe the old, ambiguous syntax.
 
        The handling of a backslash followed by a digit other than 0 is compli-
-       cated,  and  Perl  has changed in recent releases, causing PCRE also to
+       cated, and Perl has changed in recent releases, causing  PCRE  also  to
        change. Outside a character class, PCRE reads the digit and any follow-
-       ing  digits  as  a  decimal number. If the number is less than 8, or if
-       there have been at least that many previous capturing left  parentheses
-       in  the expression, the entire sequence is taken as a back reference. A
-       description of how this works is given later, following the  discussion
+       ing digits as a decimal number. If the number is less  than  8,  or  if
+       there  have been at least that many previous capturing left parentheses
+       in the expression, the entire sequence is taken as a back reference.  A
+       description  of how this works is given later, following the discussion
        of parenthesized subpatterns.
 
-       Inside  a  character  class,  or  if  the decimal number following \ is
+       Inside a character class, or if  the  decimal  number  following  \  is
        greater than 7 and there have not been that many capturing subpatterns,
-       PCRE  handles \8 and \9 as the literal characters "8" and "9", and oth-
+       PCRE handles \8 and \9 as the literal characters "8" and "9", and  oth-
        erwise re-reads up to three octal digits following the backslash, using
-       them  to  generate  a  data character.  Any subsequent digits stand for
+       them to generate a data character.  Any  subsequent  digits  stand  for
        themselves. For example:
 
          \040   is another way of writing an ASCII space
@@ -5095,31 +5095,31 @@ BACKSLASH
          \81    is either a back reference, or the two
                    characters "8" and "1"
 
-       Note that octal values of 100 or greater that are specified using  this
-       syntax  must  not be introduced by a leading zero, because no more than
+       Note  that octal values of 100 or greater that are specified using this
+       syntax must not be introduced by a leading zero, because no  more  than
        three octal digits are ever read.
 
-       By default, after \x that is not followed by {, from zero to two  hexa-
-       decimal  digits  are  read (letters can be in upper or lower case). Any
+       By  default, after \x that is not followed by {, from zero to two hexa-
+       decimal digits are read (letters can be in upper or  lower  case).  Any
        number of hexadecimal digits may appear between \x{ and }. If a charac-
-       ter  other  than  a  hexadecimal digit appears between \x{ and }, or if
+       ter other than a hexadecimal digit appears between \x{  and  },  or  if
        there is no terminating }, an error occurs.
 
-       If the PCRE_JAVASCRIPT_COMPAT option is set, the interpretation  of  \x
-       is  as  just described only when it is followed by two hexadecimal dig-
-       its.  Otherwise, it matches a  literal  "x"  character.  In  JavaScript
+       If  the  PCRE_JAVASCRIPT_COMPAT option is set, the interpretation of \x
+       is as just described only when it is followed by two  hexadecimal  dig-
+       its.   Otherwise,  it  matches  a  literal "x" character. In JavaScript
        mode, support for code points greater than 256 is provided by \u, which
-       must be followed by four hexadecimal digits;  otherwise  it  matches  a
+       must  be  followed  by  four hexadecimal digits; otherwise it matches a
        literal "u" character.
 
        Characters whose value is less than 256 can be defined by either of the
-       two syntaxes for \x (or by \u in JavaScript mode). There is no  differ-
+       two  syntaxes for \x (or by \u in JavaScript mode). There is no differ-
        ence in the way they are handled. For example, \xdc is exactly the same
        as \x{dc} (or \u00dc in JavaScript mode).
 
    Constraints on character values
 
-       Characters that are specified using octal or  hexadecimal  numbers  are
+       Characters  that  are  specified using octal or hexadecimal numbers are
        limited to certain values, as follows:
 
          8-bit non-UTF mode    less than 0x100
@@ -5129,44 +5129,44 @@ BACKSLASH
          32-bit non-UTF mode   less than 0x100000000
          32-bit UTF-32 mode    less than 0x10ffff and a valid codepoint
 
-       Invalid  Unicode  codepoints  are  the  range 0xd800 to 0xdfff (the so-
+       Invalid Unicode codepoints are the range  0xd800  to  0xdfff  (the  so-
        called "surrogate" codepoints), and 0xffef.
 
    Escape sequences in character classes
 
        All the sequences that define a single character value can be used both
-       inside  and  outside character classes. In addition, inside a character
+       inside and outside character classes. In addition, inside  a  character
        class, \b is interpreted as the backspace character (hex 08).
 
-       \N is not allowed in a character class. \B, \R, and \X are not  special
-       inside  a  character  class.  Like other unrecognized escape sequences,
-       they are treated as  the  literal  characters  "B",  "R",  and  "X"  by
-       default,  but cause an error if the PCRE_EXTRA option is set. Outside a
+       \N  is not allowed in a character class. \B, \R, and \X are not special
+       inside a character class. Like  other  unrecognized  escape  sequences,
+       they  are  treated  as  the  literal  characters  "B",  "R", and "X" by
+       default, but cause an error if the PCRE_EXTRA option is set. Outside  a
        character class, these sequences have different meanings.
 
    Unsupported escape sequences
 
-       In Perl, the sequences \l, \L, \u, and \U are recognized by its  string
-       handler  and  used  to  modify  the  case  of  following characters. By
-       default, PCRE does not support these escape sequences. However, if  the
-       PCRE_JAVASCRIPT_COMPAT  option  is set, \U matches a "U" character, and
+       In  Perl, the sequences \l, \L, \u, and \U are recognized by its string
+       handler and used  to  modify  the  case  of  following  characters.  By
+       default,  PCRE does not support these escape sequences. However, if the
+       PCRE_JAVASCRIPT_COMPAT option is set, \U matches a "U"  character,  and
        \u can be used to define a character by code point, as described in the
        previous section.
 
    Absolute and relative back references
 
-       The  sequence  \g followed by an unsigned or a negative number, option-
-       ally enclosed in braces, is an absolute or relative back  reference.  A
+       The sequence \g followed by an unsigned or a negative  number,  option-
+       ally  enclosed  in braces, is an absolute or relative back reference. A
        named back reference can be coded as \g{name}. Back references are dis-
        cussed later, following the discussion of parenthesized subpatterns.
 
    Absolute and relative subroutine calls
 
-       For compatibility with Oniguruma, the non-Perl syntax \g followed by  a
+       For  compatibility with Oniguruma, the non-Perl syntax \g followed by a
        name or a number enclosed either in angle brackets or single quotes, is
-       an alternative syntax for referencing a subpattern as  a  "subroutine".
-       Details  are  discussed  later.   Note  that  \g{...} (Perl syntax) and
-       \g<...> (Oniguruma syntax) are not synonymous. The  former  is  a  back
+       an  alternative  syntax for referencing a subpattern as a "subroutine".
+       Details are discussed later.   Note  that  \g{...}  (Perl  syntax)  and
+       \g<...>  (Oniguruma  syntax)  are  not synonymous. The former is a back
        reference; the latter is a subroutine call.
 
    Generic character types
@@ -5185,59 +5185,59 @@ BACKSLASH
          \W     any "non-word" character
 
        There is also the single sequence \N, which matches a non-newline char-
-       acter.  This is the same as the "." metacharacter when  PCRE_DOTALL  is
-       not  set.  Perl also uses \N to match characters by name; PCRE does not
+       acter.   This  is the same as the "." metacharacter when PCRE_DOTALL is
+       not set. Perl also uses \N to match characters by name; PCRE  does  not
        support this.
 
-       Each pair of lower and upper case escape sequences partitions the  com-
-       plete  set  of  characters  into two disjoint sets. Any given character
-       matches one, and only one, of each pair. The sequences can appear  both
-       inside  and outside character classes. They each match one character of
-       the appropriate type. If the current matching point is at  the  end  of
-       the  subject string, all of them fail, because there is no character to
+       Each  pair of lower and upper case escape sequences partitions the com-
+       plete set of characters into two disjoint  sets.  Any  given  character
+       matches  one, and only one, of each pair. The sequences can appear both
+       inside and outside character classes. They each match one character  of
+       the  appropriate  type.  If the current matching point is at the end of
+       the subject string, all of them fail, because there is no character  to
        match.
 
-       For compatibility with Perl, \s did not used to match the VT  character
-       (code  11),  which  made it different from the the POSIX "space" class.
-       However, Perl added VT at release  5.18,  and  PCRE  followed  suit  at
-       release  8.34.  The  default  \s characters are now HT (9), LF (10), VT
-       (11), FF (12), CR (13), and space (32),  which  are  defined  as  white
+       For  compatibility with Perl, \s did not used to match the VT character
+       (code 11), which made it different from the the  POSIX  "space"  class.
+       However,  Perl  added  VT  at  release  5.18, and PCRE followed suit at
+       release 8.34. The default \s characters are now HT  (9),  LF  (10),  VT
+       (11),  FF  (12),  CR  (13),  and space (32), which are defined as white
        space in the "C" locale. This list may vary if locale-specific matching
-       is taking place. For example, in some locales the "non-breaking  space"
-       character  (\xA0)  is  recognized  as white space, and in others the VT
+       is  taking place. For example, in some locales the "non-breaking space"
+       character (\xA0) is recognized as white space, and  in  others  the  VT
        character is not.
 
-       A "word" character is an underscore or any character that is  a  letter
-       or  digit.   By  default,  the definition of letters and digits is con-
-       trolled by PCRE's low-valued character tables, and may vary if  locale-
-       specific  matching is taking place (see "Locale support" in the pcreapi
-       page). For example, in a French locale such  as  "fr_FR"  in  Unix-like
-       systems,  or "french" in Windows, some character codes greater than 127
-       are used for accented letters, and these are then matched  by  \w.  The
+       A  "word"  character is an underscore or any character that is a letter
+       or digit.  By default, the definition of letters  and  digits  is  con-
+       trolled  by PCRE's low-valued character tables, and may vary if locale-
+       specific matching is taking place (see "Locale support" in the  pcreapi
+       page).  For  example,  in  a French locale such as "fr_FR" in Unix-like
+       systems, or "french" in Windows, some character codes greater than  127
+       are  used  for  accented letters, and these are then matched by \w. The
        use of locales with Unicode is discouraged.
 
-       By  default,  characters  whose  code points are greater than 127 never
+       By default, characters whose code points are  greater  than  127  never
        match \d, \s, or \w, and always match \D, \S, and \W, although this may
-       vary  for characters in the range 128-255 when locale-specific matching
-       is happening.  These escape sequences retain  their  original  meanings
-       from  before  Unicode support was available, mainly for efficiency rea-
-       sons. If PCRE is  compiled  with  Unicode  property  support,  and  the
-       PCRE_UCP  option is set, the behaviour is changed so that Unicode prop-
+       vary for characters in the range 128-255 when locale-specific  matching
+       is  happening.   These  escape sequences retain their original meanings
+       from before Unicode support was available, mainly for  efficiency  rea-
+       sons.  If  PCRE  is  compiled  with  Unicode  property support, and the
+       PCRE_UCP option is set, the behaviour is changed so that Unicode  prop-
        erties are used to determine character types, as follows:
 
          \d  any character that matches \p{Nd} (decimal digit)
          \s  any character that matches \p{Z} or \h or \v
          \w  any character that matches \p{L} or \p{N}, plus underscore
 
-       The upper case escapes match the inverse sets of characters. Note  that
-       \d  matches  only decimal digits, whereas \w matches any Unicode digit,
-       as well as any Unicode letter, and underscore. Note also that  PCRE_UCP
-       affects  \b,  and  \B  because  they are defined in terms of \w and \W.
+       The  upper case escapes match the inverse sets of characters. Note that
+       \d matches only decimal digits, whereas \w matches any  Unicode  digit,
+       as  well as any Unicode letter, and underscore. Note also that PCRE_UCP
+       affects \b, and \B because they are defined in  terms  of  \w  and  \W.
        Matching these sequences is noticeably slower when PCRE_UCP is set.
 
-       The sequences \h, \H, \v, and \V are features that were added  to  Perl
-       at  release  5.10. In contrast to the other sequences, which match only
-       ASCII characters by default, these  always  match  certain  high-valued
+       The  sequences  \h, \H, \v, and \V are features that were added to Perl
+       at release 5.10. In contrast to the other sequences, which  match  only
+       ASCII  characters  by  default,  these always match certain high-valued
        code points, whether or not PCRE_UCP is set. The horizontal space char-
        acters are:
 
@@ -5276,110 +5276,110 @@ BACKSLASH
 
    Newline sequences
 
-       Outside  a  character class, by default, the escape sequence \R matches
-       any Unicode newline sequence. In 8-bit non-UTF-8 mode \R is  equivalent
+       Outside a character class, by default, the escape sequence  \R  matches
+       any  Unicode newline sequence. In 8-bit non-UTF-8 mode \R is equivalent
        to the following:
 
          (?>\r\n|\n|\x0b|\f|\r|\x85)
 
-       This  is  an  example  of an "atomic group", details of which are given
+       This is an example of an "atomic group", details  of  which  are  given
        below.  This particular group matches either the two-character sequence
-       CR  followed  by  LF,  or  one  of  the single characters LF (linefeed,
-       U+000A), VT (vertical tab, U+000B), FF (form feed,  U+000C),  CR  (car-
-       riage  return,  U+000D),  or NEL (next line, U+0085). The two-character
+       CR followed by LF, or  one  of  the  single  characters  LF  (linefeed,
+       U+000A),  VT  (vertical  tab, U+000B), FF (form feed, U+000C), CR (car-
+       riage return, U+000D), or NEL (next line,  U+0085).  The  two-character
        sequence is treated as a single unit that cannot be split.
 
-       In other modes, two additional characters whose codepoints are  greater
+       In  other modes, two additional characters whose codepoints are greater
        than 255 are added: LS (line separator, U+2028) and PS (paragraph sepa-
-       rator, U+2029).  Unicode character property support is not  needed  for
+       rator,  U+2029).   Unicode character property support is not needed for
        these characters to be recognized.
 
        It is possible to restrict \R to match only CR, LF, or CRLF (instead of
-       the complete set  of  Unicode  line  endings)  by  setting  the  option
+       the  complete  set  of  Unicode  line  endings)  by  setting the option
        PCRE_BSR_ANYCRLF either at compile time or when the pattern is matched.
        (BSR is an abbrevation for "backslash R".) This can be made the default
-       when  PCRE  is  built;  if this is the case, the other behaviour can be
-       requested via the PCRE_BSR_UNICODE option.   It  is  also  possible  to
-       specify  these  settings  by  starting a pattern string with one of the
+       when PCRE is built; if this is the case, the  other  behaviour  can  be
+       requested  via  the  PCRE_BSR_UNICODE  option.   It is also possible to
+       specify these settings by starting a pattern string  with  one  of  the
        following sequences:
 
          (*BSR_ANYCRLF)   CR, LF, or CRLF only
          (*BSR_UNICODE)   any Unicode newline sequence
 
        These override the default and the options given to the compiling func-
-       tion,  but  they  can  themselves  be  overridden by options given to a
-       matching function. Note that these  special  settings,  which  are  not
-       Perl-compatible,  are  recognized  only at the very start of a pattern,
-       and that they must be in upper case.  If  more  than  one  of  them  is
-       present,  the  last  one is used. They can be combined with a change of
+       tion, but they can themselves be  overridden  by  options  given  to  a
+       matching  function.  Note  that  these  special settings, which are not
+       Perl-compatible, are recognized only at the very start  of  a  pattern,
+       and  that  they  must  be  in  upper  case. If more than one of them is
+       present, the last one is used. They can be combined with  a  change  of
        newline convention; for example, a pattern can start with:
 
          (*ANY)(*BSR_ANYCRLF)
 
-       They can also be combined with the (*UTF8), (*UTF16), (*UTF32),  (*UTF)
+       They  can also be combined with the (*UTF8), (*UTF16), (*UTF32), (*UTF)
        or (*UCP) special sequences. Inside a character class, \R is treated as
-       an unrecognized escape sequence, and  so  matches  the  letter  "R"  by
+       an  unrecognized  escape  sequence,  and  so  matches the letter "R" by
        default, but causes an error if PCRE_EXTRA is set.
 
    Unicode character properties
 
        When PCRE is built with Unicode character property support, three addi-
-       tional escape sequences that match characters with specific  properties
-       are  available.   When  in 8-bit non-UTF-8 mode, these sequences are of
-       course limited to testing characters whose  codepoints  are  less  than
+       tional  escape sequences that match characters with specific properties
+       are available.  When in 8-bit non-UTF-8 mode, these  sequences  are  of
+       course  limited  to  testing  characters whose codepoints are less than
        256, but they do work in this mode.  The extra escape sequences are:
 
          \p{xx}   a character with the xx property
          \P{xx}   a character without the xx property
          \X       a Unicode extended grapheme cluster
 
-       The  property  names represented by xx above are limited to the Unicode
+       The property names represented by xx above are limited to  the  Unicode
        script names, the general category properties, "Any", which matches any
-       character   (including  newline),  and  some  special  PCRE  properties
-       (described in the next section).  Other Perl properties such as  "InMu-
-       sicalSymbols"  are  not  currently supported by PCRE. Note that \P{Any}
+       character  (including  newline),  and  some  special  PCRE   properties
+       (described  in the next section).  Other Perl properties such as "InMu-
+       sicalSymbols" are not currently supported by PCRE.  Note  that  \P{Any}
        does not match any characters, so always causes a match failure.
 
        Sets of Unicode characters are defined as belonging to certain scripts.
-       A  character from one of these sets can be matched using a script name.
+       A character from one of these sets can be matched using a script  name.
        For example:
 
          \p{Greek}
          \P{Han}
 
-       Those that are not part of an identified script are lumped together  as
+       Those  that are not part of an identified script are lumped together as
        "Common". The current list of scripts is:
 
-       Arabic,  Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali,
-       Bopomofo, Brahmi, Braille, Buginese, Buhid,  Canadian_Aboriginal,  Car-
+       Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak,  Bengali,
+       Bopomofo,  Brahmi,  Braille, Buginese, Buhid, Canadian_Aboriginal, Car-
        ian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cunei-
        form, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hiero-
        glyphs,  Elbasan,  Ethiopic,  Georgian,  Glagolitic,  Gothic,  Grantha,
-       Greek, Gujarati, Gurmukhi,  Han,  Hangul,  Hanunoo,  Hebrew,  Hiragana,
-       Imperial_Aramaic,     Inherited,     Inscriptional_Pahlavi,    Inscrip-
-       tional_Parthian,  Javanese,  Kaithi,   Kannada,   Katakana,   Kayah_Li,
-       Kharoshthi,  Khmer,  Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Lin-
-       ear_A, Linear_B, Lisu, Lycian, Lydian,  Mahajani,  Malayalam,  Mandaic,
-       Manichaean,      Meetei_Mayek,     Mende_Kikakui,     Meroitic_Cursive,
-       Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro,  Myanmar,  Nabataean,
-       New_Tai_Lue,   Nko,  Ogham,  Ol_Chiki,  Old_Italic,  Old_North_Arabian,
+       Greek,  Gujarati,  Gurmukhi,  Han,  Hangul,  Hanunoo, Hebrew, Hiragana,
+       Imperial_Aramaic,    Inherited,     Inscriptional_Pahlavi,     Inscrip-
+       tional_Parthian,   Javanese,   Kaithi,   Kannada,  Katakana,  Kayah_Li,
+       Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha,  Limbu,  Lin-
+       ear_A,  Linear_B,  Lisu,  Lycian, Lydian, Mahajani, Malayalam, Mandaic,
+       Manichaean,     Meetei_Mayek,     Mende_Kikakui,      Meroitic_Cursive,
+       Meroitic_Hieroglyphs,  Miao,  Modi, Mongolian, Mro, Myanmar, Nabataean,
+       New_Tai_Lue,  Nko,  Ogham,  Ol_Chiki,  Old_Italic,   Old_North_Arabian,
        Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya,
        Pahawh_Hmong,    Palmyrene,    Pau_Cin_Hau,    Phags_Pa,    Phoenician,
-       Psalter_Pahlavi, Rejang, Runic, Samaritan,  Saurashtra,  Sharada,  Sha-
-       vian,  Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac,
-       Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet,  Takri,  Tamil,  Telugu,
-       Thaana,  Thai,  Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi,
+       Psalter_Pahlavi,  Rejang,  Runic,  Samaritan, Saurashtra, Sharada, Sha-
+       vian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri,  Syriac,
+       Tagalog,  Tagbanwa,  Tai_Le,  Tai_Tham, Tai_Viet, Takri, Tamil, Telugu,
+       Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic,  Vai,  Warang_Citi,
        Yi.
 
        Each character has exactly one Unicode general category property, spec-
-       ified  by a two-letter abbreviation. For compatibility with Perl, nega-
-       tion can be specified by including a  circumflex  between  the  opening
-       brace  and  the  property  name.  For  example,  \p{^Lu} is the same as
+       ified by a two-letter abbreviation. For compatibility with Perl,  nega-
+       tion  can  be  specified  by including a circumflex between the opening
+       brace and the property name.  For  example,  \p{^Lu}  is  the  same  as
        \P{Lu}.
 
        If only one letter is specified with \p or \P, it includes all the gen-
-       eral  category properties that start with that letter. In this case, in
-       the absence of negation, the curly brackets in the escape sequence  are
+       eral category properties that start with that letter. In this case,  in
+       the  absence of negation, the curly brackets in the escape sequence are
        optional; these two examples have the same effect:
 
          \p{L}
@@ -5431,73 +5431,73 @@ BACKSLASH
          Zp    Paragraph separator
          Zs    Space separator
 
-       The  special property L& is also supported: it matches a character that
-       has the Lu, Ll, or Lt property, in other words, a letter  that  is  not
+       The special property L& is also supported: it matches a character  that
+       has  the  Lu,  Ll, or Lt property, in other words, a letter that is not
        classified as a modifier or "other".
 
-       The  Cs  (Surrogate)  property  applies only to characters in the range
-       U+D800 to U+DFFF. Such characters are not valid in Unicode strings  and
-       so  cannot  be  tested  by  PCRE, unless UTF validity checking has been
+       The Cs (Surrogate) property applies only to  characters  in  the  range
+       U+D800  to U+DFFF. Such characters are not valid in Unicode strings and
+       so cannot be tested by PCRE, unless  UTF  validity  checking  has  been
        turned    off    (see    the    discussion    of    PCRE_NO_UTF8_CHECK,
-       PCRE_NO_UTF16_CHECK  and PCRE_NO_UTF32_CHECK in the pcreapi page). Perl
+       PCRE_NO_UTF16_CHECK and PCRE_NO_UTF32_CHECK in the pcreapi page).  Perl
        does not support the Cs property.
 
-       The long synonyms for  property  names  that  Perl  supports  (such  as
-       \p{Letter})  are  not  supported by PCRE, nor is it permitted to prefix
+       The  long  synonyms  for  property  names  that  Perl supports (such as
+       \p{Letter}) are not supported by PCRE, nor is it  permitted  to  prefix
        any of these properties with "Is".
 
        No character that is in the Unicode table has the Cn (unassigned) prop-
        erty.  Instead, this property is assumed for any code point that is not
        in the Unicode table.
 
-       Specifying caseless matching does not affect  these  escape  sequences.
-       For  example,  \p{Lu}  always  matches only upper case letters. This is
+       Specifying  caseless  matching  does not affect these escape sequences.
+       For example, \p{Lu} always matches only upper  case  letters.  This  is
        different from the behaviour of current versions of Perl.
 
-       Matching characters by Unicode property is not fast, because  PCRE  has
-       to  do  a  multistage table lookup in order to find a character's prop-
+       Matching  characters  by Unicode property is not fast, because PCRE has
+       to do a multistage table lookup in order to find  a  character's  prop-
        erty. That is why the traditional escape sequences such as \d and \w do
        not use Unicode properties in PCRE by default, though you can make them
-       do so by setting the PCRE_UCP option or by starting  the  pattern  with
+       do  so  by  setting the PCRE_UCP option or by starting the pattern with
        (*UCP).
 
    Extended grapheme clusters
 
-       The  \X  escape  matches  any number of Unicode characters that form an
+       The \X escape matches any number of Unicode  characters  that  form  an
        "extended grapheme cluster", and treats the sequence as an atomic group
-       (see  below).   Up  to and including release 8.31, PCRE matched an ear-
+       (see below).  Up to and including release 8.31, PCRE  matched  an  ear-
        lier, simpler definition that was equivalent to
 
          (?>\PM\pM*)
 
-       That is, it matched a character without the "mark"  property,  followed
-       by  zero  or  more characters with the "mark" property. Characters with
-       the "mark" property are typically non-spacing accents that  affect  the
+       That  is,  it matched a character without the "mark" property, followed
+       by zero or more characters with the "mark"  property.  Characters  with
+       the  "mark"  property are typically non-spacing accents that affect the
        preceding character.
 
-       This  simple definition was extended in Unicode to include more compli-
-       cated kinds of composite character by giving each character a  grapheme
-       breaking  property,  and  creating  rules  that use these properties to
-       define the boundaries of extended grapheme  clusters.  In  releases  of
+       This simple definition was extended in Unicode to include more  compli-
+       cated  kinds of composite character by giving each character a grapheme
+       breaking property, and creating rules  that  use  these  properties  to
+       define  the  boundaries  of  extended grapheme clusters. In releases of
        PCRE later than 8.31, \X matches one of these clusters.
 
-       \X  always  matches  at least one character. Then it decides whether to
+       \X always matches at least one character. Then it  decides  whether  to
        add additional characters according to the following rules for ending a
        cluster:
 
        1. End at the end of the subject string.
 
-       2.  Do not end between CR and LF; otherwise end after any control char-
+       2. Do not end between CR and LF; otherwise end after any control  char-
        acter.
 
-       3. Do not break Hangul (a Korean  script)  syllable  sequences.  Hangul
-       characters  are of five types: L, V, T, LV, and LVT. An L character may
-       be followed by an L, V, LV, or LVT character; an LV or V character  may
+       3.  Do  not  break  Hangul (a Korean script) syllable sequences. Hangul
+       characters are of five types: L, V, T, LV, and LVT. An L character  may
+       be  followed by an L, V, LV, or LVT character; an LV or V character may
        be followed by a V or T character; an LVT or T character may be follwed
        only by a T character.
 
-       4. Do not end before extending characters or spacing marks.  Characters
-       with  the  "mark"  property  always have the "extend" grapheme breaking
+       4.  Do not end before extending characters or spacing marks. Characters
+       with the "mark" property always have  the  "extend"  grapheme  breaking
        property.
 
        5. Do not end after prepend characters.
@@ -5506,9 +5506,9 @@ BACKSLASH
 
    PCRE's additional properties
 
-       As well as the standard Unicode properties described above,  PCRE  sup-
-       ports  four  more  that  make it possible to convert traditional escape
-       sequences such as \w and \s to use Unicode properties. PCRE uses  these
+       As  well  as the standard Unicode properties described above, PCRE sup-
+       ports four more that make it possible  to  convert  traditional  escape
+       sequences  such as \w and \s to use Unicode properties. PCRE uses these
        non-standard, non-Perl properties internally when PCRE_UCP is set. How-
        ever, they may also be used explicitly. These properties are:
 
@@ -5517,54 +5517,54 @@ BACKSLASH
          Xsp   Any Perl space character
          Xwd   Any Perl "word" character
 
-       Xan matches characters that have either the L (letter) or the  N  (num-
-       ber)  property. Xps matches the characters tab, linefeed, vertical tab,
-       form feed, or carriage return, and any other character that has  the  Z
-       (separator)  property.  Xsp is the same as Xps; it used to exclude ver-
-       tical tab, for Perl compatibility, but Perl changed, and so  PCRE  fol-
-       lowed  at  release  8.34.  Xwd matches the same characters as Xan, plus
+       Xan  matches  characters that have either the L (letter) or the N (num-
+       ber) property. Xps matches the characters tab, linefeed, vertical  tab,
+       form  feed,  or carriage return, and any other character that has the Z
+       (separator) property.  Xsp is the same as Xps; it used to exclude  ver-
+       tical  tab,  for Perl compatibility, but Perl changed, and so PCRE fol-
+       lowed at release 8.34. Xwd matches the same  characters  as  Xan,  plus
        underscore.
 
-       There is another non-standard property, Xuc, which matches any  charac-
-       ter  that  can  be represented by a Universal Character Name in C++ and
-       other programming languages. These are the characters $,  @,  `  (grave
-       accent),  and  all  characters with Unicode code points greater than or
-       equal to U+00A0, except for the surrogates U+D800 to U+DFFF. Note  that
-       most  base  (ASCII) characters are excluded. (Universal Character Names
-       are of the form \uHHHH or \UHHHHHHHH where H is  a  hexadecimal  digit.
+       There  is another non-standard property, Xuc, which matches any charac-
+       ter that can be represented by a Universal Character Name  in  C++  and
+       other  programming  languages.  These are the characters $, @, ` (grave
+       accent), and all characters with Unicode code points  greater  than  or
+       equal  to U+00A0, except for the surrogates U+D800 to U+DFFF. Note that
+       most base (ASCII) characters are excluded. (Universal  Character  Names
+       are  of  the  form \uHHHH or \UHHHHHHHH where H is a hexadecimal digit.
        Note that the Xuc property does not match these sequences but the char-
        acters that they represent.)
 
    Resetting the match start
 
-       The escape sequence \K causes any previously matched characters not  to
+       The  escape sequence \K causes any previously matched characters not to
        be included in the final matched sequence. For example, the pattern:
 
          foo\Kbar
 
-       matches  "foobar",  but reports that it has matched "bar". This feature
-       is similar to a lookbehind assertion (described  below).   However,  in
-       this  case, the part of the subject before the real match does not have
-       to be of fixed length, as lookbehind assertions do. The use of \K  does
-       not  interfere  with  the setting of captured substrings.  For example,
+       matches "foobar", but reports that it has matched "bar".  This  feature
+       is  similar  to  a lookbehind assertion (described below).  However, in
+       this case, the part of the subject before the real match does not  have
+       to  be of fixed length, as lookbehind assertions do. The use of \K does
+       not interfere with the setting of captured  substrings.   For  example,
        when the pattern
 
          (foo)\Kbar
 
        matches "foobar", the first substring is still set to "foo".
 
-       Perl documents that the use  of  \K  within  assertions  is  "not  well
-       defined".  In  PCRE,  \K  is  acted upon when it occurs inside positive
-       assertions, but is ignored in negative assertions.  Note  that  when  a
-       pattern  such  as (?=ab\K) matches, the reported start of the match can
+       Perl  documents  that  the  use  of  \K  within assertions is "not well
+       defined". In PCRE, \K is acted upon  when  it  occurs  inside  positive
+       assertions,  but  is  ignored  in negative assertions. Note that when a
+       pattern such as (?=ab\K) matches, the reported start of the  match  can
        be greater than the end of the match.
 
    Simple assertions
 
-       The final use of backslash is for certain simple assertions. An  asser-
-       tion  specifies a condition that has to be met at a particular point in
-       a match, without consuming any characters from the subject string.  The
-       use  of subpatterns for more complicated assertions is described below.
+       The  final use of backslash is for certain simple assertions. An asser-
+       tion specifies a condition that has to be met at a particular point  in
+       a  match, without consuming any characters from the subject string. The
+       use of subpatterns for more complicated assertions is described  below.
        The backslashed assertions are:
 
          \b     matches at a word boundary
@@ -5575,161 +5575,161 @@ BACKSLASH
          \z     matches only at the end of the subject
          \G     matches at the first matching position in the subject
 
-       Inside a character class, \b has a different meaning;  it  matches  the
-       backspace  character.  If  any  other  of these assertions appears in a
-       character class, by default it matches the corresponding literal  char-
+       Inside  a  character  class, \b has a different meaning; it matches the
+       backspace character. If any other of  these  assertions  appears  in  a
+       character  class, by default it matches the corresponding literal char-
        acter  (for  example,  \B  matches  the  letter  B).  However,  if  the
-       PCRE_EXTRA option is set, an "invalid escape sequence" error is  gener-
+       PCRE_EXTRA  option is set, an "invalid escape sequence" error is gener-
        ated instead.
 
-       A  word  boundary is a position in the subject string where the current
-       character and the previous character do not both match \w or  \W  (i.e.
-       one  matches  \w  and the other matches \W), or the start or end of the
-       string if the first or last character matches \w,  respectively.  In  a
-       UTF  mode,  the  meanings  of  \w  and \W can be changed by setting the
-       PCRE_UCP option. When this is done, it also affects \b and \B.  Neither
-       PCRE  nor  Perl has a separate "start of word" or "end of word" metase-
-       quence. However, whatever follows \b normally determines which  it  is.
+       A word boundary is a position in the subject string where  the  current
+       character  and  the previous character do not both match \w or \W (i.e.
+       one matches \w and the other matches \W), or the start or  end  of  the
+       string  if  the  first or last character matches \w, respectively. In a
+       UTF mode, the meanings of \w and \W  can  be  changed  by  setting  the
+       PCRE_UCP  option. When this is done, it also affects \b and \B. Neither
+       PCRE nor Perl has a separate "start of word" or "end of  word"  metase-
+       quence.  However,  whatever follows \b normally determines which it is.
        For example, the fragment \ba matches "a" at the start of a word.
 
-       The  \A,  \Z,  and \z assertions differ from the traditional circumflex
+       The \A, \Z, and \z assertions differ from  the  traditional  circumflex
        and dollar (described in the next section) in that they only ever match
-       at  the  very start and end of the subject string, whatever options are
-       set. Thus, they are independent of multiline mode. These  three  asser-
+       at the very start and end of the subject string, whatever  options  are
+       set.  Thus,  they are independent of multiline mode. These three asser-
        tions are not affected by the PCRE_NOTBOL or PCRE_NOTEOL options, which
-       affect only the behaviour of the circumflex and dollar  metacharacters.
-       However,  if the startoffset argument of pcre_exec() is non-zero, indi-
+       affect  only the behaviour of the circumflex and dollar metacharacters.
+       However, if the startoffset argument of pcre_exec() is non-zero,  indi-
        cating that matching is to start at a point other than the beginning of
-       the  subject,  \A  can never match. The difference between \Z and \z is
+       the subject, \A can never match. The difference between \Z  and  \z  is
        that \Z matches before a newline at the end of the string as well as at
        the very end, whereas \z matches only at the end.
 
-       The  \G assertion is true only when the current matching position is at
-       the start point of the match, as specified by the startoffset  argument
-       of  pcre_exec().  It  differs  from \A when the value of startoffset is
-       non-zero. By calling pcre_exec() multiple times with appropriate  argu-
+       The \G assertion is true only when the current matching position is  at
+       the  start point of the match, as specified by the startoffset argument
+       of pcre_exec(). It differs from \A when the  value  of  startoffset  is
+       non-zero.  By calling pcre_exec() multiple times with appropriate argu-
        ments, you can mimic Perl's /g option, and it is in this kind of imple-
        mentation where \G can be useful.
 
-       Note, however, that PCRE's interpretation of \G, as the  start  of  the
+       Note,  however,  that  PCRE's interpretation of \G, as the start of the
        current match, is subtly different from Perl's, which defines it as the
-       end of the previous match. In Perl, these can  be  different  when  the
-       previously  matched  string was empty. Because PCRE does just one match
+       end  of  the  previous  match. In Perl, these can be different when the
+       previously matched string was empty. Because PCRE does just  one  match
        at a time, it cannot reproduce this behaviour.
 
-       If all the alternatives of a pattern begin with \G, the  expression  is
+       If  all  the alternatives of a pattern begin with \G, the expression is
        anchored to the starting match position, and the "anchored" flag is set
        in the compiled regular expression.
 
 
 CIRCUMFLEX AND DOLLAR
 
-       The circumflex and dollar  metacharacters  are  zero-width  assertions.
-       That  is,  they test for a particular condition being true without con-
+       The  circumflex  and  dollar  metacharacters are zero-width assertions.
+       That is, they test for a particular condition being true  without  con-
        suming any characters from the subject string.
 
        Outside a character class, in the default matching mode, the circumflex
-       character  is  an  assertion  that is true only if the current matching
-       point is at the start of the subject string. If the  startoffset  argu-
-       ment  of  pcre_exec()  is  non-zero,  circumflex can never match if the
-       PCRE_MULTILINE option is unset. Inside a  character  class,  circumflex
+       character is an assertion that is true only  if  the  current  matching
+       point  is  at the start of the subject string. If the startoffset argu-
+       ment of pcre_exec() is non-zero, circumflex  can  never  match  if  the
+       PCRE_MULTILINE  option  is  unset. Inside a character class, circumflex
        has an entirely different meaning (see below).
 
-       Circumflex  need  not be the first character of the pattern if a number
-       of alternatives are involved, but it should be the first thing in  each
-       alternative  in  which  it appears if the pattern is ever to match that
-       branch. If all possible alternatives start with a circumflex, that  is,
-       if  the  pattern  is constrained to match only at the start of the sub-
-       ject, it is said to be an "anchored" pattern.  (There  are  also  other
+       Circumflex need not be the first character of the pattern if  a  number
+       of  alternatives are involved, but it should be the first thing in each
+       alternative in which it appears if the pattern is ever  to  match  that
+       branch.  If all possible alternatives start with a circumflex, that is,
+       if the pattern is constrained to match only at the start  of  the  sub-
+       ject,  it  is  said  to be an "anchored" pattern. (There are also other
        constructs that can cause a pattern to be anchored.)
 
-       The  dollar  character is an assertion that is true only if the current
-       matching point is at the end of  the  subject  string,  or  immediately
-       before  a newline at the end of the string (by default). Note, however,
-       that it does not actually match the newline. Dollar  need  not  be  the
+       The dollar character is an assertion that is true only if  the  current
+       matching  point  is  at  the  end of the subject string, or immediately
+       before a newline at the end of the string (by default). Note,  however,
+       that  it  does  not  actually match the newline. Dollar need not be the
        last character of the pattern if a number of alternatives are involved,
-       but it should be the last item in any branch in which it appears.  Dol-
+       but  it should be the last item in any branch in which it appears. Dol-
        lar has no special meaning in a character class.
 
-       The  meaning  of  dollar  can be changed so that it matches only at the
-       very end of the string, by setting the  PCRE_DOLLAR_ENDONLY  option  at
+       The meaning of dollar can be changed so that it  matches  only  at  the
+       very  end  of  the string, by setting the PCRE_DOLLAR_ENDONLY option at
        compile time. This does not affect the \Z assertion.
 
        The meanings of the circumflex and dollar characters are changed if the
-       PCRE_MULTILINE option is set. When  this  is  the  case,  a  circumflex
-       matches  immediately after internal newlines as well as at the start of
-       the subject string. It does not match after a  newline  that  ends  the
-       string.  A dollar matches before any newlines in the string, as well as
-       at the very end, when PCRE_MULTILINE is set. When newline is  specified
-       as  the  two-character  sequence CRLF, isolated CR and LF characters do
+       PCRE_MULTILINE  option  is  set.  When  this  is the case, a circumflex
+       matches immediately after internal newlines as well as at the start  of
+       the  subject  string.  It  does not match after a newline that ends the
+       string. A dollar matches before any newlines in the string, as well  as
+       at  the very end, when PCRE_MULTILINE is set. When newline is specified
+       as the two-character sequence CRLF, isolated CR and  LF  characters  do
        not indicate newlines.
 
-       For example, the pattern /^abc$/ matches the subject string  "def\nabc"
-       (where  \n  represents a newline) in multiline mode, but not otherwise.
-       Consequently, patterns that are anchored in single  line  mode  because
-       all  branches  start  with  ^ are not anchored in multiline mode, and a
-       match for circumflex is  possible  when  the  startoffset  argument  of
-       pcre_exec()  is  non-zero. The PCRE_DOLLAR_ENDONLY option is ignored if
+       For  example, the pattern /^abc$/ matches the subject string "def\nabc"
+       (where \n represents a newline) in multiline mode, but  not  otherwise.
+       Consequently,  patterns  that  are anchored in single line mode because
+       all branches start with ^ are not anchored in  multiline  mode,  and  a
+       match  for  circumflex  is  possible  when  the startoffset argument of
+       pcre_exec() is non-zero. The PCRE_DOLLAR_ENDONLY option is  ignored  if
        PCRE_MULTILINE is set.
 
-       Note that the sequences \A, \Z, and \z can be used to match  the  start
-       and  end of the subject in both modes, and if all branches of a pattern
-       start with \A it is always anchored, whether or not  PCRE_MULTILINE  is
+       Note  that  the sequences \A, \Z, and \z can be used to match the start
+       and end of the subject in both modes, and if all branches of a  pattern
+       start  with  \A it is always anchored, whether or not PCRE_MULTILINE is
        set.
 
 
 FULL STOP (PERIOD, DOT) AND \N
 
        Outside a character class, a dot in the pattern matches any one charac-
-       ter in the subject string except (by default) a character  that  signi-
+       ter  in  the subject string except (by default) a character that signi-
        fies the end of a line.
 
-       When  a line ending is defined as a single character, dot never matches
-       that character; when the two-character sequence CRLF is used, dot  does
-       not  match  CR  if  it  is immediately followed by LF, but otherwise it
-       matches all characters (including isolated CRs and LFs). When any  Uni-
-       code  line endings are being recognized, dot does not match CR or LF or
+       When a line ending is defined as a single character, dot never  matches
+       that  character; when the two-character sequence CRLF is used, dot does
+       not match CR if it is immediately followed  by  LF,  but  otherwise  it
+       matches  all characters (including isolated CRs and LFs). When any Uni-
+       code line endings are being recognized, dot does not match CR or LF  or
        any of the other line ending characters.
 
-       The behaviour of dot with regard to newlines can  be  changed.  If  the
-       PCRE_DOTALL  option  is  set,  a dot matches any one character, without
+       The  behaviour  of  dot  with regard to newlines can be changed. If the
+       PCRE_DOTALL option is set, a dot matches  any  one  character,  without
        exception. If the two-character sequence CRLF is present in the subject
        string, it takes two dots to match it.
 
-       The  handling of dot is entirely independent of the handling of circum-
-       flex and dollar, the only relationship being  that  they  both  involve
+       The handling of dot is entirely independent of the handling of  circum-
+       flex  and  dollar,  the  only relationship being that they both involve
        newlines. Dot has no special meaning in a character class.
 
-       The  escape  sequence  \N  behaves  like  a  dot, except that it is not
-       affected by the PCRE_DOTALL option. In  other  words,  it  matches  any
-       character  except  one that signifies the end of a line. Perl also uses
+       The escape sequence \N behaves like  a  dot,  except  that  it  is  not
+       affected  by  the  PCRE_DOTALL  option.  In other words, it matches any
+       character except one that signifies the end of a line. Perl  also  uses
        \N to match characters by name; PCRE does not support this.
 
 
 MATCHING A SINGLE DATA UNIT
 
-       Outside a character class, the escape sequence \C matches any one  data
-       unit,  whether or not a UTF mode is set. In the 8-bit library, one data
-       unit is one byte; in the 16-bit library it is a  16-bit  unit;  in  the
-       32-bit  library  it  is  a 32-bit unit. Unlike a dot, \C always matches
-       line-ending characters. The feature is provided in  Perl  in  order  to
+       Outside  a character class, the escape sequence \C matches any one data
+       unit, whether or not a UTF mode is set. In the 8-bit library, one  data
+       unit  is  one  byte;  in the 16-bit library it is a 16-bit unit; in the
+       32-bit library it is a 32-bit unit. Unlike a  dot,  \C  always  matches
+       line-ending  characters.  The  feature  is provided in Perl in order to
        match individual bytes in UTF-8 mode, but it is unclear how it can use-
-       fully be used. Because \C breaks up  characters  into  individual  data
-       units,  matching  one unit with \C in a UTF mode means that the rest of
+       fully  be  used.  Because  \C breaks up characters into individual data
+       units, matching one unit with \C in a UTF mode means that the  rest  of
        the string may start with a malformed UTF character. This has undefined
        results, because PCRE assumes that it is dealing with valid UTF strings
-       (and by default it checks this at the start of  processing  unless  the
-       PCRE_NO_UTF8_CHECK,  PCRE_NO_UTF16_CHECK  or PCRE_NO_UTF32_CHECK option
+       (and  by  default  it checks this at the start of processing unless the
+       PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK or  PCRE_NO_UTF32_CHECK  option
        is used).
 
-       PCRE does not allow \C to appear in  lookbehind  assertions  (described
-       below)  in  a UTF mode, because this would make it impossible to calcu-
+       PCRE  does  not  allow \C to appear in lookbehind assertions (described
+       below) in a UTF mode, because this would make it impossible  to  calcu-
        late the length of the lookbehind.
 
        In general, the \C escape sequence is best avoided. However, one way of
-       using  it that avoids the problem of malformed UTF characters is to use
-       a lookahead to check the length of the next character, as in this  pat-
-       tern,  which  could be used with a UTF-8 string (ignore white space and
+       using it that avoids the problem of malformed UTF characters is to  use
+       a  lookahead to check the length of the next character, as in this pat-
+       tern, which could be used with a UTF-8 string (ignore white  space  and
        line breaks):
 
          (?| (?=[\x00-\x7f])(\C) |
@@ -5737,11 +5737,11 @@ MATCHING A SINGLE DATA UNIT
              (?=[\x{800}-\x{ffff}])(\C)(\C)(\C) |
              (?=[\x{10000}-\x{1fffff}])(\C)(\C)(\C)(\C))
 
-       A group that starts with (?| resets the capturing  parentheses  numbers
-       in  each  alternative  (see  "Duplicate Subpattern Numbers" below). The
-       assertions at the start of each branch check the next  UTF-8  character
-       for  values  whose encoding uses 1, 2, 3, or 4 bytes, respectively. The
-       character's individual bytes are then captured by the appropriate  num-
+       A  group  that starts with (?| resets the capturing parentheses numbers
+       in each alternative (see "Duplicate  Subpattern  Numbers"  below).  The
+       assertions  at  the start of each branch check the next UTF-8 character
+       for values whose encoding uses 1, 2, 3, or 4 bytes,  respectively.  The
+       character's  individual bytes are then captured by the appropriate num-
        ber of groups.
 
 
@@ -5751,109 +5751,109 @@ SQUARE BRACKETS AND CHARACTER CLASSES
        closing square bracket. A closing square bracket on its own is not spe-
        cial by default.  However, if the PCRE_JAVASCRIPT_COMPAT option is set,
        a lone closing square bracket causes a compile-time error. If a closing
-       square  bracket  is required as a member of the class, it should be the
-       first data character in the class  (after  an  initial  circumflex,  if
+       square bracket is required as a member of the class, it should  be  the
+       first  data  character  in  the  class (after an initial circumflex, if
        present) or escaped with a backslash.
 
-       A  character  class matches a single character in the subject. In a UTF
-       mode, the character may be more than one  data  unit  long.  A  matched
+       A character class matches a single character in the subject. In  a  UTF
+       mode,  the  character  may  be  more than one data unit long. A matched
        character must be in the set of characters defined by the class, unless
-       the first character in the class definition is a circumflex,  in  which
+       the  first  character in the class definition is a circumflex, in which
        case the subject character must not be in the set defined by the class.
-       If a circumflex is actually required as a member of the  class,  ensure
+       If  a  circumflex is actually required as a member of the class, ensure
        it is not the first character, or escape it with a backslash.
 
-       For  example, the character class [aeiou] matches any lower case vowel,
-       while [^aeiou] matches any character that is not a  lower  case  vowel.
+       For example, the character class [aeiou] matches any lower case  vowel,
+       while  [^aeiou]  matches  any character that is not a lower case vowel.
        Note that a circumflex is just a convenient notation for specifying the
-       characters that are in the class by enumerating those that are  not.  A
-       class  that starts with a circumflex is not an assertion; it still con-
-       sumes a character from the subject string, and therefore  it  fails  if
+       characters  that  are in the class by enumerating those that are not. A
+       class that starts with a circumflex is not an assertion; it still  con-
+       sumes  a  character  from the subject string, and therefore it fails if
        the current pointer is at the end of the string.
 
        In UTF-8 (UTF-16, UTF-32) mode, characters with values greater than 255
-       (0xffff) can be included in a class as a literal string of data  units,
+       (0xffff)  can be included in a class as a literal string of data units,
        or by using the \x{ escaping mechanism.
 
-       When  caseless  matching  is set, any letters in a class represent both
-       their upper case and lower case versions, so for  example,  a  caseless
-       [aeiou]  matches  "A"  as well as "a", and a caseless [^aeiou] does not
-       match "A", whereas a caseful version would. In a UTF mode, PCRE  always
-       understands  the  concept  of case for characters whose values are less
-       than 128, so caseless matching is always possible. For characters  with
-       higher  values,  the  concept  of case is supported if PCRE is compiled
-       with Unicode property support, but not otherwise.  If you want  to  use
-       caseless  matching in a UTF mode for characters 128 and above, you must
-       ensure that PCRE is compiled with Unicode property support as  well  as
+       When caseless matching is set, any letters in a  class  represent  both
+       their  upper  case  and lower case versions, so for example, a caseless
+       [aeiou] matches "A" as well as "a", and a caseless  [^aeiou]  does  not
+       match  "A", whereas a caseful version would. In a UTF mode, PCRE always
+       understands the concept of case for characters whose  values  are  less
+       than  128, so caseless matching is always possible. For characters with
+       higher values, the concept of case is supported  if  PCRE  is  compiled
+       with  Unicode  property support, but not otherwise.  If you want to use
+       caseless matching in a UTF mode for characters 128 and above, you  must
+       ensure  that  PCRE is compiled with Unicode property support as well as
        with UTF support.
 
-       Characters  that  might  indicate  line breaks are never treated in any
-       special way  when  matching  character  classes,  whatever  line-ending
-       sequence  is  in  use,  and  whatever  setting  of  the PCRE_DOTALL and
+       Characters that might indicate line breaks are  never  treated  in  any
+       special  way  when  matching  character  classes,  whatever line-ending
+       sequence is in  use,  and  whatever  setting  of  the  PCRE_DOTALL  and
        PCRE_MULTILINE options is used. A class such as [^a] always matches one
        of these characters.
 
-       The  minus (hyphen) character can be used to specify a range of charac-
-       ters in a character  class.  For  example,  [d-m]  matches  any  letter
-       between  d  and  m,  inclusive.  If  a minus character is required in a
-       class, it must be escaped with a backslash  or  appear  in  a  position
-       where  it cannot be interpreted as indicating a range, typically as the
+       The minus (hyphen) character can be used to specify a range of  charac-
+       ters  in  a  character  class.  For  example,  [d-m] matches any letter
+       between d and m, inclusive. If a  minus  character  is  required  in  a
+       class,  it  must  be  escaped  with a backslash or appear in a position
+       where it cannot be interpreted as indicating a range, typically as  the
        first or last character in the class, or immediately after a range. For
-       example,  [b-d-z] matches letters in the range b to d, a hyphen charac-
+       example, [b-d-z] matches letters in the range b to d, a hyphen  charac-
        ter, or z.
 
        It is not possible to have the literal character "]" as the end charac-
-       ter  of a range. A pattern such as [W-]46] is interpreted as a class of
-       two characters ("W" and "-") followed by a literal string "46]", so  it
-       would  match  "W46]"  or  "-46]". However, if the "]" is escaped with a
-       backslash it is interpreted as the end of range, so [W-\]46] is  inter-
-       preted  as a class containing a range followed by two other characters.
-       The octal or hexadecimal representation of "]" can also be used to  end
+       ter of a range. A pattern such as [W-]46] is interpreted as a class  of
+       two  characters ("W" and "-") followed by a literal string "46]", so it
+       would match "W46]" or "-46]". However, if the "]"  is  escaped  with  a
+       backslash  it is interpreted as the end of range, so [W-\]46] is inter-
+       preted as a class containing a range followed by two other  characters.
+       The  octal or hexadecimal representation of "]" can also be used to end
        a range.
 
-       An  error  is  generated  if  a POSIX character class (see below) or an
-       escape sequence other than one that defines a single character  appears
-       at  a  point  where  a range ending character is expected. For example,
+       An error is generated if a POSIX character  class  (see  below)  or  an
+       escape  sequence other than one that defines a single character appears
+       at a point where a range ending character  is  expected.  For  example,
        [z-\xff] is valid, but [A-\d] and [A-[:digit:]] are not.
 
-       Ranges operate in the collating sequence of character values. They  can
-       also   be  used  for  characters  specified  numerically,  for  example
-       [\000-\037]. Ranges can include any characters that are valid  for  the
+       Ranges  operate in the collating sequence of character values. They can
+       also  be  used  for  characters  specified  numerically,  for   example
+       [\000-\037].  Ranges  can include any characters that are valid for the
        current mode.
 
        If a range that includes letters is used when caseless matching is set,
        it matches the letters in either case. For example, [W-c] is equivalent
-       to  [][\\^_`wxyzabc],  matched  caselessly,  and  in a non-UTF mode, if
-       character tables for a French locale are in  use,  [\xc8-\xcb]  matches
-       accented  E  characters  in both cases. In UTF modes, PCRE supports the
-       concept of case for characters with values greater than 128  only  when
+       to [][\\^_`wxyzabc], matched caselessly, and  in  a  non-UTF  mode,  if
+       character  tables  for  a French locale are in use, [\xc8-\xcb] matches
+       accented E characters in both cases. In UTF modes,  PCRE  supports  the
+       concept  of  case for characters with values greater than 128 only when
        it is compiled with Unicode property support.
 
-       The  character escape sequences \d, \D, \h, \H, \p, \P, \s, \S, \v, \V,
+       The character escape sequences \d, \D, \h, \H, \p, \P, \s, \S, \v,  \V,
        \w, and \W may appear in a character class, and add the characters that
-       they  match to the class. For example, [\dABCDEF] matches any hexadeci-
-       mal digit. In UTF modes, the PCRE_UCP option affects  the  meanings  of
-       \d,  \s,  \w  and  their upper case partners, just as it does when they
-       appear outside a character class, as described in the section  entitled
+       they match to the class. For example, [\dABCDEF] matches any  hexadeci-
+       mal  digit.  In  UTF modes, the PCRE_UCP option affects the meanings of
+       \d, \s, \w and their upper case partners, just as  it  does  when  they
+       appear  outside a character class, as described in the section entitled
        "Generic character types" above. The escape sequence \b has a different
-       meaning inside a character class; it matches the  backspace  character.
-       The  sequences  \B,  \N,  \R, and \X are not special inside a character
-       class. Like any other unrecognized escape sequences, they  are  treated
-       as  the literal characters "B", "N", "R", and "X" by default, but cause
+       meaning  inside  a character class; it matches the backspace character.
+       The sequences \B, \N, \R, and \X are not  special  inside  a  character
+       class.  Like  any other unrecognized escape sequences, they are treated
+       as the literal characters "B", "N", "R", and "X" by default, but  cause
        an error if the PCRE_EXTRA option is set.
 
-       A circumflex can conveniently be used with  the  upper  case  character
-       types  to specify a more restricted set of characters than the matching
-       lower case type.  For example, the class [^\W_] matches any  letter  or
+       A  circumflex  can  conveniently  be used with the upper case character
+       types to specify a more restricted set of characters than the  matching
+       lower  case  type.  For example, the class [^\W_] matches any letter or
        digit, but not underscore, whereas [\w] includes underscore. A positive
        character class should be read as "something OR something OR ..." and a
        negative class as "NOT something AND NOT something AND NOT ...".
 
-       The  only  metacharacters  that are recognized in character classes are
-       backslash, hyphen (only where it can be  interpreted  as  specifying  a
-       range),  circumflex  (only  at the start), opening square bracket (only
-       when it can be interpreted as introducing a POSIX class name, or for  a
-       special  compatibility  feature  -  see the next two sections), and the
+       The only metacharacters that are recognized in  character  classes  are
+       backslash,  hyphen  (only  where  it can be interpreted as specifying a
+       range), circumflex (only at the start), opening  square  bracket  (only
+       when  it can be interpreted as introducing a POSIX class name, or for a
+       special compatibility feature - see the next  two  sections),  and  the
        terminating  closing  square  bracket.  However,  escaping  other  non-
        alphanumeric characters does no harm.
 
@@ -5861,7 +5861,7 @@ SQUARE BRACKETS AND CHARACTER CLASSES
 POSIX CHARACTER CLASSES
 
        Perl supports the POSIX notation for character classes. This uses names
-       enclosed by [: and :] within the enclosing square brackets.  PCRE  also
+       enclosed  by  [: and :] within the enclosing square brackets. PCRE also
        supports this notation. For example,
 
          [01[:alpha:]%]
@@ -5884,28 +5884,28 @@ POSIX CHARACTER CLASSES
          word     "word" characters (same as \w)
          xdigit   hexadecimal digits
 
-       The default "space" characters are HT (9), LF (10), VT (11),  FF  (12),
-       CR  (13),  and space (32). If locale-specific matching is taking place,
-       the list of space characters may be different; there may  be  fewer  or
+       The  default  "space" characters are HT (9), LF (10), VT (11), FF (12),
+       CR (13), and space (32). If locale-specific matching is  taking  place,
+       the  list  of  space characters may be different; there may be fewer or
        more of them. "Space" used to be different to \s, which did not include
        VT, for Perl compatibility.  However, Perl changed at release 5.18, and
-       PCRE  followed  at release 8.34.  "Space" and \s now match the same set
+       PCRE followed at release 8.34.  "Space" and \s now match the  same  set
        of characters.
 
-       The name "word" is a Perl extension, and "blank"  is  a  GNU  extension
-       from  Perl  5.8. Another Perl extension is negation, which is indicated
+       The  name  "word"  is  a Perl extension, and "blank" is a GNU extension
+       from Perl 5.8. Another Perl extension is negation, which  is  indicated
        by a ^ character after the colon. For example,
 
          [12[:^digit:]]
 
-       matches "1", "2", or any non-digit. PCRE (and Perl) also recognize  the
+       matches  "1", "2", or any non-digit. PCRE (and Perl) also recognize the
        POSIX syntax [.ch.] and [=ch=] where "ch" is a "collating element", but
        these are not supported, and an error is given if they are encountered.
 
        By default, characters with values greater than 128 do not match any of
-       the  POSIX character classes. However, if the PCRE_UCP option is passed
-       to pcre_compile(), some of the classes  are  changed  so  that  Unicode
-       character  properties  are  used. This is achieved by replacing certain
+       the POSIX character classes. However, if the PCRE_UCP option is  passed
+       to  pcre_compile(),  some  of  the  classes are changed so that Unicode
+       character properties are used. This is achieved  by  replacing  certain
        POSIX classes by other sequences, as follows:
 
          [:alnum:]  becomes  \p{Xan}
@@ -5917,10 +5917,10 @@ POSIX CHARACTER CLASSES
          [:upper:]  becomes  \p{Lu}
          [:word:]   becomes  \p{Xwd}
 
-       Negated versions, such as [:^alpha:] use \P instead of \p. Three  other
+       Negated  versions, such as [:^alpha:] use \P instead of \p. Three other
        POSIX classes are handled specially in UCP mode:
 
-       [:graph:] This  matches  characters that have glyphs that mark the page
+       [:graph:] This matches characters that have glyphs that mark  the  page
                  when printed. In Unicode property terms, it matches all char-
                  acters with the L, M, N, P, S, or Cf properties, except for:
 
@@ -5929,58 +5929,58 @@ POSIX CHARACTER CLASSES
                    U+2066 - U+2069  Various "isolate"s
 
 
-       [:print:] This  matches  the  same  characters  as [:graph:] plus space
-                 characters that are not controls, that  is,  characters  with
+       [:print:] This matches the same  characters  as  [:graph:]  plus  space
+                 characters  that  are  not controls, that is, characters with
                  the Zs property.
 
        [:punct:] This matches all characters that have the Unicode P (punctua-
-                 tion) property, plus those characters whose code  points  are
+                 tion)  property,  plus those characters whose code points are
                  less than 128 that have the S (Symbol) property.
 
-       The  other  POSIX classes are unchanged, and match only characters with
+       The other POSIX classes are unchanged, and match only  characters  with
        code points less than 128.
 
 
 COMPATIBILITY FEATURE FOR WORD BOUNDARIES
 
-       In the POSIX.2 compliant library that was included in 4.4BSD Unix,  the
-       ugly  syntax  [[:<:]]  and [[:>:]] is used for matching "start of word"
+       In  the POSIX.2 compliant library that was included in 4.4BSD Unix, the
+       ugly syntax [[:<:]] and [[:>:]] is used for matching  "start  of  word"
        and "end of word". PCRE treats these items as follows:
 
          [[:<:]]  is converted to  \b(?=\w)
          [[:>:]]  is converted to  \b(?<=\w)
 
        Only these exact character sequences are recognized. A sequence such as
-       [a[:<:]b]  provokes  error  for  an unrecognized POSIX class name. This
-       support is not compatible with Perl. It is provided to help  migrations
+       [a[:<:]b] provokes error for an unrecognized  POSIX  class  name.  This
+       support  is not compatible with Perl. It is provided to help migrations
        from other environments, and is best not used in any new patterns. Note
-       that \b matches at the start and the end of a word (see "Simple  asser-
-       tions"  above),  and in a Perl-style pattern the preceding or following
-       character normally shows which is wanted,  without  the  need  for  the
-       assertions  that  are used above in order to give exactly the POSIX be-
+       that  \b matches at the start and the end of a word (see "Simple asser-
+       tions" above), and in a Perl-style pattern the preceding  or  following
+       character  normally  shows  which  is  wanted, without the need for the
+       assertions that are used above in order to give exactly the  POSIX  be-
        haviour.
 
 
 VERTICAL BAR
 
-       Vertical bar characters are used to separate alternative patterns.  For
+       Vertical  bar characters are used to separate alternative patterns. For
        example, the pattern
 
          gilbert|sullivan
 
-       matches  either "gilbert" or "sullivan". Any number of alternatives may
-       appear, and an empty  alternative  is  permitted  (matching  the  empty
+       matches either "gilbert" or "sullivan". Any number of alternatives  may
+       appear,  and  an  empty  alternative  is  permitted (matching the empty
        string). The matching process tries each alternative in turn, from left
-       to right, and the first one that succeeds is used. If the  alternatives
-       are  within a subpattern (defined below), "succeeds" means matching the
+       to  right, and the first one that succeeds is used. If the alternatives
+       are within a subpattern (defined below), "succeeds" means matching  the
        rest of the main pattern as well as the alternative in the subpattern.
 
 
 INTERNAL OPTION SETTING
 
-       The settings of the  PCRE_CASELESS,  PCRE_MULTILINE,  PCRE_DOTALL,  and
-       PCRE_EXTENDED  options  (which are Perl-compatible) can be changed from
-       within the pattern by  a  sequence  of  Perl  option  letters  enclosed
+       The  settings  of  the  PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, and
+       PCRE_EXTENDED options (which are Perl-compatible) can be  changed  from
+       within  the  pattern  by  a  sequence  of  Perl option letters enclosed
        between "(?" and ")".  The option letters are
 
          i  for PCRE_CASELESS
@@ -5990,51 +5990,47 @@ INTERNAL OPTION SETTING
 
        For example, (?im) sets caseless, multiline matching. It is also possi-
        ble to unset these options by preceding the letter with a hyphen, and a
-       combined  setting and unsetting such as (?im-sx), which sets PCRE_CASE-
-       LESS and PCRE_MULTILINE while unsetting PCRE_DOTALL and  PCRE_EXTENDED,
-       is  also  permitted.  If  a  letter  appears  both before and after the
+       combined setting and unsetting such as (?im-sx), which sets  PCRE_CASE-
+       LESS  and PCRE_MULTILINE while unsetting PCRE_DOTALL and PCRE_EXTENDED,
+       is also permitted. If a  letter  appears  both  before  and  after  the
        hyphen, the option is unset.
 
-       The PCRE-specific options PCRE_DUPNAMES, PCRE_UNGREEDY, and  PCRE_EXTRA
-       can  be changed in the same way as the Perl-compatible options by using
+       The  PCRE-specific options PCRE_DUPNAMES, PCRE_UNGREEDY, and PCRE_EXTRA
+       can be changed in the same way as the Perl-compatible options by  using
        the characters J, U and X respectively.
 
-       When one of these option changes occurs at  top  level  (that  is,  not
-       inside  subpattern parentheses), the change applies to the remainder of
-       the pattern that follows. If the change is placed right at the start of
-       a pattern, PCRE extracts it into the global options (and it will there-
-       fore show up in data extracted by the pcre_fullinfo() function).
-
-       An option change within a subpattern (see below for  a  description  of
-       subpatterns)  affects only that part of the subpattern that follows it,
-       so
+       When  one  of  these  option  changes occurs at top level (that is, not
+       inside subpattern parentheses), the change applies to the remainder  of
+       the  pattern  that  follows.  An option change within a subpattern (see
+       below for a description of subpatterns) affects only that part  of  the
+       subpattern that follows it, so
 
          (a(?i)b)c
 
        matches abc and aBc and no other strings (assuming PCRE_CASELESS is not
-       used).   By  this means, options can be made to have different settings
-       in different parts of the pattern. Any changes made in one  alternative
-       do  carry  on  into subsequent branches within the same subpattern. For
+       used).  By this means, options can be made to have  different  settings
+       in  different parts of the pattern. Any changes made in one alternative
+       do carry on into subsequent branches within the  same  subpattern.  For
        example,
 
          (a(?i)b|c)
 
-       matches "ab", "aB", "c", and "C", even though  when  matching  "C"  the
-       first  branch  is  abandoned before the option setting. This is because
-       the effects of option settings happen at compile time. There  would  be
+       matches  "ab",  "aB",  "c",  and "C", even though when matching "C" the
+       first branch is abandoned before the option setting.  This  is  because
+       the  effects  of option settings happen at compile time. There would be
        some very weird behaviour otherwise.
 
-       Note:  There  are  other  PCRE-specific  options that can be set by the
-       application when the compiling or matching  functions  are  called.  In
-       some  cases  the  pattern can contain special leading sequences such as
-       (*CRLF) to override what the application  has  set  or  what  has  been
-       defaulted.   Details   are  given  in  the  section  entitled  "Newline
-       sequences" above. There are also the  (*UTF8),  (*UTF16),(*UTF32),  and
-       (*UCP)  leading sequences that can be used to set UTF and Unicode prop-
-       erty modes; they are equivalent to setting the  PCRE_UTF8,  PCRE_UTF16,
-       PCRE_UTF32  and the PCRE_UCP options, respectively. The (*UTF) sequence
-       is a generic version that can be used with any of the  libraries.  How-
-       ever,  the  application  can set the PCRE_NEVER_UTF option, which locks
+       Note: There are other PCRE-specific options that  can  be  set  by  the
+       application  when  the  compiling  or matching functions are called. In
+       some cases the pattern can contain special leading  sequences  such  as
+       (*CRLF)  to  override  what  the  application  has set or what has been
+       defaulted.  Details  are  given  in  the  section   entitled   "Newline
+       sequences"  above.  There  are also the (*UTF8), (*UTF16),(*UTF32), and
+       (*UCP) leading sequences that can be used to set UTF and Unicode  prop-
+       erty  modes;  they are equivalent to setting the PCRE_UTF8, PCRE_UTF16,
+       PCRE_UTF32 and the PCRE_UCP options, respectively. The (*UTF)  sequence
+       is  a  generic version that can be used with any of the libraries. How-
+       ever, the application can set the PCRE_NEVER_UTF  option,  which  locks
        out the use of the (*UTF) sequences.
 
 
@@ -6047,18 +6043,18 @@ SUBPATTERNS
 
          cat(aract|erpillar|)
 
-       matches  "cataract",  "caterpillar", or "cat". Without the parentheses,
+       matches "cataract", "caterpillar", or "cat". Without  the  parentheses,
        it would match "cataract", "erpillar" or an empty string.
 
-       2. It sets up the subpattern as  a  capturing  subpattern.  This  means
-       that,  when  the  whole  pattern  matches,  that portion of the subject
+       2.  It  sets  up  the  subpattern as a capturing subpattern. This means
+       that, when the whole pattern  matches,  that  portion  of  the  subject
        string that matched the subpattern is passed back to the caller via the
-       ovector  argument  of  the matching function. (This applies only to the
-       traditional matching functions; the DFA matching functions do not  sup-
+       ovector argument of the matching function. (This applies  only  to  the
+       traditional  matching functions; the DFA matching functions do not sup-
        port capturing.)
 
        Opening parentheses are counted from left to right (starting from 1) to
-       obtain numbers for the  capturing  subpatterns.  For  example,  if  the
+       obtain  numbers  for  the  capturing  subpatterns.  For example, if the
        string "the red king" is matched against the pattern
 
          the ((red|white) (king|queen))
@@ -6066,12 +6062,12 @@ SUBPATTERNS
        the captured substrings are "red king", "red", and "king", and are num-
        bered 1, 2, and 3, respectively.
 
-       The fact that plain parentheses fulfil  two  functions  is  not  always
-       helpful.   There are often times when a grouping subpattern is required
-       without a capturing requirement. If an opening parenthesis is  followed
-       by  a question mark and a colon, the subpattern does not do any captur-
-       ing, and is not counted when computing the  number  of  any  subsequent
-       capturing  subpatterns. For example, if the string "the white queen" is
+       The  fact  that  plain  parentheses  fulfil two functions is not always
+       helpful.  There are often times when a grouping subpattern is  required
+       without  a capturing requirement. If an opening parenthesis is followed
+       by a question mark and a colon, the subpattern does not do any  captur-
+       ing,  and  is  not  counted when computing the number of any subsequent
+       capturing subpatterns. For example, if the string "the white queen"  is
        matched against the pattern
 
          the ((?:red|white) (king|queen))
@@ -6079,37 +6075,37 @@ SUBPATTERNS
        the captured substrings are "white queen" and "queen", and are numbered
        1 and 2. The maximum number of capturing subpatterns is 65535.
 
-       As  a  convenient shorthand, if any option settings are required at the
-       start of a non-capturing subpattern,  the  option  letters  may  appear
+       As a convenient shorthand, if any option settings are required  at  the
+       start  of  a  non-capturing  subpattern,  the option letters may appear
        between the "?" and the ":". Thus the two patterns
 
          (?i:saturday|sunday)
          (?:(?i)saturday|sunday)
 
        match exactly the same set of strings. Because alternative branches are
-       tried from left to right, and options are not reset until  the  end  of
-       the  subpattern is reached, an option setting in one branch does affect
-       subsequent branches, so the above patterns match "SUNDAY"  as  well  as
+       tried  from  left  to right, and options are not reset until the end of
+       the subpattern is reached, an option setting in one branch does  affect
+       subsequent  branches,  so  the above patterns match "SUNDAY" as well as
        "Saturday".
 
 
 DUPLICATE SUBPATTERN NUMBERS
 
        Perl 5.10 introduced a feature whereby each alternative in a subpattern
-       uses the same numbers for its capturing parentheses. Such a  subpattern
-       starts  with (?| and is itself a non-capturing subpattern. For example,
+       uses  the same numbers for its capturing parentheses. Such a subpattern
+       starts with (?| and is itself a non-capturing subpattern. For  example,
        consider this pattern:
 
          (?|(Sat)ur|(Sun))day
 
-       Because the two alternatives are inside a (?| group, both sets of  cap-
-       turing  parentheses  are  numbered one. Thus, when the pattern matches,
-       you can look at captured substring number  one,  whichever  alternative
-       matched.  This  construct  is useful when you want to capture part, but
+       Because  the two alternatives are inside a (?| group, both sets of cap-
+       turing parentheses are numbered one. Thus, when  the  pattern  matches,
+       you  can  look  at captured substring number one, whichever alternative
+       matched. This construct is useful when you want to  capture  part,  but
        not all, of one of a number of alternatives. Inside a (?| group, paren-
-       theses  are  numbered as usual, but the number is reset at the start of
-       each branch. The numbers of any capturing parentheses that  follow  the
-       subpattern  start after the highest number used in any branch. The fol-
+       theses are numbered as usual, but the number is reset at the  start  of
+       each  branch.  The numbers of any capturing parentheses that follow the
+       subpattern start after the highest number used in any branch. The  fol-
        lowing example is taken from the Perl documentation. The numbers under-
        neath show in which buffer the captured content will be stored.
 
@@ -6117,58 +6113,58 @@ DUPLICATE SUBPATTERN NUMBERS
          / ( a )  (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
          # 1            2         2  3        2     3     4
 
-       A  back  reference  to a numbered subpattern uses the most recent value
-       that is set for that number by any subpattern.  The  following  pattern
+       A back reference to a numbered subpattern uses the  most  recent  value
+       that  is  set  for that number by any subpattern. The following pattern
        matches "abcabc" or "defdef":
 
          /(?|(abc)|(def))\1/
 
-       In  contrast,  a subroutine call to a numbered subpattern always refers
-       to the first one in the pattern with the given  number.  The  following
+       In contrast, a subroutine call to a numbered subpattern  always  refers
+       to  the  first  one in the pattern with the given number. The following
        pattern matches "abcabc" or "defabc":
 
          /(?|(abc)|(def))(?1)/
 
-       If  a condition test for a subpattern's having matched refers to a non-
-       unique number, the test is true if any of the subpatterns of that  num-
+       If a condition test for a subpattern's having matched refers to a  non-
+       unique  number, the test is true if any of the subpatterns of that num-
        ber have matched.
 
-       An  alternative approach to using this "branch reset" feature is to use
+       An alternative approach to using this "branch reset" feature is to  use
        duplicate named subpatterns, as described in the next section.
 
 
 NAMED SUBPATTERNS
 
-       Identifying capturing parentheses by number is simple, but  it  can  be
-       very  hard  to keep track of the numbers in complicated regular expres-
-       sions. Furthermore, if an  expression  is  modified,  the  numbers  may
-       change.  To help with this difficulty, PCRE supports the naming of sub-
+       Identifying  capturing  parentheses  by number is simple, but it can be
+       very hard to keep track of the numbers in complicated  regular  expres-
+       sions.  Furthermore,  if  an  expression  is  modified, the numbers may
+       change. To help with this difficulty, PCRE supports the naming of  sub-
        patterns. This feature was not added to Perl until release 5.10. Python
-       had  the  feature earlier, and PCRE introduced it at release 4.0, using
-       the Python syntax. PCRE now supports both the Perl and the Python  syn-
-       tax.  Perl  allows  identically  numbered subpatterns to have different
+       had the feature earlier, and PCRE introduced it at release  4.0,  using
+       the  Python syntax. PCRE now supports both the Perl and the Python syn-
+       tax. Perl allows identically numbered  subpatterns  to  have  different
        names, but PCRE does not.
 
-       In PCRE, a subpattern can be named in one of three  ways:  (?<name>...)
-       or  (?'name'...)  as in Perl, or (?P<name>...) as in Python. References
-       to capturing parentheses from other parts of the pattern, such as  back
-       references,  recursion,  and conditions, can be made by name as well as
+       In  PCRE,  a subpattern can be named in one of three ways: (?<name>...)
+       or (?'name'...) as in Perl, or (?P<name>...) as in  Python.  References
+       to  capturing parentheses from other parts of the pattern, such as back
+       references, recursion, and conditions, can be made by name as  well  as
        by number.
 
-       Names consist of up to 32 alphanumeric characters and underscores,  but
-       must  start  with  a  non-digit.  Named capturing parentheses are still
-       allocated numbers as well as names, exactly as if the  names  were  not
-       present.  The PCRE API provides function calls for extracting the name-
-       to-number translation table from a compiled pattern. There  is  also  a
+       Names  consist of up to 32 alphanumeric characters and underscores, but
+       must start with a non-digit.  Named  capturing  parentheses  are  still
+       allocated  numbers  as  well as names, exactly as if the names were not
+       present. The PCRE API provides function calls for extracting the  name-
+       to-number  translation  table  from a compiled pattern. There is also a
        convenience function for extracting a captured substring by name.
 
-       By  default, a name must be unique within a pattern, but it is possible
+       By default, a name must be unique within a pattern, but it is  possible
        to relax this constraint by setting the PCRE_DUPNAMES option at compile
-       time.  (Duplicate  names are also always permitted for subpatterns with
-       the same number, set up as described in the previous  section.)  Dupli-
-       cate  names  can  be useful for patterns where only one instance of the
-       named parentheses can match. Suppose you want to match the  name  of  a
-       weekday,  either as a 3-letter abbreviation or as the full name, and in
+       time. (Duplicate names are also always permitted for  subpatterns  with
+       the  same  number, set up as described in the previous section.) Dupli-
+       cate names can be useful for patterns where only one  instance  of  the
+       named  parentheses  can  match. Suppose you want to match the name of a
+       weekday, either as a 3-letter abbreviation or as the full name, and  in
        both cases you want to extract the abbreviation. This pattern (ignoring
        the line breaks) does the job:
 
@@ -6178,18 +6174,18 @@ NAMED SUBPATTERNS
          (?<DN>Thu)(?:rsday)?|
          (?<DN>Sat)(?:urday)?
 
-       There  are  five capturing substrings, but only one is ever set after a
+       There are five capturing substrings, but only one is ever set  after  a
        match.  (An alternative way of solving this problem is to use a "branch
        reset" subpattern, as described in the previous section.)
 
-       The  convenience  function  for extracting the data by name returns the
-       substring for the first (and in this example, the only)  subpattern  of
-       that  name  that  matched.  This saves searching to find which numbered
+       The convenience function for extracting the data by  name  returns  the
+       substring  for  the first (and in this example, the only) subpattern of
+       that name that matched. This saves searching  to  find  which  numbered
        subpattern it was.
 
-       If you make a back reference to  a  non-unique  named  subpattern  from
-       elsewhere  in the pattern, the subpatterns to which the name refers are
-       checked in the order in which they appear in the overall  pattern.  The
+       If  you  make  a  back  reference to a non-unique named subpattern from
+       elsewhere in the pattern, the subpatterns to which the name refers  are
+       checked  in  the order in which they appear in the overall pattern. The
        first one that is set is used for the reference. For example, this pat-
        tern matches both "foofoo" and "barbar" but not "foobar" or "barfoo":
 
@@ -6197,29 +6193,29 @@ NAMED SUBPATTERNS
 
 
        If you make a subroutine call to a non-unique named subpattern, the one
-       that  corresponds  to  the first occurrence of the name is used. In the
+       that corresponds to the first occurrence of the name is  used.  In  the
        absence of duplicate numbers (see the previous section) this is the one
        with the lowest number.
 
        If you use a named reference in a condition test (see the section about
        conditions below), either to check whether a subpattern has matched, or
-       to  check for recursion, all subpatterns with the same name are tested.
-       If the condition is true for any one of them, the overall condition  is
-       true.  This  is  the  same  behaviour as testing by number. For further
-       details of the interfaces  for  handling  named  subpatterns,  see  the
+       to check for recursion, all subpatterns with the same name are  tested.
+       If  the condition is true for any one of them, the overall condition is
+       true. This is the same behaviour as  testing  by  number.  For  further
+       details  of  the  interfaces  for  handling  named subpatterns, see the
        pcreapi documentation.
 
        Warning: You cannot use different names to distinguish between two sub-
-       patterns with the same number because PCRE uses only the  numbers  when
+       patterns  with  the same number because PCRE uses only the numbers when
        matching. For this reason, an error is given at compile time if differ-
-       ent names are given to subpatterns with the same number.  However,  you
+       ent  names  are given to subpatterns with the same number. However, you
        can always give the same name to subpatterns with the same number, even
        when PCRE_DUPNAMES is not set.
 
 
 REPETITION
 
-       Repetition is specified by quantifiers, which can  follow  any  of  the
+       Repetition  is  specified  by  quantifiers, which can follow any of the
        following items:
 
          a literal data character
@@ -6233,17 +6229,17 @@ REPETITION
          a parenthesized subpattern (including assertions)
          a subroutine call to a subpattern (recursive or otherwise)
 
-       The  general repetition quantifier specifies a minimum and maximum num-
-       ber of permitted matches, by giving the two numbers in  curly  brackets
-       (braces),  separated  by  a comma. The numbers must be less than 65536,
+       The general repetition quantifier specifies a minimum and maximum  num-
+       ber  of  permitted matches, by giving the two numbers in curly brackets
+       (braces), separated by a comma. The numbers must be  less  than  65536,
        and the first must be less than or equal to the second. For example:
 
          z{2,4}
 
-       matches "zz", "zzz", or "zzzz". A closing brace on its  own  is  not  a
-       special  character.  If  the second number is omitted, but the comma is
-       present, there is no upper limit; if the second number  and  the  comma
-       are  both omitted, the quantifier specifies an exact number of required
+       matches  "zz",  "zzz",  or  "zzzz". A closing brace on its own is not a
+       special character. If the second number is omitted, but  the  comma  is
+       present,  there  is  no upper limit; if the second number and the comma
+       are both omitted, the quantifier specifies an exact number of  required
        matches. Thus
 
          [aeiou]{3,}
@@ -6252,50 +6248,50 @@ REPETITION
 
          \d{8}
 
-       matches exactly 8 digits. An opening curly bracket that  appears  in  a
-       position  where a quantifier is not allowed, or one that does not match
-       the syntax of a quantifier, is taken as a literal character. For  exam-
+       matches  exactly  8  digits. An opening curly bracket that appears in a
+       position where a quantifier is not allowed, or one that does not  match
+       the  syntax of a quantifier, is taken as a literal character. For exam-
        ple, {,6} is not a quantifier, but a literal string of four characters.
 
        In UTF modes, quantifiers apply to characters rather than to individual
-       data units. Thus, for example, \x{100}{2} matches two characters,  each
+       data  units. Thus, for example, \x{100}{2} matches two characters, each
        of which is represented by a two-byte sequence in a UTF-8 string. Simi-
-       larly, \X{3} matches three Unicode extended grapheme clusters, each  of
-       which  may  be  several  data  units long (and they may be of different
+       larly,  \X{3} matches three Unicode extended grapheme clusters, each of
+       which may be several data units long (and  they  may  be  of  different
        lengths).
 
        The quantifier {0} is permitted, causing the expression to behave as if
        the previous item and the quantifier were not present. This may be use-
-       ful for subpatterns that are referenced as subroutines  from  elsewhere
+       ful  for  subpatterns that are referenced as subroutines from elsewhere
        in the pattern (but see also the section entitled "Defining subpatterns
-       for use by reference only" below). Items other  than  subpatterns  that
+       for  use  by  reference only" below). Items other than subpatterns that
        have a {0} quantifier are omitted from the compiled pattern.
 
-       For  convenience, the three most common quantifiers have single-charac-
+       For convenience, the three most common quantifiers have  single-charac-
        ter abbreviations:
 
          *    is equivalent to {0,}
          +    is equivalent to {1,}
          ?    is equivalent to {0,1}
 
-       It is possible to construct infinite loops by  following  a  subpattern
+       It  is  possible  to construct infinite loops by following a subpattern
        that can match no characters with a quantifier that has no upper limit,
        for example:
 
          (a?)*
 
        Earlier versions of Perl and PCRE used to give an error at compile time
-       for  such  patterns. However, because there are cases where this can be
-       useful, such patterns are now accepted, but if any  repetition  of  the
-       subpattern  does in fact match no characters, the loop is forcibly bro-
+       for such patterns. However, because there are cases where this  can  be
+       useful,  such  patterns  are now accepted, but if any repetition of the
+       subpattern does in fact match no characters, the loop is forcibly  bro-
        ken.
 
-       By default, the quantifiers are "greedy", that is, they match  as  much
-       as  possible  (up  to  the  maximum number of permitted times), without
-       causing the rest of the pattern to fail. The classic example  of  where
+       By  default,  the quantifiers are "greedy", that is, they match as much
+       as possible (up to the maximum  number  of  permitted  times),  without
+       causing  the  rest of the pattern to fail. The classic example of where
        this gives problems is in trying to match comments in C programs. These
-       appear between /* and */ and within the comment,  individual  *  and  /
-       characters  may  appear. An attempt to match C comments by applying the
+       appear  between  /*  and  */ and within the comment, individual * and /
+       characters may appear. An attempt to match C comments by  applying  the
        pattern
 
          /\*.*\*/
@@ -6304,19 +6300,19 @@ REPETITION
 
          /* first comment */  not comment  /* second comment */
 
-       fails, because it matches the entire string owing to the greediness  of
+       fails,  because it matches the entire string owing to the greediness of
        the .*  item.
 
-       However,  if  a quantifier is followed by a question mark, it ceases to
+       However, if a quantifier is followed by a question mark, it  ceases  to
        be greedy, and instead matches the minimum number of times possible, so
        the pattern
 
          /\*.*?\*/
 
-       does  the  right  thing with the C comments. The meaning of the various
-       quantifiers is not otherwise changed,  just  the  preferred  number  of
-       matches.   Do  not  confuse this use of question mark with its use as a
-       quantifier in its own right. Because it has two uses, it can  sometimes
+       does the right thing with the C comments. The meaning  of  the  various
+       quantifiers  is  not  otherwise  changed,  just the preferred number of
+       matches.  Do not confuse this use of question mark with its  use  as  a
+       quantifier  in its own right. Because it has two uses, it can sometimes
        appear doubled, as in
 
          \d??\d
@@ -6324,45 +6320,45 @@ REPETITION
        which matches one digit by preference, but can match two if that is the
        only way the rest of the pattern matches.
 
-       If the PCRE_UNGREEDY option is set (an option that is not available  in
-       Perl),  the  quantifiers are not greedy by default, but individual ones
-       can be made greedy by following them with a  question  mark.  In  other
+       If  the PCRE_UNGREEDY option is set (an option that is not available in
+       Perl), the quantifiers are not greedy by default, but  individual  ones
+       can  be  made  greedy  by following them with a question mark. In other
        words, it inverts the default behaviour.
 
-       When  a  parenthesized  subpattern  is quantified with a minimum repeat
-       count that is greater than 1 or with a limited maximum, more memory  is
-       required  for  the  compiled  pattern, in proportion to the size of the
+       When a parenthesized subpattern is quantified  with  a  minimum  repeat
+       count  that is greater than 1 or with a limited maximum, more memory is
+       required for the compiled pattern, in proportion to  the  size  of  the
        minimum or maximum.
 
        If a pattern starts with .* or .{0,} and the PCRE_DOTALL option (equiv-
-       alent  to  Perl's  /s) is set, thus allowing the dot to match newlines,
-       the pattern is implicitly anchored, because whatever  follows  will  be
-       tried  against every character position in the subject string, so there
-       is no point in retrying the overall match at  any  position  after  the
-       first.  PCRE  normally treats such a pattern as though it were preceded
+       alent to Perl's /s) is set, thus allowing the dot  to  match  newlines,
+       the  pattern  is  implicitly anchored, because whatever follows will be
+       tried against every character position in the subject string, so  there
+       is  no  point  in  retrying the overall match at any position after the
+       first. PCRE normally treats such a pattern as though it  were  preceded
        by \A.
 
-       In cases where it is known that the subject  string  contains  no  new-
-       lines,  it  is  worth setting PCRE_DOTALL in order to obtain this opti-
+       In  cases  where  it  is known that the subject string contains no new-
+       lines, it is worth setting PCRE_DOTALL in order to  obtain  this  opti-
        mization, or alternatively using ^ to indicate anchoring explicitly.
 
-       However, there are some cases where the optimization  cannot  be  used.
+       However,  there  are  some cases where the optimization cannot be used.
        When .*  is inside capturing parentheses that are the subject of a back
        reference elsewhere in the pattern, a match at the start may fail where
        a later one succeeds. Consider, for example:
 
          (.*)abc\1
 
-       If  the subject is "xyz123abc123" the match point is the fourth charac-
+       If the subject is "xyz123abc123" the match point is the fourth  charac-
        ter. For this reason, such a pattern is not implicitly anchored.
 
-       Another case where implicit anchoring is not applied is when the  lead-
-       ing  .* is inside an atomic group. Once again, a match at the start may
+       Another  case where implicit anchoring is not applied is when the lead-
+       ing .* is inside an atomic group. Once again, a match at the start  may
        fail where a later one succeeds. Consider this pattern:
 
          (?>.*?a)b
 
-       It matches "ab" in the subject "aab". The use of the backtracking  con-
+       It  matches "ab" in the subject "aab". The use of the backtracking con-
        trol verbs (*PRUNE) and (*SKIP) also disable this optimization.
 
        When a capturing subpattern is repeated, the value captured is the sub-
@@ -6371,8 +6367,8 @@ REPETITION
          (tweedle[dume]{3}\s*)+
 
        has matched "tweedledum tweedledee" the value of the captured substring
-       is  "tweedledee".  However,  if there are nested capturing subpatterns,
-       the corresponding captured values may have been set in previous  itera-
+       is "tweedledee". However, if there are  nested  capturing  subpatterns,
+       the  corresponding captured values may have been set in previous itera-
        tions. For example, after
 
          /(a|(b))+/
@@ -6382,53 +6378,53 @@ REPETITION
 
 ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS
 
-       With  both  maximizing ("greedy") and minimizing ("ungreedy" or "lazy")
-       repetition, failure of what follows normally causes the  repeated  item
-       to  be  re-evaluated to see if a different number of repeats allows the
-       rest of the pattern to match. Sometimes it is useful to  prevent  this,
-       either  to  change the nature of the match, or to cause it fail earlier
-       than it otherwise might, when the author of the pattern knows there  is
+       With both maximizing ("greedy") and minimizing ("ungreedy"  or  "lazy")
+       repetition,  failure  of what follows normally causes the repeated item
+       to be re-evaluated to see if a different number of repeats  allows  the
+       rest  of  the pattern to match. Sometimes it is useful to prevent this,
+       either to change the nature of the match, or to cause it  fail  earlier
+       than  it otherwise might, when the author of the pattern knows there is
        no point in carrying on.
 
-       Consider,  for  example, the pattern \d+foo when applied to the subject
+       Consider, for example, the pattern \d+foo when applied to  the  subject
        line
 
          123456bar
 
        After matching all 6 digits and then failing to match "foo", the normal
-       action  of  the matcher is to try again with only 5 digits matching the
-       \d+ item, and then with  4,  and  so  on,  before  ultimately  failing.
-       "Atomic  grouping"  (a  term taken from Jeffrey Friedl's book) provides
-       the means for specifying that once a subpattern has matched, it is  not
+       action of the matcher is to try again with only 5 digits  matching  the
+       \d+  item,  and  then  with  4,  and  so on, before ultimately failing.
+       "Atomic grouping" (a term taken from Jeffrey  Friedl's  book)  provides
+       the  means for specifying that once a subpattern has matched, it is not
        to be re-evaluated in this way.
 
-       If  we  use atomic grouping for the previous example, the matcher gives
-       up immediately on failing to match "foo" the first time.  The  notation
+       If we use atomic grouping for the previous example, the  matcher  gives
+       up  immediately  on failing to match "foo" the first time. The notation
        is a kind of special parenthesis, starting with (?> as in this example:
 
          (?>\d+)foo
 
-       This  kind  of  parenthesis "locks up" the  part of the pattern it con-
-       tains once it has matched, and a failure further into  the  pattern  is
-       prevented  from  backtracking into it. Backtracking past it to previous
+       This kind of parenthesis "locks up" the  part of the  pattern  it  con-
+       tains  once  it  has matched, and a failure further into the pattern is
+       prevented from backtracking into it. Backtracking past it  to  previous
        items, however, works as normal.
 
-       An alternative description is that a subpattern of  this  type  matches
-       the  string  of  characters  that an identical standalone pattern would
+       An  alternative  description  is that a subpattern of this type matches
+       the string of characters that an  identical  standalone  pattern  would
        match, if anchored at the current point in the subject string.
 
        Atomic grouping subpatterns are not capturing subpatterns. Simple cases
        such as the above example can be thought of as a maximizing repeat that
-       must swallow everything it can. So, while both \d+ and  \d+?  are  pre-
-       pared  to  adjust  the number of digits they match in order to make the
+       must  swallow  everything  it can. So, while both \d+ and \d+? are pre-
+       pared to adjust the number of digits they match in order  to  make  the
        rest of the pattern match, (?>\d+) can only match an entire sequence of
        digits.
 
-       Atomic  groups in general can of course contain arbitrarily complicated
-       subpatterns, and can be nested. However, when  the  subpattern  for  an
+       Atomic groups in general can of course contain arbitrarily  complicated
+       subpatterns,  and  can  be  nested. However, when the subpattern for an
        atomic group is just a single repeated item, as in the example above, a
-       simpler notation, called a "possessive quantifier" can  be  used.  This
-       consists  of  an  additional  + character following a quantifier. Using
+       simpler  notation,  called  a "possessive quantifier" can be used. This
+       consists of an additional + character  following  a  quantifier.  Using
        this notation, the previous example can be rewritten as
 
          \d++foo
@@ -6438,45 +6434,45 @@ ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS
 
          (abc|xyz){2,3}+
 
-       Possessive   quantifiers   are   always  greedy;  the  setting  of  the
+       Possessive  quantifiers  are  always  greedy;  the   setting   of   the
        PCRE_UNGREEDY option is ignored. They are a convenient notation for the
-       simpler  forms  of atomic group. However, there is no difference in the
-       meaning of a possessive quantifier and  the  equivalent  atomic  group,
-       though  there  may  be a performance difference; possessive quantifiers
+       simpler forms of atomic group. However, there is no difference  in  the
+       meaning  of  a  possessive  quantifier and the equivalent atomic group,
+       though there may be a performance  difference;  possessive  quantifiers
        should be slightly faster.
 
-       The possessive quantifier syntax is an extension to the Perl  5.8  syn-
-       tax.   Jeffrey  Friedl  originated the idea (and the name) in the first
+       The  possessive  quantifier syntax is an extension to the Perl 5.8 syn-
+       tax.  Jeffrey Friedl originated the idea (and the name)  in  the  first
        edition of his book. Mike McCloskey liked it, so implemented it when he
-       built  Sun's Java package, and PCRE copied it from there. It ultimately
+       built Sun's Java package, and PCRE copied it from there. It  ultimately
        found its way into Perl at release 5.10.
 
        PCRE has an optimization that automatically "possessifies" certain sim-
-       ple  pattern  constructs.  For  example, the sequence A+B is treated as
-       A++B because there is no point in backtracking into a sequence  of  A's
+       ple pattern constructs. For example, the sequence  A+B  is  treated  as
+       A++B  because  there is no point in backtracking into a sequence of A's
        when B must follow.
 
-       When  a  pattern  contains an unlimited repeat inside a subpattern that
-       can itself be repeated an unlimited number of  times,  the  use  of  an
-       atomic  group  is  the  only way to avoid some failing matches taking a
+       When a pattern contains an unlimited repeat inside  a  subpattern  that
+       can  itself  be  repeated  an  unlimited number of times, the use of an
+       atomic group is the only way to avoid some  failing  matches  taking  a
        very long time indeed. The pattern
 
          (\D+|<\d+>)*[!?]
 
-       matches an unlimited number of substrings that either consist  of  non-
-       digits,  or  digits  enclosed in <>, followed by either ! or ?. When it
+       matches  an  unlimited number of substrings that either consist of non-
+       digits, or digits enclosed in <>, followed by either ! or  ?.  When  it
        matches, it runs quickly. However, if it is applied to
 
          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 
-       it takes a long time before reporting  failure.  This  is  because  the
-       string  can be divided between the internal \D+ repeat and the external
-       * repeat in a large number of ways, and all  have  to  be  tried.  (The
-       example  uses  [!?]  rather than a single character at the end, because
-       both PCRE and Perl have an optimization that allows  for  fast  failure
-       when  a single character is used. They remember the last single charac-
-       ter that is required for a match, and fail early if it is  not  present
-       in  the  string.)  If  the pattern is changed so that it uses an atomic
+       it  takes  a  long  time  before reporting failure. This is because the
+       string can be divided between the internal \D+ repeat and the  external
+       *  repeat  in  a  large  number of ways, and all have to be tried. (The
+       example uses [!?] rather than a single character at  the  end,  because
+       both  PCRE  and  Perl have an optimization that allows for fast failure
+       when a single character is used. They remember the last single  charac-
+       ter  that  is required for a match, and fail early if it is not present
+       in the string.) If the pattern is changed so that  it  uses  an  atomic
        group, like this:
 
          ((?>\D+)|<\d+>)*[!?]
@@ -6488,28 +6484,28 @@ BACK REFERENCES
 
        Outside a character class, a backslash followed by a digit greater than
        0 (and possibly further digits) is a back reference to a capturing sub-
-       pattern earlier (that is, to its left) in the pattern,  provided  there
+       pattern  earlier  (that is, to its left) in the pattern, provided there
        have been that many previous capturing left parentheses.
 
        However, if the decimal number following the backslash is less than 10,
-       it is always taken as a back reference, and causes  an  error  only  if
-       there  are  not that many capturing left parentheses in the entire pat-
-       tern. In other words, the parentheses that are referenced need  not  be
-       to  the left of the reference for numbers less than 10. A "forward back
-       reference" of this type can make sense when a  repetition  is  involved
-       and  the  subpattern to the right has participated in an earlier itera-
+       it  is  always  taken  as a back reference, and causes an error only if
+       there are not that many capturing left parentheses in the  entire  pat-
+       tern.  In  other words, the parentheses that are referenced need not be
+       to the left of the reference for numbers less than 10. A "forward  back
+       reference"  of  this  type can make sense when a repetition is involved
+       and the subpattern to the right has participated in an  earlier  itera-
        tion.
 
-       It is not possible to have a numerical "forward back  reference"  to  a
-       subpattern  whose  number  is  10  or  more using this syntax because a
-       sequence such as \50 is interpreted as a character  defined  in  octal.
+       It  is  not  possible to have a numerical "forward back reference" to a
+       subpattern whose number is 10 or  more  using  this  syntax  because  a
+       sequence  such  as  \50 is interpreted as a character defined in octal.
        See the subsection entitled "Non-printing characters" above for further
-       details of the handling of digits following a backslash.  There  is  no
-       such  problem  when named parentheses are used. A back reference to any
+       details  of  the  handling of digits following a backslash. There is no
+       such problem when named parentheses are used. A back reference  to  any
        subpattern is possible using named parentheses (see below).
 
-       Another way of avoiding the ambiguity inherent in  the  use  of  digits
-       following  a  backslash  is  to use the \g escape sequence. This escape
+       Another  way  of  avoiding  the ambiguity inherent in the use of digits
+       following a backslash is to use the \g  escape  sequence.  This  escape
        must be followed by an unsigned number or a negative number, optionally
        enclosed in braces. These examples are all identical:
 
@@ -6517,7 +6513,7 @@ BACK REFERENCES
          (ring), \g1
          (ring), \g{1}
 
-       An  unsigned number specifies an absolute reference without the ambigu-
+       An unsigned number specifies an absolute reference without the  ambigu-
        ity that is present in the older syntax. It is also useful when literal
        digits follow the reference. A negative number is a relative reference.
        Consider this example:
@@ -6526,33 +6522,33 @@ BACK REFERENCES
 
        The sequence \g{-1} is a reference to the most recently started captur-
        ing subpattern before \g, that is, is it equivalent to \2 in this exam-
-       ple.  Similarly, \g{-2} would be equivalent to \1. The use of  relative
-       references  can  be helpful in long patterns, and also in patterns that
-       are created by  joining  together  fragments  that  contain  references
+       ple.   Similarly, \g{-2} would be equivalent to \1. The use of relative
+       references can be helpful in long patterns, and also in  patterns  that
+       are  created  by  joining  together  fragments  that contain references
        within themselves.
 
-       A  back  reference matches whatever actually matched the capturing sub-
-       pattern in the current subject string, rather  than  anything  matching
+       A back reference matches whatever actually matched the  capturing  sub-
+       pattern  in  the  current subject string, rather than anything matching
        the subpattern itself (see "Subpatterns as subroutines" below for a way
        of doing that). So the pattern
 
          (sens|respons)e and \1ibility
 
-       matches "sense and sensibility" and "response and responsibility",  but
-       not  "sense and responsibility". If caseful matching is in force at the
-       time of the back reference, the case of letters is relevant. For  exam-
+       matches  "sense and sensibility" and "response and responsibility", but
+       not "sense and responsibility". If caseful matching is in force at  the
+       time  of the back reference, the case of letters is relevant. For exam-
        ple,
 
          ((?i)rah)\s+\1
 
-       matches  "rah  rah"  and  "RAH RAH", but not "RAH rah", even though the
+       matches "rah rah" and "RAH RAH", but not "RAH  rah",  even  though  the
        original capturing subpattern is matched caselessly.
 
-       There are several different ways of writing back  references  to  named
-       subpatterns.  The  .NET syntax \k{name} and the Perl syntax \k<name> or
-       \k'name' are supported, as is the Python syntax (?P=name). Perl  5.10's
+       There  are  several  different ways of writing back references to named
+       subpatterns. The .NET syntax \k{name} and the Perl syntax  \k<name>  or
+       \k'name'  are supported, as is the Python syntax (?P=name). Perl 5.10's
        unified back reference syntax, in which \g can be used for both numeric
-       and named references, is also supported. We  could  rewrite  the  above
+       and  named  references,  is  also supported. We could rewrite the above
        example in any of the following ways:
 
          (?<p1>(?i)rah)\s+\k<p1>
@@ -6560,84 +6556,92 @@ BACK REFERENCES
          (?P<p1>(?i)rah)\s+(?P=p1)
          (?<p1>(?i)rah)\s+\g{p1}
 
-       A  subpattern  that  is  referenced  by  name may appear in the pattern
+       A subpattern that is referenced by  name  may  appear  in  the  pattern
        before or after the reference.
 
-       There may be more than one back reference to the same subpattern. If  a
-       subpattern  has  not actually been used in a particular match, any back
+       There  may be more than one back reference to the same subpattern. If a
+       subpattern has not actually been used in a particular match,  any  back
        references to it always fail by default. For example, the pattern
 
          (a|(bc))\2
 
-       always fails if it starts to match "a" rather than  "bc".  However,  if
+       always  fails  if  it starts to match "a" rather than "bc". However, if
        the PCRE_JAVASCRIPT_COMPAT option is set at compile time, a back refer-
        ence to an unset value matches an empty string.
 
-       Because there may be many capturing parentheses in a pattern, all  dig-
-       its  following a backslash are taken as part of a potential back refer-
-       ence number.  If the pattern continues with  a  digit  character,  some
-       delimiter  must  be  used  to  terminate  the  back  reference.  If the
-       PCRE_EXTENDED option is set, this can be white  space.  Otherwise,  the
+       Because  there may be many capturing parentheses in a pattern, all dig-
+       its following a backslash are taken as part of a potential back  refer-
+       ence  number.   If  the  pattern continues with a digit character, some
+       delimiter must  be  used  to  terminate  the  back  reference.  If  the
+       PCRE_EXTENDED  option  is  set, this can be white space. Otherwise, the
        \g{ syntax or an empty comment (see "Comments" below) can be used.
 
    Recursive back references
 
-       A  back reference that occurs inside the parentheses to which it refers
-       fails when the subpattern is first used, so, for example,  (a\1)  never
-       matches.   However,  such references can be useful inside repeated sub-
+       A back reference that occurs inside the parentheses to which it  refers
+       fails  when  the subpattern is first used, so, for example, (a\1) never
+       matches.  However, such references can be useful inside  repeated  sub-
        patterns. For example, the pattern
 
          (a|b\1)+
 
        matches any number of "a"s and also "aba", "ababbaa" etc. At each iter-
-       ation  of  the  subpattern,  the  back  reference matches the character
-       string corresponding to the previous iteration. In order  for  this  to
-       work,  the  pattern must be such that the first iteration does not need
-       to match the back reference. This can be done using alternation, as  in
+       ation of the subpattern,  the  back  reference  matches  the  character
+       string  corresponding  to  the previous iteration. In order for this to
+       work, the pattern must be such that the first iteration does  not  need
+       to  match the back reference. This can be done using alternation, as in
        the example above, or by a quantifier with a minimum of zero.
 
-       Back  references of this type cause the group that they reference to be
-       treated as an atomic group.  Once the whole group has been  matched,  a
-       subsequent  matching  failure cannot cause backtracking into the middle
+       Back references of this type cause the group that they reference to  be
+       treated  as  an atomic group.  Once the whole group has been matched, a
+       subsequent matching failure cannot cause backtracking into  the  middle
        of the group.
 
 
 ASSERTIONS
 
-       An assertion is a test on the characters  following  or  preceding  the
-       current  matching  point that does not actually consume any characters.
-       The simple assertions coded as \b, \B, \A, \G, \Z,  \z,  ^  and  $  are
+       An  assertion  is  a  test on the characters following or preceding the
+       current matching point that does not actually consume  any  characters.
+       The  simple  assertions  coded  as  \b, \B, \A, \G, \Z, \z, ^ and $ are
        described above.
 
-       More  complicated  assertions  are  coded as subpatterns. There are two
-       kinds: those that look ahead of the current  position  in  the  subject
-       string,  and  those  that  look  behind  it. An assertion subpattern is
-       matched in the normal way, except that it does not  cause  the  current
+       More complicated assertions are coded as  subpatterns.  There  are  two
+       kinds:  those  that  look  ahead of the current position in the subject
+       string, and those that look  behind  it.  An  assertion  subpattern  is
+       matched  in  the  normal way, except that it does not cause the current
        matching position to be changed.
 
-       Assertion  subpatterns are not capturing subpatterns. If such an asser-
-       tion contains capturing subpatterns within it, these  are  counted  for
-       the  purposes  of numbering the capturing subpatterns in the whole pat-
-       tern. However, substring capturing is carried  out  only  for  positive
+       Assertion subpatterns are not capturing subpatterns. If such an  asser-
+       tion  contains  capturing  subpatterns within it, these are counted for
+       the purposes of numbering the capturing subpatterns in the  whole  pat-
+       tern.  However,  substring  capturing  is carried out only for positive
        assertions. (Perl sometimes, but not always, does do capturing in nega-
        tive assertions.)
 
-       For compatibility with Perl, assertion  subpatterns  may  be  repeated;
-       though  it  makes  no sense to assert the same thing several times, the
-       side effect of capturing parentheses may  occasionally  be  useful.  In
+       WARNING:  If a positive assertion containing one or more capturing sub-
+       patterns succeeds, but failure to match later  in  the  pattern  causes
+       backtracking over this assertion, the captures within the assertion are
+       reset only if no higher numbered captures are  already  set.  This  is,
+       unfortunately,  a fundamental limitation of the current implementation,
+       and as PCRE1 is now in maintenance-only status, it is unlikely ever  to
+       change.
+
+       For  compatibility  with  Perl,  assertion subpatterns may be repeated;
+       though it makes no sense to assert the same thing  several  times,  the
+       side  effect  of  capturing  parentheses may occasionally be useful. In
        practice, there only three cases:
 
-       (1)  If  the  quantifier  is  {0}, the assertion is never obeyed during
-       matching.  However, it may  contain  internal  capturing  parenthesized
+       (1) If the quantifier is {0}, the  assertion  is  never  obeyed  during
+       matching.   However,  it  may  contain internal capturing parenthesized
        groups that are called from elsewhere via the subroutine mechanism.
 
-       (2)  If quantifier is {0,n} where n is greater than zero, it is treated
-       as if it were {0,1}. At run time, the rest  of  the  pattern  match  is
+       (2) If quantifier is {0,n} where n is greater than zero, it is  treated
+       as  if  it  were  {0,1}.  At run time, the rest of the pattern match is
        tried with and without the assertion, the order depending on the greed-
        iness of the quantifier.
 
-       (3) If the minimum repetition is greater than zero, the  quantifier  is
-       ignored.   The  assertion  is  obeyed just once when encountered during
+       (3)  If  the minimum repetition is greater than zero, the quantifier is
+       ignored.  The assertion is obeyed just  once  when  encountered  during
        matching.
 
    Lookahead assertions
@@ -6647,38 +6651,38 @@ ASSERTIONS
 
          \w+(?=;)
 
-       matches  a word followed by a semicolon, but does not include the semi-
+       matches a word followed by a semicolon, but does not include the  semi-
        colon in the match, and
 
          foo(?!bar)
 
-       matches any occurrence of "foo" that is not  followed  by  "bar".  Note
+       matches  any  occurrence  of  "foo" that is not followed by "bar". Note
        that the apparently similar pattern
 
          (?!foo)bar
 
-       does  not  find  an  occurrence  of "bar" that is preceded by something
-       other than "foo"; it finds any occurrence of "bar" whatsoever,  because
+       does not find an occurrence of "bar"  that  is  preceded  by  something
+       other  than "foo"; it finds any occurrence of "bar" whatsoever, because
        the assertion (?!foo) is always true when the next three characters are
        "bar". A lookbehind assertion is needed to achieve the other effect.
 
        If you want to force a matching failure at some point in a pattern, the
-       most  convenient  way  to  do  it  is with (?!) because an empty string
-       always matches, so an assertion that requires there not to be an  empty
+       most convenient way to do it is  with  (?!)  because  an  empty  string
+       always  matches, so an assertion that requires there not to be an empty
        string must always fail.  The backtracking control verb (*FAIL) or (*F)
        is a synonym for (?!).
 
    Lookbehind assertions
 
-       Lookbehind assertions start with (?<= for positive assertions and  (?<!
+       Lookbehind  assertions start with (?<= for positive assertions and (?<!
        for negative assertions. For example,
 
          (?<!foo)bar
 
-       does  find  an  occurrence  of "bar" that is not preceded by "foo". The
-       contents of a lookbehind assertion are restricted  such  that  all  the
+       does find an occurrence of "bar" that is not  preceded  by  "foo".  The
+       contents  of  a  lookbehind  assertion are restricted such that all the
        strings it matches must have a fixed length. However, if there are sev-
-       eral top-level alternatives, they do not all  have  to  have  the  same
+       eral  top-level  alternatives,  they  do  not all have to have the same
        fixed length. Thus
 
          (?<=bullock|donkey)
@@ -6687,62 +6691,62 @@ ASSERTIONS
 
          (?<!dogs?|cats?)
 
-       causes  an  error at compile time. Branches that match different length
-       strings are permitted only at the top level of a lookbehind  assertion.
+       causes an error at compile time. Branches that match  different  length
+       strings  are permitted only at the top level of a lookbehind assertion.
        This is an extension compared with Perl, which requires all branches to
        match the same length of string. An assertion such as
 
          (?<=ab(c|de))
 
-       is not permitted, because its single top-level  branch  can  match  two
+       is  not  permitted,  because  its single top-level branch can match two
        different lengths, but it is acceptable to PCRE if rewritten to use two
        top-level branches:
 
          (?<=abc|abde)
 
-       In some cases, the escape sequence \K (see above) can be  used  instead
+       In  some  cases, the escape sequence \K (see above) can be used instead
        of a lookbehind assertion to get round the fixed-length restriction.
 
-       The  implementation  of lookbehind assertions is, for each alternative,
-       to temporarily move the current position back by the fixed  length  and
+       The implementation of lookbehind assertions is, for  each  alternative,
+       to  temporarily  move the current position back by the fixed length and
        then try to match. If there are insufficient characters before the cur-
        rent position, the assertion fails.
 
-       In a UTF mode, PCRE does not allow the \C escape (which matches a  sin-
-       gle  data  unit even in a UTF mode) to appear in lookbehind assertions,
-       because it makes it impossible to calculate the length of  the  lookbe-
-       hind.  The \X and \R escapes, which can match different numbers of data
+       In  a UTF mode, PCRE does not allow the \C escape (which matches a sin-
+       gle data unit even in a UTF mode) to appear in  lookbehind  assertions,
+       because  it  makes it impossible to calculate the length of the lookbe-
+       hind. The \X and \R escapes, which can match different numbers of  data
        units, are also not permitted.
 
-       "Subroutine" calls (see below) such as (?2) or (?&X) are  permitted  in
-       lookbehinds,  as  long as the subpattern matches a fixed-length string.
+       "Subroutine"  calls  (see below) such as (?2) or (?&X) are permitted in
+       lookbehinds, as long as the subpattern matches a  fixed-length  string.
        Recursion, however, is not supported.
 
-       Possessive quantifiers can  be  used  in  conjunction  with  lookbehind
+       Possessive  quantifiers  can  be  used  in  conjunction with lookbehind
        assertions to specify efficient matching of fixed-length strings at the
        end of subject strings. Consider a simple pattern such as
 
          abcd$
 
-       when applied to a long string that does  not  match.  Because  matching
+       when  applied  to  a  long string that does not match. Because matching
        proceeds from left to right, PCRE will look for each "a" in the subject
-       and then see if what follows matches the rest of the  pattern.  If  the
+       and  then  see  if what follows matches the rest of the pattern. If the
        pattern is specified as
 
          ^.*abcd$
 
-       the  initial .* matches the entire string at first, but when this fails
+       the initial .* matches the entire string at first, but when this  fails
        (because there is no following "a"), it backtracks to match all but the
-       last  character,  then all but the last two characters, and so on. Once
-       again the search for "a" covers the entire string, from right to  left,
+       last character, then all but the last two characters, and so  on.  Once
+       again  the search for "a" covers the entire string, from right to left,
        so we are no better off. However, if the pattern is written as
 
          ^.*+(?<=abcd)
 
-       there  can  be  no backtracking for the .*+ item; it can match only the
-       entire string. The subsequent lookbehind assertion does a  single  test
-       on  the last four characters. If it fails, the match fails immediately.
-       For long strings, this approach makes a significant difference  to  the
+       there can be no backtracking for the .*+ item; it can  match  only  the
+       entire  string.  The subsequent lookbehind assertion does a single test
+       on the last four characters. If it fails, the match fails  immediately.
+       For  long  strings, this approach makes a significant difference to the
        processing time.
 
    Using multiple assertions
@@ -6751,18 +6755,18 @@ ASSERTIONS
 
          (?<=\d{3})(?<!999)foo
 
-       matches  "foo" preceded by three digits that are not "999". Notice that
-       each of the assertions is applied independently at the  same  point  in
-       the  subject  string.  First  there  is a check that the previous three
-       characters are all digits, and then there is  a  check  that  the  same
+       matches "foo" preceded by three digits that are not "999". Notice  that
+       each  of  the  assertions is applied independently at the same point in
+       the subject string. First there is a  check  that  the  previous  three
+       characters  are  all  digits,  and  then there is a check that the same
        three characters are not "999".  This pattern does not match "foo" pre-
-       ceded by six characters, the first of which are  digits  and  the  last
-       three  of  which  are not "999". For example, it doesn't match "123abc-
+       ceded  by  six  characters,  the first of which are digits and the last
+       three of which are not "999". For example, it  doesn't  match  "123abc-
        foo". A pattern to do that is
 
          (?<=\d{3}...)(?<!999)foo
 
-       This time the first assertion looks at the  preceding  six  characters,
+       This  time  the  first assertion looks at the preceding six characters,
        checking that the first three are digits, and then the second assertion
        checks that the preceding three characters are not "999".
 
@@ -6770,29 +6774,29 @@ ASSERTIONS
 
          (?<=(?<!foo)bar)baz
 
-       matches an occurrence of "baz" that is preceded by "bar" which in  turn
+       matches  an occurrence of "baz" that is preceded by "bar" which in turn
        is not preceded by "foo", while
 
          (?<=\d{3}(?!999)...)foo
 
-       is  another pattern that matches "foo" preceded by three digits and any
+       is another pattern that matches "foo" preceded by three digits and  any
        three characters that are not "999".
 
 
 CONDITIONAL SUBPATTERNS
 
-       It is possible to cause the matching process to obey a subpattern  con-
-       ditionally  or to choose between two alternative subpatterns, depending
-       on the result of an assertion, or whether a specific capturing  subpat-
-       tern  has  already  been matched. The two possible forms of conditional
+       It  is possible to cause the matching process to obey a subpattern con-
+       ditionally or to choose between two alternative subpatterns,  depending
+       on  the result of an assertion, or whether a specific capturing subpat-
+       tern has already been matched. The two possible  forms  of  conditional
        subpattern are:
 
          (?(condition)yes-pattern)
          (?(condition)yes-pattern|no-pattern)
 
-       If the condition is satisfied, the yes-pattern is used;  otherwise  the
-       no-pattern  (if  present)  is used. If there are more than two alterna-
-       tives in the subpattern, a compile-time error occurs. Each of  the  two
+       If  the  condition is satisfied, the yes-pattern is used; otherwise the
+       no-pattern (if present) is used. If there are more  than  two  alterna-
+       tives  in  the subpattern, a compile-time error occurs. Each of the two
        alternatives may itself contain nested subpatterns of any form, includ-
        ing  conditional  subpatterns;  the  restriction  to  two  alternatives
        applies only at the level of the condition. This pattern fragment is an
@@ -6801,68 +6805,68 @@ CONDITIONAL SUBPATTERNS
          (?(1) (A|B|C) | (D | (?(2)E|F) | E) )
 
 
-       There are four kinds of condition: references  to  subpatterns,  refer-
+       There  are  four  kinds of condition: references to subpatterns, refer-
        ences to recursion, a pseudo-condition called DEFINE, and assertions.
 
    Checking for a used subpattern by number
 
-       If  the  text between the parentheses consists of a sequence of digits,
+       If the text between the parentheses consists of a sequence  of  digits,
        the condition is true if a capturing subpattern of that number has pre-
-       viously  matched.  If  there is more than one capturing subpattern with
-       the same number (see the earlier  section  about  duplicate  subpattern
-       numbers),  the condition is true if any of them have matched. An alter-
-       native notation is to precede the digits with a plus or minus sign.  In
-       this  case, the subpattern number is relative rather than absolute. The
-       most recently opened parentheses can be referenced by (?(-1), the  next
-       most  recent  by (?(-2), and so on. Inside loops it can also make sense
+       viously matched. If there is more than one  capturing  subpattern  with
+       the  same  number  (see  the earlier section about duplicate subpattern
+       numbers), the condition is true if any of them have matched. An  alter-
+       native  notation is to precede the digits with a plus or minus sign. In
+       this case, the subpattern number is relative rather than absolute.  The
+       most  recently opened parentheses can be referenced by (?(-1), the next
+       most recent by (?(-2), and so on. Inside loops it can also  make  sense
        to refer to subsequent groups. The next parentheses to be opened can be
-       referenced  as (?(+1), and so on. (The value zero in any of these forms
+       referenced as (?(+1), and so on. (The value zero in any of these  forms
        is not used; it provokes a compile-time error.)
 
-       Consider the following pattern, which  contains  non-significant  white
+       Consider  the  following  pattern, which contains non-significant white
        space to make it more readable (assume the PCRE_EXTENDED option) and to
        divide it into three parts for ease of discussion:
 
          ( \( )?    [^()]+    (?(1) \) )
 
-       The first part matches an optional opening  parenthesis,  and  if  that
+       The  first  part  matches  an optional opening parenthesis, and if that
        character is present, sets it as the first captured substring. The sec-
-       ond part matches one or more characters that are not  parentheses.  The
-       third  part  is  a conditional subpattern that tests whether or not the
-       first set of parentheses matched. If they  did,  that  is,  if  subject
-       started  with an opening parenthesis, the condition is true, and so the
-       yes-pattern is executed and a closing parenthesis is  required.  Other-
-       wise,  since no-pattern is not present, the subpattern matches nothing.
-       In other words, this pattern matches  a  sequence  of  non-parentheses,
+       ond  part  matches one or more characters that are not parentheses. The
+       third part is a conditional subpattern that tests whether  or  not  the
+       first  set  of  parentheses  matched.  If they did, that is, if subject
+       started with an opening parenthesis, the condition is true, and so  the
+       yes-pattern  is  executed and a closing parenthesis is required. Other-
+       wise, since no-pattern is not present, the subpattern matches  nothing.
+       In  other  words,  this  pattern matches a sequence of non-parentheses,
        optionally enclosed in parentheses.
 
-       If  you  were  embedding  this pattern in a larger one, you could use a
+       If you were embedding this pattern in a larger one,  you  could  use  a
        relative reference:
 
          ...other stuff... ( \( )?    [^()]+    (?(-1) \) ) ...
 
-       This makes the fragment independent of the parentheses  in  the  larger
+       This  makes  the  fragment independent of the parentheses in the larger
        pattern.
 
    Checking for a used subpattern by name
 
-       Perl  uses  the  syntax  (?(<name>)...) or (?('name')...) to test for a
-       used subpattern by name. For compatibility  with  earlier  versions  of
-       PCRE,  which  had this facility before Perl, the syntax (?(name)...) is
+       Perl uses the syntax (?(<name>)...) or (?('name')...)  to  test  for  a
+       used  subpattern  by  name.  For compatibility with earlier versions of
+       PCRE, which had this facility before Perl, the syntax  (?(name)...)  is
        also recognized.
 
        Rewriting the above example to use a named subpattern gives this:
 
          (?<OPEN> \( )?    [^()]+    (?(<OPEN>) \) )
 
-       If the name used in a condition of this kind is a duplicate,  the  test
-       is  applied to all subpatterns of the same name, and is true if any one
+       If  the  name used in a condition of this kind is a duplicate, the test
+       is applied to all subpatterns of the same name, and is true if any  one
        of them has matched.
 
    Checking for pattern recursion
 
        If the condition is the string (R), and there is no subpattern with the
-       name  R, the condition is true if a recursive call to the whole pattern
+       name R, the condition is true if a recursive call to the whole  pattern
        or any subpattern has been made. If digits or a name preceded by amper-
        sand follow the letter R, for example:
 
@@ -6870,51 +6874,51 @@ CONDITIONAL SUBPATTERNS
 
        the condition is true if the most recent recursion is into a subpattern
        whose number or name is given. This condition does not check the entire
-       recursion  stack.  If  the  name  used in a condition of this kind is a
+       recursion stack. If the name used in a condition  of  this  kind  is  a
        duplicate, the test is applied to all subpatterns of the same name, and
        is true if any one of them is the most recent recursion.
 
-       At  "top  level",  all  these recursion test conditions are false.  The
+       At "top level", all these recursion test  conditions  are  false.   The
        syntax for recursive patterns is described below.
 
    Defining subpatterns for use by reference only
 
-       If the condition is the string (DEFINE), and  there  is  no  subpattern
-       with  the  name  DEFINE,  the  condition is always false. In this case,
-       there may be only one alternative  in  the  subpattern.  It  is  always
-       skipped  if  control  reaches  this  point  in the pattern; the idea of
-       DEFINE is that it can be used to define subroutines that can be  refer-
-       enced  from elsewhere. (The use of subroutines is described below.) For
-       example, a pattern to match an IPv4 address  such  as  "192.168.23.245"
+       If  the  condition  is  the string (DEFINE), and there is no subpattern
+       with the name DEFINE, the condition is  always  false.  In  this  case,
+       there  may  be  only  one  alternative  in the subpattern. It is always
+       skipped if control reaches this point  in  the  pattern;  the  idea  of
+       DEFINE  is that it can be used to define subroutines that can be refer-
+       enced from elsewhere. (The use of subroutines is described below.)  For
+       example,  a  pattern  to match an IPv4 address such as "192.168.23.245"
        could be written like this (ignore white space and line breaks):
 
          (?(DEFINE) (?<byte> 2[0-4]\d | 25[0-5] | 1\d\d | [1-9]?\d) )
          \b (?&byte) (\.(?&byte)){3} \b
 
-       The  first part of the pattern is a DEFINE group inside which a another
-       group named "byte" is defined. This matches an individual component  of
-       an  IPv4  address  (a number less than 256). When matching takes place,
-       this part of the pattern is skipped because DEFINE acts  like  a  false
-       condition.  The  rest of the pattern uses references to the named group
-       to match the four dot-separated components of an IPv4 address,  insist-
+       The first part of the pattern is a DEFINE group inside which a  another
+       group  named "byte" is defined. This matches an individual component of
+       an IPv4 address (a number less than 256). When  matching  takes  place,
+       this  part  of  the pattern is skipped because DEFINE acts like a false
+       condition. The rest of the pattern uses references to the  named  group
+       to  match the four dot-separated components of an IPv4 address, insist-
        ing on a word boundary at each end.
 
    Assertion conditions
 
-       If  the  condition  is  not  in any of the above formats, it must be an
-       assertion.  This may be a positive or negative lookahead or  lookbehind
-       assertion.  Consider  this  pattern,  again  containing non-significant
+       If the condition is not in any of the above  formats,  it  must  be  an
+       assertion.   This may be a positive or negative lookahead or lookbehind
+       assertion. Consider  this  pattern,  again  containing  non-significant
        white space, and with the two alternatives on the second line:
 
          (?(?=[^a-z]*[a-z])
          \d{2}-[a-z]{3}-\d{2}  |  \d{2}-\d{2}-\d{2} )
 
-       The condition  is  a  positive  lookahead  assertion  that  matches  an
-       optional  sequence of non-letters followed by a letter. In other words,
-       it tests for the presence of at least one letter in the subject.  If  a
-       letter  is found, the subject is matched against the first alternative;
-       otherwise it is  matched  against  the  second.  This  pattern  matches
-       strings  in  one  of the two forms dd-aaa-dd or dd-dd-dd, where aaa are
+       The  condition  is  a  positive  lookahead  assertion  that  matches an
+       optional sequence of non-letters followed by a letter. In other  words,
+       it  tests  for the presence of at least one letter in the subject. If a
+       letter is found, the subject is matched against the first  alternative;
+       otherwise  it  is  matched  against  the  second.  This pattern matches
+       strings in one of the two forms dd-aaa-dd or dd-dd-dd,  where  aaa  are
        letters and dd are digits.
 
 
@@ -6923,41 +6927,41 @@ COMMENTS
        There are two ways of including comments in patterns that are processed
        by PCRE. In both cases, the start of the comment must not be in a char-
        acter class, nor in the middle of any other sequence of related charac-
-       ters  such  as  (?: or a subpattern name or number. The characters that
+       ters such as (?: or a subpattern name or number.  The  characters  that
        make up a comment play no part in the pattern matching.
 
-       The sequence (?# marks the start of a comment that continues up to  the
-       next  closing parenthesis. Nested parentheses are not permitted. If the
+       The  sequence (?# marks the start of a comment that continues up to the
+       next closing parenthesis. Nested parentheses are not permitted. If  the
        PCRE_EXTENDED option is set, an unescaped # character also introduces a
-       comment,  which  in  this  case continues to immediately after the next
-       newline character or character sequence in the pattern.  Which  charac-
+       comment, which in this case continues to  immediately  after  the  next
+       newline  character  or character sequence in the pattern. Which charac-
        ters are interpreted as newlines is controlled by the options passed to
-       a compiling function or by a special sequence at the start of the  pat-
+       a  compiling function or by a special sequence at the start of the pat-
        tern, as described in the section entitled "Newline conventions" above.
        Note that the end of this type of comment is a literal newline sequence
-       in  the pattern; escape sequences that happen to represent a newline do
-       not count. For example, consider this  pattern  when  PCRE_EXTENDED  is
+       in the pattern; escape sequences that happen to represent a newline  do
+       not  count.  For  example,  consider this pattern when PCRE_EXTENDED is
        set, and the default newline convention is in force:
 
          abc #comment \n still comment
 
-       On  encountering  the  # character, pcre_compile() skips along, looking
-       for a newline in the pattern. The sequence \n is still literal at  this
-       stage,  so  it does not terminate the comment. Only an actual character
+       On encountering the # character, pcre_compile()  skips  along,  looking
+       for  a newline in the pattern. The sequence \n is still literal at this
+       stage, so it does not terminate the comment. Only an  actual  character
        with the code value 0x0a (the default newline) does so.
 
 
 RECURSIVE PATTERNS
 
-       Consider the problem of matching a string in parentheses, allowing  for
-       unlimited  nested  parentheses.  Without the use of recursion, the best
-       that can be done is to use a pattern that  matches  up  to  some  fixed
-       depth  of  nesting.  It  is not possible to handle an arbitrary nesting
+       Consider  the problem of matching a string in parentheses, allowing for
+       unlimited nested parentheses. Without the use of  recursion,  the  best
+       that  can  be  done  is  to use a pattern that matches up to some fixed
+       depth of nesting. It is not possible to  handle  an  arbitrary  nesting
        depth.
 
        For some time, Perl has provided a facility that allows regular expres-
-       sions  to recurse (amongst other things). It does this by interpolating
-       Perl code in the expression at run time, and the code can refer to  the
+       sions to recurse (amongst other things). It does this by  interpolating
+       Perl  code in the expression at run time, and the code can refer to the
        expression itself. A Perl pattern using code interpolation to solve the
        parentheses problem can be created like this:
 
@@ -6967,201 +6971,201 @@ RECURSIVE PATTERNS
        refers recursively to the pattern in which it appears.
 
        Obviously, PCRE cannot support the interpolation of Perl code. Instead,
-       it supports special syntax for recursion of  the  entire  pattern,  and
-       also  for  individual  subpattern  recursion. After its introduction in
-       PCRE and Python, this kind of  recursion  was  subsequently  introduced
+       it  supports  special  syntax  for recursion of the entire pattern, and
+       also for individual subpattern recursion.  After  its  introduction  in
+       PCRE  and  Python,  this  kind of recursion was subsequently introduced
        into Perl at release 5.10.
 
-       A  special  item  that consists of (? followed by a number greater than
-       zero and a closing parenthesis is a recursive subroutine  call  of  the
-       subpattern  of  the  given  number, provided that it occurs inside that
-       subpattern. (If not, it is a non-recursive subroutine  call,  which  is
-       described  in  the  next  section.)  The special item (?R) or (?0) is a
+       A special item that consists of (? followed by a  number  greater  than
+       zero  and  a  closing parenthesis is a recursive subroutine call of the
+       subpattern of the given number, provided that  it  occurs  inside  that
+       subpattern.  (If  not,  it is a non-recursive subroutine call, which is
+       described in the next section.) The special item  (?R)  or  (?0)  is  a
        recursive call of the entire regular expression.
 
-       This PCRE pattern solves the nested  parentheses  problem  (assume  the
+       This  PCRE  pattern  solves  the nested parentheses problem (assume the
        PCRE_EXTENDED option is set so that white space is ignored):
 
          \( ( [^()]++ | (?R) )* \)
 
-       First  it matches an opening parenthesis. Then it matches any number of
-       substrings which can either be a  sequence  of  non-parentheses,  or  a
-       recursive  match  of the pattern itself (that is, a correctly parenthe-
+       First it matches an opening parenthesis. Then it matches any number  of
+       substrings  which  can  either  be  a sequence of non-parentheses, or a
+       recursive match of the pattern itself (that is, a  correctly  parenthe-
        sized substring).  Finally there is a closing parenthesis. Note the use
        of a possessive quantifier to avoid backtracking into sequences of non-
        parentheses.
 
-       If this were part of a larger pattern, you would not  want  to  recurse
+       If  this  were  part of a larger pattern, you would not want to recurse
        the entire pattern, so instead you could use this:
 
          ( \( ( [^()]++ | (?1) )* \) )
 
-       We  have  put the pattern into parentheses, and caused the recursion to
+       We have put the pattern into parentheses, and caused the  recursion  to
        refer to them instead of the whole pattern.
 
-       In a larger pattern,  keeping  track  of  parenthesis  numbers  can  be
-       tricky.  This is made easier by the use of relative references. Instead
+       In  a  larger  pattern,  keeping  track  of  parenthesis numbers can be
+       tricky. This is made easier by the use of relative references.  Instead
        of (?1) in the pattern above you can write (?-2) to refer to the second
-       most  recently  opened  parentheses  preceding  the recursion. In other
-       words, a negative number counts capturing  parentheses  leftwards  from
+       most recently opened parentheses  preceding  the  recursion.  In  other
+       words,  a  negative  number counts capturing parentheses leftwards from
        the point at which it is encountered.
 
-       It  is  also  possible  to refer to subsequently opened parentheses, by
-       writing references such as (?+2). However, these  cannot  be  recursive
-       because  the  reference  is  not inside the parentheses that are refer-
-       enced. They are always non-recursive subroutine calls, as described  in
+       It is also possible to refer to  subsequently  opened  parentheses,  by
+       writing  references  such  as (?+2). However, these cannot be recursive
+       because the reference is not inside the  parentheses  that  are  refer-
+       enced.  They are always non-recursive subroutine calls, as described in
        the next section.
 
-       An  alternative  approach is to use named parentheses instead. The Perl
-       syntax for this is (?&name); PCRE's earlier syntax  (?P>name)  is  also
+       An alternative approach is to use named parentheses instead.  The  Perl
+       syntax  for  this  is (?&name); PCRE's earlier syntax (?P>name) is also
        supported. We could rewrite the above example as follows:
 
          (?<pn> \( ( [^()]++ | (?&pn) )* \) )
 
-       If  there  is more than one subpattern with the same name, the earliest
+       If there is more than one subpattern with the same name,  the  earliest
        one is used.
 
-       This particular example pattern that we have been looking  at  contains
+       This  particular  example pattern that we have been looking at contains
        nested unlimited repeats, and so the use of a possessive quantifier for
        matching strings of non-parentheses is important when applying the pat-
-       tern  to  strings  that do not match. For example, when this pattern is
+       tern to strings that do not match. For example, when  this  pattern  is
        applied to
 
          (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
 
-       it yields "no match" quickly. However, if a  possessive  quantifier  is
-       not  used, the match runs for a very long time indeed because there are
-       so many different ways the + and * repeats can carve  up  the  subject,
+       it  yields  "no  match" quickly. However, if a possessive quantifier is
+       not used, the match runs for a very long time indeed because there  are
+       so  many  different  ways the + and * repeats can carve up the subject,
        and all have to be tested before failure can be reported.
 
-       At  the  end  of a match, the values of capturing parentheses are those
-       from the outermost level. If you want to obtain intermediate values,  a
-       callout  function can be used (see below and the pcrecallout documenta-
+       At the end of a match, the values of capturing  parentheses  are  those
+       from  the outermost level. If you want to obtain intermediate values, a
+       callout function can be used (see below and the pcrecallout  documenta-
        tion). If the pattern above is matched against
 
          (ab(cd)ef)
 
-       the value for the inner capturing parentheses  (numbered  2)  is  "ef",
-       which  is the last value taken on at the top level. If a capturing sub-
-       pattern is not matched at the top level, its final  captured  value  is
-       unset,  even  if  it was (temporarily) set at a deeper level during the
+       the  value  for  the  inner capturing parentheses (numbered 2) is "ef",
+       which is the last value taken on at the top level. If a capturing  sub-
+       pattern  is  not  matched at the top level, its final captured value is
+       unset, even if it was (temporarily) set at a deeper  level  during  the
        matching process.
 
-       If there are more than 15 capturing parentheses in a pattern, PCRE  has
-       to  obtain extra memory to store data during a recursion, which it does
+       If  there are more than 15 capturing parentheses in a pattern, PCRE has
+       to obtain extra memory to store data during a recursion, which it  does
        by using pcre_malloc, freeing it via pcre_free afterwards. If no memory
        can be obtained, the match fails with the PCRE_ERROR_NOMEMORY error.
 
-       Do  not  confuse  the (?R) item with the condition (R), which tests for
-       recursion.  Consider this pattern, which matches text in  angle  brack-
-       ets,  allowing for arbitrary nesting. Only digits are allowed in nested
-       brackets (that is, when recursing), whereas any characters are  permit-
+       Do not confuse the (?R) item with the condition (R),  which  tests  for
+       recursion.   Consider  this pattern, which matches text in angle brack-
+       ets, allowing for arbitrary nesting. Only digits are allowed in  nested
+       brackets  (that is, when recursing), whereas any characters are permit-
        ted at the outer level.
 
          < (?: (?(R) \d++  | [^<>]*+) | (?R)) * >
 
-       In  this  pattern, (?(R) is the start of a conditional subpattern, with
-       two different alternatives for the recursive and  non-recursive  cases.
+       In this pattern, (?(R) is the start of a conditional  subpattern,  with
+       two  different  alternatives for the recursive and non-recursive cases.
        The (?R) item is the actual recursive call.
 
    Differences in recursion processing between PCRE and Perl
 
-       Recursion  processing  in PCRE differs from Perl in two important ways.
-       In PCRE (like Python, but unlike Perl), a recursive subpattern call  is
+       Recursion processing in PCRE differs from Perl in two  important  ways.
+       In  PCRE (like Python, but unlike Perl), a recursive subpattern call is
        always treated as an atomic group. That is, once it has matched some of
        the subject string, it is never re-entered, even if it contains untried
-       alternatives  and  there  is a subsequent matching failure. This can be
-       illustrated by the following pattern, which purports to match a  palin-
-       dromic  string  that contains an odd number of characters (for example,
+       alternatives and there is a subsequent matching failure.  This  can  be
+       illustrated  by the following pattern, which purports to match a palin-
+       dromic string that contains an odd number of characters  (for  example,
        "a", "aba", "abcba", "abcdcba"):
 
          ^(.|(.)(?1)\2)$
 
        The idea is that it either matches a single character, or two identical
-       characters  surrounding  a sub-palindrome. In Perl, this pattern works;
-       in PCRE it does not if the pattern is  longer  than  three  characters.
+       characters surrounding a sub-palindrome. In Perl, this  pattern  works;
+       in  PCRE  it  does  not if the pattern is longer than three characters.
        Consider the subject string "abcba":
 
-       At  the  top level, the first character is matched, but as it is not at
+       At the top level, the first character is matched, but as it is  not  at
        the end of the string, the first alternative fails; the second alterna-
        tive is taken and the recursion kicks in. The recursive call to subpat-
-       tern 1 successfully matches the next character ("b").  (Note  that  the
+       tern  1  successfully  matches the next character ("b"). (Note that the
        beginning and end of line tests are not part of the recursion).
 
-       Back  at  the top level, the next character ("c") is compared with what
-       subpattern 2 matched, which was "a". This fails. Because the  recursion
-       is  treated  as  an atomic group, there are now no backtracking points,
-       and so the entire match fails. (Perl is able, at  this  point,  to  re-
-       enter  the  recursion  and try the second alternative.) However, if the
+       Back at the top level, the next character ("c") is compared  with  what
+       subpattern  2 matched, which was "a". This fails. Because the recursion
+       is treated as an atomic group, there are now  no  backtracking  points,
+       and  so  the  entire  match fails. (Perl is able, at this point, to re-
+       enter the recursion and try the second alternative.)  However,  if  the
        pattern is written with the alternatives in the other order, things are
        different:
 
          ^((.)(?1)\2|.)$
 
-       This  time,  the recursing alternative is tried first, and continues to
-       recurse until it runs out of characters, at which point  the  recursion
-       fails.  But  this  time  we  do  have another alternative to try at the
-       higher level. That is the big difference:  in  the  previous  case  the
+       This time, the recursing alternative is tried first, and  continues  to
+       recurse  until  it runs out of characters, at which point the recursion
+       fails. But this time we do have  another  alternative  to  try  at  the
+       higher  level.  That  is  the  big difference: in the previous case the
        remaining alternative is at a deeper recursion level, which PCRE cannot
        use.
 
-       To change the pattern so that it matches all palindromic  strings,  not
-       just  those  with an odd number of characters, it is tempting to change
+       To  change  the pattern so that it matches all palindromic strings, not
+       just those with an odd number of characters, it is tempting  to  change
        the pattern to this:
 
          ^((.)(?1)\2|.?)$
 
-       Again, this works in Perl, but not in PCRE, and for  the  same  reason.
-       When  a  deeper  recursion has matched a single character, it cannot be
-       entered again in order to match an empty string.  The  solution  is  to
-       separate  the two cases, and write out the odd and even cases as alter-
+       Again,  this  works  in Perl, but not in PCRE, and for the same reason.
+       When a deeper recursion has matched a single character,  it  cannot  be
+       entered  again  in  order  to match an empty string. The solution is to
+       separate the two cases, and write out the odd and even cases as  alter-
        natives at the higher level:
 
          ^(?:((.)(?1)\2|)|((.)(?3)\4|.))
 
-       If you want to match typical palindromic phrases, the  pattern  has  to
+       If  you  want  to match typical palindromic phrases, the pattern has to
        ignore all non-word characters, which can be done like this:
 
          ^\W*+(?:((.)\W*+(?1)\W*+\2|)|((.)\W*+(?3)\W*+\4|\W*+.\W*+))\W*+$
 
        If run with the PCRE_CASELESS option, this pattern matches phrases such
        as "A man, a plan, a canal: Panama!" and it works well in both PCRE and
-       Perl.  Note the use of the possessive quantifier *+ to avoid backtrack-
-       ing into sequences of non-word characters. Without this, PCRE  takes  a
-       great  deal  longer  (ten  times or more) to match typical phrases, and
+       Perl. Note the use of the possessive quantifier *+ to avoid  backtrack-
+       ing  into  sequences of non-word characters. Without this, PCRE takes a
+       great deal longer (ten times or more) to  match  typical  phrases,  and
        Perl takes so long that you think it has gone into a loop.
 
-       WARNING: The palindrome-matching patterns above work only if  the  sub-
-       ject  string  does not start with a palindrome that is shorter than the
-       entire string.  For example, although "abcba" is correctly matched,  if
-       the  subject  is "ababa", PCRE finds the palindrome "aba" at the start,
-       then fails at top level because the end of the string does not  follow.
-       Once  again, it cannot jump back into the recursion to try other alter-
+       WARNING:  The  palindrome-matching patterns above work only if the sub-
+       ject string does not start with a palindrome that is shorter  than  the
+       entire  string.  For example, although "abcba" is correctly matched, if
+       the subject is "ababa", PCRE finds the palindrome "aba" at  the  start,
+       then  fails at top level because the end of the string does not follow.
+       Once again, it cannot jump back into the recursion to try other  alter-
        natives, so the entire match fails.
 
-       The second way in which PCRE and Perl differ in  their  recursion  pro-
-       cessing  is in the handling of captured values. In Perl, when a subpat-
-       tern is called recursively or as a subpattern (see the  next  section),
-       it  has  no  access to any values that were captured outside the recur-
-       sion, whereas in PCRE these values can  be  referenced.  Consider  this
+       The  second  way  in which PCRE and Perl differ in their recursion pro-
+       cessing is in the handling of captured values. In Perl, when a  subpat-
+       tern  is  called recursively or as a subpattern (see the next section),
+       it has no access to any values that were captured  outside  the  recur-
+       sion,  whereas  in  PCRE  these values can be referenced. Consider this
        pattern:
 
          ^(.)(\1|a(?2))
 
-       In  PCRE,  this  pattern matches "bab". The first capturing parentheses
-       match "b", then in the second group, when the back reference  \1  fails
-       to  match "b", the second alternative matches "a" and then recurses. In
-       the recursion, \1 does now match "b" and so the whole  match  succeeds.
-       In  Perl,  the pattern fails to match because inside the recursive call
+       In PCRE, this pattern matches "bab". The  first  capturing  parentheses
+       match  "b",  then in the second group, when the back reference \1 fails
+       to match "b", the second alternative matches "a" and then recurses.  In
+       the  recursion,  \1 does now match "b" and so the whole match succeeds.
+       In Perl, the pattern fails to match because inside the  recursive  call
        \1 cannot access the externally set value.
 
 
 SUBPATTERNS AS SUBROUTINES
 
-       If the syntax for a recursive subpattern call (either by number  or  by
-       name)  is  used outside the parentheses to which it refers, it operates
-       like a subroutine in a programming language. The called subpattern  may
-       be  defined  before or after the reference. A numbered reference can be
+       If  the  syntax for a recursive subpattern call (either by number or by
+       name) is used outside the parentheses to which it refers,  it  operates
+       like  a subroutine in a programming language. The called subpattern may
+       be defined before or after the reference. A numbered reference  can  be
        absolute or relative, as in these examples:
 
          (...(absolute)...)...(?2)...
@@ -7172,79 +7176,79 @@ SUBPATTERNS AS SUBROUTINES
 
          (sens|respons)e and \1ibility
 
-       matches "sense and sensibility" and "response and responsibility",  but
+       matches  "sense and sensibility" and "response and responsibility", but
        not "sense and responsibility". If instead the pattern
 
          (sens|respons)e and (?1)ibility
 
-       is  used, it does match "sense and responsibility" as well as the other
-       two strings. Another example is  given  in  the  discussion  of  DEFINE
+       is used, it does match "sense and responsibility" as well as the  other
+       two  strings.  Another  example  is  given  in the discussion of DEFINE
        above.
 
-       All  subroutine  calls, whether recursive or not, are always treated as
-       atomic groups. That is, once a subroutine has matched some of the  sub-
+       All subroutine calls, whether recursive or not, are always  treated  as
+       atomic  groups. That is, once a subroutine has matched some of the sub-
        ject string, it is never re-entered, even if it contains untried alter-
-       natives and there is  a  subsequent  matching  failure.  Any  capturing
-       parentheses  that  are  set  during the subroutine call revert to their
+       natives  and  there  is  a  subsequent  matching failure. Any capturing
+       parentheses that are set during the subroutine  call  revert  to  their
        previous values afterwards.
 
-       Processing options such as case-independence are fixed when  a  subpat-
-       tern  is defined, so if it is used as a subroutine, such options cannot
+       Processing  options  such as case-independence are fixed when a subpat-
+       tern is defined, so if it is used as a subroutine, such options  cannot
        be changed for different calls. For example, consider this pattern:
 
          (abc)(?i:(?-1))
 
-       It matches "abcabc". It does not match "abcABC" because the  change  of
+       It  matches  "abcabc". It does not match "abcABC" because the change of
        processing option does not affect the called subpattern.
 
 
 ONIGURUMA SUBROUTINE SYNTAX
 
-       For  compatibility with Oniguruma, the non-Perl syntax \g followed by a
+       For compatibility with Oniguruma, the non-Perl syntax \g followed by  a
        name or a number enclosed either in angle brackets or single quotes, is
-       an  alternative  syntax  for  referencing a subpattern as a subroutine,
-       possibly recursively. Here are two of the examples used above,  rewrit-
+       an alternative syntax for referencing a  subpattern  as  a  subroutine,
+       possibly  recursively. Here are two of the examples used above, rewrit-
        ten using this syntax:
 
          (?<pn> \( ( (?>[^()]+) | \g<pn> )* \) )
          (sens|respons)e and \g'1'ibility
 
-       PCRE  supports  an extension to Oniguruma: if a number is preceded by a
+       PCRE supports an extension to Oniguruma: if a number is preceded  by  a
        plus or a minus sign it is taken as a relative reference. For example:
 
          (abc)(?i:\g<-1>)
 
-       Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are  not
-       synonymous.  The former is a back reference; the latter is a subroutine
+       Note  that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not
+       synonymous. The former is a back reference; the latter is a  subroutine
        call.
 
 
 CALLOUTS
 
        Perl has a feature whereby using the sequence (?{...}) causes arbitrary
-       Perl  code to be obeyed in the middle of matching a regular expression.
+       Perl code to be obeyed in the middle of matching a regular  expression.
        This makes it possible, amongst other things, to extract different sub-
        strings that match the same pair of parentheses when there is a repeti-
        tion.
 
        PCRE provides a similar feature, but of course it cannot obey arbitrary
        Perl code. The feature is called "callout". The caller of PCRE provides
-       an external function by putting its entry point in the global  variable
-       pcre_callout  (8-bit  library) or pcre[16|32]_callout (16-bit or 32-bit
-       library).  By default, this variable contains NULL, which disables  all
+       an  external function by putting its entry point in the global variable
+       pcre_callout (8-bit library) or pcre[16|32]_callout (16-bit  or  32-bit
+       library).   By default, this variable contains NULL, which disables all
        calling out.
 
-       Within  a  regular  expression,  (?C) indicates the points at which the
-       external function is to be called. If you want  to  identify  different
-       callout  points, you can put a number less than 256 after the letter C.
-       The default value is zero.  For example, this pattern has  two  callout
+       Within a regular expression, (?C) indicates the  points  at  which  the
+       external  function  is  to be called. If you want to identify different
+       callout points, you can put a number less than 256 after the letter  C.
+       The  default  value is zero.  For example, this pattern has two callout
        points:
 
          (?C1)abc(?C2)def
 
-       If  the PCRE_AUTO_CALLOUT flag is passed to a compiling function, call-
-       outs are automatically installed before each item in the pattern.  They
-       are  all  numbered  255. If there is a conditional group in the pattern
+       If the PCRE_AUTO_CALLOUT flag is passed to a compiling function,  call-
+       outs  are automatically installed before each item in the pattern. They
+       are all numbered 255. If there is a conditional group  in  the  pattern
        whose condition is an assertion, an additional callout is inserted just
        before the condition. An explicit callout may also be set at this posi-
        tion, as in this example:
@@ -7254,120 +7258,120 @@ CALLOUTS
        Note that this applies only to assertion conditions, not to other types
        of condition.
 
-       During  matching, when PCRE reaches a callout point, the external func-
-       tion is called. It is provided with the  number  of  the  callout,  the
-       position  in  the pattern, and, optionally, one item of data originally
-       supplied by the caller of the matching function. The  callout  function
+       During matching, when PCRE reaches a callout point, the external  func-
+       tion  is  called.  It  is  provided with the number of the callout, the
+       position in the pattern, and, optionally, one item of  data  originally
+       supplied  by  the caller of the matching function. The callout function
        may cause matching to proceed, to backtrack, or to fail altogether.
 
-       By  default,  PCRE implements a number of optimizations at compile time
-       and matching time, and one side-effect is that sometimes  callouts  are
-       skipped.  If  you need all possible callouts to happen, you need to set
-       options that disable the relevant optimizations. More  details,  and  a
-       complete  description  of  the  interface  to the callout function, are
+       By default, PCRE implements a number of optimizations at  compile  time
+       and  matching  time, and one side-effect is that sometimes callouts are
+       skipped. If you need all possible callouts to happen, you need  to  set
+       options  that  disable  the relevant optimizations. More details, and a
+       complete description of the interface  to  the  callout  function,  are
        given in the pcrecallout documentation.
 
 
 BACKTRACKING CONTROL
 
-       Perl 5.10 introduced a number of "Special Backtracking Control  Verbs",
-       which  are  still  described in the Perl documentation as "experimental
-       and subject to change or removal in a future version of Perl". It  goes
-       on  to  say:  "Their  usage in production code should be noted to avoid
-       problems during upgrades." The same remarks apply to the PCRE  features
+       Perl  5.10 introduced a number of "Special Backtracking Control Verbs",
+       which are still described in the Perl  documentation  as  "experimental
+       and  subject to change or removal in a future version of Perl". It goes
+       on to say: "Their usage in production code should  be  noted  to  avoid
+       problems  during upgrades." The same remarks apply to the PCRE features
        described in this section.
 
-       The  new verbs make use of what was previously invalid syntax: an open-
+       The new verbs make use of what was previously invalid syntax: an  open-
        ing parenthesis followed by an asterisk. They are generally of the form
-       (*VERB)  or  (*VERB:NAME). Some may take either form, possibly behaving
-       differently depending on whether or not a name is present.  A  name  is
+       (*VERB) or (*VERB:NAME). Some may take either form,  possibly  behaving
+       differently  depending  on  whether or not a name is present. A name is
        any sequence of characters that does not include a closing parenthesis.
        The maximum length of name is 255 in the 8-bit library and 65535 in the
-       16-bit  and  32-bit  libraries.  If  the name is empty, that is, if the
-       closing parenthesis immediately follows the colon, the effect is as  if
-       the  colon  were  not  there.  Any number of these verbs may occur in a
+       16-bit and 32-bit libraries. If the name is  empty,  that  is,  if  the
+       closing  parenthesis immediately follows the colon, the effect is as if
+       the colon were not there.  Any number of these verbs  may  occur  in  a
        pattern.
 
-       Since these verbs are specifically related  to  backtracking,  most  of
-       them  can  be  used only when the pattern is to be matched using one of
-       the traditional matching functions, because these  use  a  backtracking
-       algorithm.  With the exception of (*FAIL), which behaves like a failing
-       negative assertion, the backtracking control verbs cause  an  error  if
+       Since  these  verbs  are  specifically related to backtracking, most of
+       them can be used only when the pattern is to be matched  using  one  of
+       the  traditional  matching  functions, because these use a backtracking
+       algorithm. With the exception of (*FAIL), which behaves like a  failing
+       negative  assertion,  the  backtracking control verbs cause an error if
        encountered by a DFA matching function.
 
-       The  behaviour  of  these  verbs in repeated groups, assertions, and in
+       The behaviour of these verbs in repeated  groups,  assertions,  and  in
        subpatterns called as subroutines (whether or not recursively) is docu-
        mented below.
 
    Optimizations that affect backtracking verbs
 
-       PCRE  contains some optimizations that are used to speed up matching by
+       PCRE contains some optimizations that are used to speed up matching  by
        running some checks at the start of each match attempt. For example, it
-       may  know  the minimum length of matching subject, or that a particular
+       may know the minimum length of matching subject, or that  a  particular
        character must be present. When one of these optimizations bypasses the
-       running  of  a  match,  any  included  backtracking  verbs will not, of
+       running of a match,  any  included  backtracking  verbs  will  not,  of
        course, be processed. You can suppress the start-of-match optimizations
-       by  setting  the  PCRE_NO_START_OPTIMIZE  option when calling pcre_com-
+       by setting the PCRE_NO_START_OPTIMIZE  option  when  calling  pcre_com-
        pile() or pcre_exec(), or by starting the pattern with (*NO_START_OPT).
        There is more discussion of this option in the section entitled "Option
        bits for pcre_exec()" in the pcreapi documentation.
 
-       Experiments with Perl suggest that it too  has  similar  optimizations,
+       Experiments  with  Perl  suggest that it too has similar optimizations,
        sometimes leading to anomalous results.
 
    Verbs that act immediately
 
-       The  following  verbs act as soon as they are encountered. They may not
+       The following verbs act as soon as they are encountered. They  may  not
        be followed by a name.
 
           (*ACCEPT)
 
-       This verb causes the match to end successfully, skipping the  remainder
-       of  the pattern. However, when it is inside a subpattern that is called
-       as a subroutine, only that subpattern is ended  successfully.  Matching
+       This  verb causes the match to end successfully, skipping the remainder
+       of the pattern. However, when it is inside a subpattern that is  called
+       as  a  subroutine, only that subpattern is ended successfully. Matching
        then continues at the outer level. If (*ACCEPT) in triggered in a posi-
-       tive assertion, the assertion succeeds; in a  negative  assertion,  the
+       tive  assertion,  the  assertion succeeds; in a negative assertion, the
        assertion fails.
 
-       If  (*ACCEPT)  is inside capturing parentheses, the data so far is cap-
+       If (*ACCEPT) is inside capturing parentheses, the data so far  is  cap-
        tured. For example:
 
          A((?:A|B(*ACCEPT)|C)D)
 
-       This matches "AB", "AAD", or "ACD"; when it matches "AB", "B"  is  cap-
+       This  matches  "AB", "AAD", or "ACD"; when it matches "AB", "B" is cap-
        tured by the outer parentheses.
 
          (*FAIL) or (*F)
 
-       This  verb causes a matching failure, forcing backtracking to occur. It
-       is equivalent to (?!) but easier to read. The Perl documentation  notes
-       that  it  is  probably  useful only when combined with (?{}) or (??{}).
-       Those are, of course, Perl features that are not present in  PCRE.  The
-       nearest  equivalent is the callout feature, as for example in this pat-
+       This verb causes a matching failure, forcing backtracking to occur.  It
+       is  equivalent to (?!) but easier to read. The Perl documentation notes
+       that it is probably useful only when combined  with  (?{})  or  (??{}).
+       Those  are,  of course, Perl features that are not present in PCRE. The
+       nearest equivalent is the callout feature, as for example in this  pat-
        tern:
 
          a+(?C)(*FAIL)
 
-       A match with the string "aaaa" always fails, but the callout  is  taken
+       A  match  with the string "aaaa" always fails, but the callout is taken
        before each backtrack happens (in this example, 10 times).
 
    Recording which path was taken
 
-       There  is  one  verb  whose  main  purpose  is to track how a match was
-       arrived at, though it also has a  secondary  use  in  conjunction  with
+       There is one verb whose main purpose  is  to  track  how  a  match  was
+       arrived  at,  though  it  also  has a secondary use in conjunction with
        advancing the match starting point (see (*SKIP) below).
 
          (*MARK:NAME) or (*:NAME)
 
-       A  name  is  always  required  with  this  verb.  There  may be as many
-       instances of (*MARK) as you like in a pattern, and their names  do  not
+       A name is always  required  with  this  verb.  There  may  be  as  many
+       instances  of  (*MARK) as you like in a pattern, and their names do not
        have to be unique.
 
-       When  a  match succeeds, the name of the last-encountered (*MARK:NAME),
-       (*PRUNE:NAME), or (*THEN:NAME) on the matching path is passed  back  to
-       the  caller  as  described  in  the  section  entitled  "Extra data for
-       pcre_exec()" in the  pcreapi  documentation.  Here  is  an  example  of
-       pcretest  output, where the /K modifier requests the retrieval and out-
+       When a match succeeds, the name of the  last-encountered  (*MARK:NAME),
+       (*PRUNE:NAME),  or  (*THEN:NAME) on the matching path is passed back to
+       the caller as  described  in  the  section  entitled  "Extra  data  for
+       pcre_exec()"  in  the  pcreapi  documentation.  Here  is  an example of
+       pcretest output, where the /K modifier requests the retrieval and  out-
        putting of (*MARK) data:
 
            re> /X(*MARK:A)Y|X(*MARK:B)Z/K
@@ -7379,73 +7383,73 @@ BACKTRACKING CONTROL
          MK: B
 
        The (*MARK) name is tagged with "MK:" in this output, and in this exam-
-       ple  it indicates which of the two alternatives matched. This is a more
-       efficient way of obtaining this information than putting each  alterna-
+       ple it indicates which of the two alternatives matched. This is a  more
+       efficient  way of obtaining this information than putting each alterna-
        tive in its own capturing parentheses.
 
-       If  a  verb  with a name is encountered in a positive assertion that is
-       true, the name is recorded and passed back if it  is  the  last-encoun-
+       If a verb with a name is encountered in a positive  assertion  that  is
+       true,  the  name  is recorded and passed back if it is the last-encoun-
        tered. This does not happen for negative assertions or failing positive
        assertions.
 
-       After a partial match or a failed match, the last encountered  name  in
+       After  a  partial match or a failed match, the last encountered name in
        the entire match process is returned. For example:
 
            re> /X(*MARK:A)Y|X(*MARK:B)Z/K
          data> XP
          No match, mark = B
 
-       Note  that  in  this  unanchored  example the mark is retained from the
+       Note that in this unanchored example the  mark  is  retained  from  the
        match attempt that started at the letter "X" in the subject. Subsequent
        match attempts starting at "P" and then with an empty string do not get
        as far as the (*MARK) item, but nevertheless do not reset it.
 
-       If you are interested in  (*MARK)  values  after  failed  matches,  you
-       should  probably  set  the PCRE_NO_START_OPTIMIZE option (see above) to
+       If  you  are  interested  in  (*MARK)  values after failed matches, you
+       should probably set the PCRE_NO_START_OPTIMIZE option  (see  above)  to
        ensure that the match is always attempted.
 
    Verbs that act after backtracking
 
        The following verbs do nothing when they are encountered. Matching con-
-       tinues  with what follows, but if there is no subsequent match, causing
-       a backtrack to the verb, a failure is  forced.  That  is,  backtracking
-       cannot  pass  to the left of the verb. However, when one of these verbs
+       tinues with what follows, but if there is no subsequent match,  causing
+       a  backtrack  to  the  verb, a failure is forced. That is, backtracking
+       cannot pass to the left of the verb. However, when one of  these  verbs
        appears inside an atomic group or an assertion that is true, its effect
-       is  confined  to  that  group, because once the group has been matched,
-       there is never any backtracking into it. In this situation,  backtrack-
-       ing  can  "jump  back" to the left of the entire atomic group or asser-
-       tion. (Remember also, as stated  above,  that  this  localization  also
+       is confined to that group, because once the  group  has  been  matched,
+       there  is never any backtracking into it. In this situation, backtrack-
+       ing can "jump back" to the left of the entire atomic  group  or  asser-
+       tion.  (Remember  also,  as  stated  above, that this localization also
        applies in subroutine calls.)
 
-       These  verbs  differ  in exactly what kind of failure occurs when back-
-       tracking reaches them. The behaviour described below  is  what  happens
-       when  the  verb is not in a subroutine or an assertion. Subsequent sec-
+       These verbs differ in exactly what kind of failure  occurs  when  back-
+       tracking  reaches  them.  The behaviour described below is what happens
+       when the verb is not in a subroutine or an assertion.  Subsequent  sec-
        tions cover these special cases.
 
          (*COMMIT)
 
-       This verb, which may not be followed by a name, causes the whole  match
+       This  verb, which may not be followed by a name, causes the whole match
        to fail outright if there is a later matching failure that causes back-
-       tracking to reach it. Even if the pattern  is  unanchored,  no  further
+       tracking  to  reach  it.  Even if the pattern is unanchored, no further
        attempts to find a match by advancing the starting point take place. If
-       (*COMMIT) is the only backtracking verb that is  encountered,  once  it
+       (*COMMIT)  is  the  only backtracking verb that is encountered, once it
        has been passed pcre_exec() is committed to finding a match at the cur-
        rent starting point, or not at all. For example:
 
          a+(*COMMIT)b
 
-       This matches "xxaab" but not "aacaab". It can be thought of as  a  kind
+       This  matches  "xxaab" but not "aacaab". It can be thought of as a kind
        of dynamic anchor, or "I've started, so I must finish." The name of the
-       most recently passed (*MARK) in the path is passed back when  (*COMMIT)
+       most  recently passed (*MARK) in the path is passed back when (*COMMIT)
        forces a match failure.
 
-       If  there  is more than one backtracking verb in a pattern, a different
-       one that follows (*COMMIT) may be triggered first,  so  merely  passing
+       If there is more than one backtracking verb in a pattern,  a  different
+       one  that  follows  (*COMMIT) may be triggered first, so merely passing
        (*COMMIT) during a match does not always guarantee that a match must be
        at this starting point.
 
-       Note that (*COMMIT) at the start of a pattern is not  the  same  as  an
-       anchor,  unless  PCRE's start-of-match optimizations are turned off, as
+       Note  that  (*COMMIT)  at  the start of a pattern is not the same as an
+       anchor, unless PCRE's start-of-match optimizations are turned  off,  as
        shown in this output from pcretest:
 
            re> /(*COMMIT)abc/
@@ -7456,207 +7460,207 @@ BACKTRACKING CONTROL
 
        For this pattern, PCRE knows that any match must start with "a", so the
        optimization skips along the subject to "a" before applying the pattern
-       to the first set of data. The match attempt then succeeds. In the  sec-
-       ond  set of data, the escape sequence \Y is interpreted by the pcretest
-       program. It causes the PCRE_NO_START_OPTIMIZE option  to  be  set  when
+       to  the first set of data. The match attempt then succeeds. In the sec-
+       ond set of data, the escape sequence \Y is interpreted by the  pcretest
+       program.  It  causes  the  PCRE_NO_START_OPTIMIZE option to be set when
        pcre_exec() is called.  This disables the optimization that skips along
        to the first character. The pattern is now applied starting at "x", and
-       so  the  (*COMMIT)  causes  the  match to fail without trying any other
+       so the (*COMMIT) causes the match to  fail  without  trying  any  other
        starting points.
 
          (*PRUNE) or (*PRUNE:NAME)
 
-       This verb causes the match to fail at the current starting position  in
+       This  verb causes the match to fail at the current starting position in
        the subject if there is a later matching failure that causes backtrack-
-       ing to reach it. If the pattern is unanchored, the  normal  "bumpalong"
-       advance  to  the next starting character then happens. Backtracking can
-       occur as usual to the left of (*PRUNE), before it is reached,  or  when
-       matching  to  the  right  of  (*PRUNE), but if there is no match to the
-       right, backtracking cannot cross (*PRUNE). In simple cases, the use  of
-       (*PRUNE)  is just an alternative to an atomic group or possessive quan-
+       ing  to  reach it. If the pattern is unanchored, the normal "bumpalong"
+       advance to the next starting character then happens.  Backtracking  can
+       occur  as  usual to the left of (*PRUNE), before it is reached, or when
+       matching to the right of (*PRUNE), but if there  is  no  match  to  the
+       right,  backtracking cannot cross (*PRUNE). In simple cases, the use of
+       (*PRUNE) is just an alternative to an atomic group or possessive  quan-
        tifier, but there are some uses of (*PRUNE) that cannot be expressed in
-       any  other  way. In an anchored pattern (*PRUNE) has the same effect as
+       any other way. In an anchored pattern (*PRUNE) has the same  effect  as
        (*COMMIT).
 
        The   behaviour   of   (*PRUNE:NAME)   is   the   not   the   same   as
-       (*MARK:NAME)(*PRUNE).   It  is  like  (*MARK:NAME)  in that the name is
-       remembered for  passing  back  to  the  caller.  However,  (*SKIP:NAME)
+       (*MARK:NAME)(*PRUNE).  It is like (*MARK:NAME)  in  that  the  name  is
+       remembered  for  passing  back  to  the  caller.  However, (*SKIP:NAME)
        searches only for names set with (*MARK).
 
          (*SKIP)
 
-       This  verb, when given without a name, is like (*PRUNE), except that if
-       the pattern is unanchored, the "bumpalong" advance is not to  the  next
+       This verb, when given without a name, is like (*PRUNE), except that  if
+       the  pattern  is unanchored, the "bumpalong" advance is not to the next
        character, but to the position in the subject where (*SKIP) was encoun-
-       tered. (*SKIP) signifies that whatever text was matched leading  up  to
+       tered.  (*SKIP)  signifies that whatever text was matched leading up to
        it cannot be part of a successful match. Consider:
 
          a+(*SKIP)b
 
-       If  the  subject  is  "aaaac...",  after  the first match attempt fails
-       (starting at the first character in the  string),  the  starting  point
+       If the subject is "aaaac...",  after  the  first  match  attempt  fails
+       (starting  at  the  first  character in the string), the starting point
        skips on to start the next attempt at "c". Note that a possessive quan-
-       tifer does not have the same effect as this example; although it  would
-       suppress  backtracking  during  the  first  match  attempt,  the second
-       attempt would start at the second character instead of skipping  on  to
+       tifer  does not have the same effect as this example; although it would
+       suppress backtracking  during  the  first  match  attempt,  the  second
+       attempt  would  start at the second character instead of skipping on to
        "c".
 
          (*SKIP:NAME)
 
        When (*SKIP) has an associated name, its behaviour is modified. When it
        is triggered, the previous path through the pattern is searched for the
-       most  recent  (*MARK)  that  has  the  same  name. If one is found, the
+       most recent (*MARK) that has the  same  name.  If  one  is  found,  the
        "bumpalong" advance is to the subject position that corresponds to that
        (*MARK) instead of to where (*SKIP) was encountered. If no (*MARK) with
        a matching name is found, the (*SKIP) is ignored.
 
-       Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME).  It
+       Note  that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It
        ignores names that are set by (*PRUNE:NAME) or (*THEN:NAME).
 
          (*THEN) or (*THEN:NAME)
 
-       This  verb  causes  a skip to the next innermost alternative when back-
-       tracking reaches it. That  is,  it  cancels  any  further  backtracking
-       within  the  current  alternative.  Its name comes from the observation
+       This verb causes a skip to the next innermost  alternative  when  back-
+       tracking  reaches  it.  That  is,  it  cancels any further backtracking
+       within the current alternative. Its name  comes  from  the  observation
        that it can be used for a pattern-based if-then-else block:
 
          ( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ...
 
-       If the COND1 pattern matches, FOO is tried (and possibly further  items
-       after  the  end  of the group if FOO succeeds); on failure, the matcher
-       skips to the second alternative and tries COND2,  without  backtracking
-       into  COND1.  If that succeeds and BAR fails, COND3 is tried. If subse-
-       quently BAZ fails, there are no more alternatives, so there is a  back-
-       track  to  whatever  came  before  the  entire group. If (*THEN) is not
+       If  the COND1 pattern matches, FOO is tried (and possibly further items
+       after the end of the group if FOO succeeds); on  failure,  the  matcher
+       skips  to  the second alternative and tries COND2, without backtracking
+       into COND1. If that succeeds and BAR fails, COND3 is tried.  If  subse-
+       quently  BAZ fails, there are no more alternatives, so there is a back-
+       track to whatever came before the  entire  group.  If  (*THEN)  is  not
        inside an alternation, it acts like (*PRUNE).
 
-       The   behaviour   of   (*THEN:NAME)   is   the   not   the   same    as
-       (*MARK:NAME)(*THEN).   It  is  like  (*MARK:NAME)  in  that the name is
-       remembered for  passing  back  to  the  caller.  However,  (*SKIP:NAME)
+       The    behaviour   of   (*THEN:NAME)   is   the   not   the   same   as
+       (*MARK:NAME)(*THEN).  It is like  (*MARK:NAME)  in  that  the  name  is
+       remembered  for  passing  back  to  the  caller.  However, (*SKIP:NAME)
        searches only for names set with (*MARK).
 
-       A  subpattern that does not contain a | character is just a part of the
-       enclosing alternative; it is not a nested  alternation  with  only  one
-       alternative.  The effect of (*THEN) extends beyond such a subpattern to
-       the enclosing alternative. Consider this pattern, where A, B, etc.  are
-       complex  pattern fragments that do not contain any | characters at this
+       A subpattern that does not contain a | character is just a part of  the
+       enclosing  alternative;  it  is  not a nested alternation with only one
+       alternative. The effect of (*THEN) extends beyond such a subpattern  to
+       the  enclosing alternative. Consider this pattern, where A, B, etc. are
+       complex pattern fragments that do not contain any | characters at  this
        level:
 
          A (B(*THEN)C) | D
 
-       If A and B are matched, but there is a failure in C, matching does  not
+       If  A and B are matched, but there is a failure in C, matching does not
        backtrack into A; instead it moves to the next alternative, that is, D.
-       However, if the subpattern containing (*THEN) is given an  alternative,
+       However,  if the subpattern containing (*THEN) is given an alternative,
        it behaves differently:
 
          A (B(*THEN)C | (*FAIL)) | D
 
-       The  effect of (*THEN) is now confined to the inner subpattern. After a
+       The effect of (*THEN) is now confined to the inner subpattern. After  a
        failure in C, matching moves to (*FAIL), which causes the whole subpat-
-       tern  to  fail  because  there are no more alternatives to try. In this
+       tern to fail because there are no more alternatives  to  try.  In  this
        case, matching does now backtrack into A.
 
-       Note that a conditional subpattern is  not  considered  as  having  two
-       alternatives,  because  only  one  is  ever used. In other words, the |
+       Note  that  a  conditional  subpattern  is not considered as having two
+       alternatives, because only one is ever used.  In  other  words,  the  |
        character in a conditional subpattern has a different meaning. Ignoring
        white space, consider:
 
          ^.*? (?(?=a) a | b(*THEN)c )
 
-       If  the  subject  is  "ba", this pattern does not match. Because .*? is
-       ungreedy, it initially matches zero  characters.  The  condition  (?=a)
-       then  fails,  the  character  "b"  is  matched, but "c" is not. At this
-       point, matching does not backtrack to .*? as might perhaps be  expected
-       from  the  presence  of  the | character. The conditional subpattern is
+       If the subject is "ba", this pattern does not  match.  Because  .*?  is
+       ungreedy,  it  initially  matches  zero characters. The condition (?=a)
+       then fails, the character "b" is matched,  but  "c"  is  not.  At  this
+       point,  matching does not backtrack to .*? as might perhaps be expected
+       from the presence of the | character.  The  conditional  subpattern  is
        part of the single alternative that comprises the whole pattern, and so
-       the  match  fails.  (If  there was a backtrack into .*?, allowing it to
+       the match fails. (If there was a backtrack into  .*?,  allowing  it  to
        match "b", the match would succeed.)
 
-       The verbs just described provide four different "strengths" of  control
+       The  verbs just described provide four different "strengths" of control
        when subsequent matching fails. (*THEN) is the weakest, carrying on the
-       match at the next alternative. (*PRUNE) comes next, failing  the  match
-       at  the  current starting position, but allowing an advance to the next
-       character (for an unanchored pattern). (*SKIP) is similar, except  that
+       match  at  the next alternative. (*PRUNE) comes next, failing the match
+       at the current starting position, but allowing an advance to  the  next
+       character  (for an unanchored pattern). (*SKIP) is similar, except that
        the advance may be more than one character. (*COMMIT) is the strongest,
        causing the entire match to fail.
 
    More than one backtracking verb
 
-       If more than one backtracking verb is present in  a  pattern,  the  one
-       that  is  backtracked  onto first acts. For example, consider this pat-
+       If  more  than  one  backtracking verb is present in a pattern, the one
+       that is backtracked onto first acts. For example,  consider  this  pat-
        tern, where A, B, etc. are complex pattern fragments:
 
          (A(*COMMIT)B(*THEN)C|ABD)
 
-       If A matches but B fails, the backtrack to (*COMMIT) causes the  entire
+       If  A matches but B fails, the backtrack to (*COMMIT) causes the entire
        match to fail. However, if A and B match, but C fails, the backtrack to
-       (*THEN) causes the next alternative (ABD) to be tried.  This  behaviour
-       is  consistent,  but is not always the same as Perl's. It means that if
-       two or more backtracking verbs appear in succession, all the  the  last
+       (*THEN)  causes  the next alternative (ABD) to be tried. This behaviour
+       is consistent, but is not always the same as Perl's. It means  that  if
+       two  or  more backtracking verbs appear in succession, all the the last
        of them has no effect. Consider this example:
 
          ...(*COMMIT)(*PRUNE)...
 
        If there is a matching failure to the right, backtracking onto (*PRUNE)
-       causes it to be triggered, and its action is taken. There can never  be
+       causes  it to be triggered, and its action is taken. There can never be
        a backtrack onto (*COMMIT).
 
    Backtracking verbs in repeated groups
 
-       PCRE  differs  from  Perl  in  its  handling  of  backtracking verbs in
+       PCRE differs from  Perl  in  its  handling  of  backtracking  verbs  in
        repeated groups. For example, consider:
 
          /(a(*COMMIT)b)+ac/
 
-       If the subject is "abac", Perl matches,  but  PCRE  fails  because  the
+       If  the  subject  is  "abac",  Perl matches, but PCRE fails because the
        (*COMMIT) in the second repeat of the group acts.
 
    Backtracking verbs in assertions
 
-       (*FAIL)  in  an assertion has its normal effect: it forces an immediate
+       (*FAIL) in an assertion has its normal effect: it forces  an  immediate
        backtrack.
 
        (*ACCEPT) in a positive assertion causes the assertion to succeed with-
-       out  any  further processing. In a negative assertion, (*ACCEPT) causes
+       out any further processing. In a negative assertion,  (*ACCEPT)  causes
        the assertion to fail without any further processing.
 
-       The other backtracking verbs are not treated specially if  they  appear
-       in  a  positive  assertion.  In  particular,  (*THEN) skips to the next
-       alternative in the innermost enclosing  group  that  has  alternations,
+       The  other  backtracking verbs are not treated specially if they appear
+       in a positive assertion. In  particular,  (*THEN)  skips  to  the  next
+       alternative  in  the  innermost  enclosing group that has alternations,
        whether or not this is within the assertion.
 
-       Negative  assertions  are,  however, different, in order to ensure that
-       changing a positive assertion into a  negative  assertion  changes  its
+       Negative assertions are, however, different, in order  to  ensure  that
+       changing  a  positive  assertion  into a negative assertion changes its
        result. Backtracking into (*COMMIT), (*SKIP), or (*PRUNE) causes a neg-
        ative assertion to be true, without considering any further alternative
        branches in the assertion.  Backtracking into (*THEN) causes it to skip
-       to the next enclosing alternative within the assertion (the normal  be-
-       haviour),  but  if  the  assertion  does  not have such an alternative,
+       to  the next enclosing alternative within the assertion (the normal be-
+       haviour), but if the assertion  does  not  have  such  an  alternative,
        (*THEN) behaves like (*PRUNE).
 
    Backtracking verbs in subroutines
 
-       These behaviours occur whether or not the subpattern is  called  recur-
+       These  behaviours  occur whether or not the subpattern is called recur-
        sively.  Perl's treatment of subroutines is different in some cases.
 
-       (*FAIL)  in  a subpattern called as a subroutine has its normal effect:
+       (*FAIL) in a subpattern called as a subroutine has its  normal  effect:
        it forces an immediate backtrack.
 
-       (*ACCEPT) in a subpattern called as a subroutine causes the  subroutine
-       match  to succeed without any further processing. Matching then contin-
+       (*ACCEPT)  in a subpattern called as a subroutine causes the subroutine
+       match to succeed without any further processing. Matching then  contin-
        ues after the subroutine call.
 
        (*COMMIT), (*SKIP), and (*PRUNE) in a subpattern called as a subroutine
        cause the subroutine match to fail.
 
-       (*THEN)  skips to the next alternative in the innermost enclosing group
-       within the subpattern that has alternatives. If there is no such  group
+       (*THEN) skips to the next alternative in the innermost enclosing  group
+       within  the subpattern that has alternatives. If there is no such group
        within the subpattern, (*THEN) causes the subroutine match to fail.
 
 
 SEE ALSO
 
-       pcreapi(3),  pcrecallout(3),  pcrematching(3),  pcresyntax(3), pcre(3),
+       pcreapi(3), pcrecallout(3),  pcrematching(3),  pcresyntax(3),  pcre(3),
        pcre16(3), pcre32(3).
 
 
@@ -7669,8 +7673,8 @@ AUTHOR
 
 REVISION
 
-       Last updated: 14 June 2015
-       Copyright (c) 1997-2015 University of Cambridge.
+       Last updated: 23 October 2016
+       Copyright (c) 1997-2016 University of Cambridge.
 ------------------------------------------------------------------------------
 
 
@@ -8361,7 +8365,11 @@ AVAILABILITY OF JIT SUPPORT
        If  your program may sometimes be linked with versions of PCRE that are
        older than 8.20, but you want to use JIT when it is available, you  can
        test the values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT
-       macro such as PCRE_CONFIG_JIT, for compile-time control of your code.
+       macro such as PCRE_CONFIG_JIT, for compile-time control of  your  code.
+       Also  beware that the pcre_jit_exec() function was not available at all
+       before 8.32, and may not be available at all  if  PCRE  isn't  compiled
+       with  --enable-jit.  See  the  "JIT  FAST  PATH  API" section below for
+       details.
 
 
 SIMPLE USE OF JIT
@@ -8403,6 +8411,18 @@ SIMPLE USE OF JIT
          PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
          PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
 
+       If using pcre_jit_exec() and supporting a pre-8.32 version of PCRE, you
+       can insert:
+
+          #if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
+          pcre_jit_exec(...);
+          #else
+          pcre_exec(...)
+          #endif
+
+       but  as described in the "JIT FAST PATH API" section below this assumes
+       version 8.32 and later are compiled with --enable-jit, which may break.
+
        The JIT compiler generates different optimized code  for  each  of  the
        three  modes  (normal, soft partial, hard partial). When pcre_exec() is
        called, the appropriate code is run if it is available. Otherwise,  the
@@ -8692,6 +8712,33 @@ JIT FAST PATH API
        Bypassing  the  sanity  checks  and  the  pcre_exec() wrapping can give
        speedups of more than 10%.
 
+       Note that the pcre_jit_exec() function is not available in versions  of
+       PCRE  before  8.32  (released in November 2012). If you need to support
+       versions that old you must either use the slower pcre_exec(), or switch
+       between  the  two  codepaths  by  checking the values of PCRE_MAJOR and
+       PCRE_MINOR.
+
+       Due to an unfortunate implementation oversight, even in  versions  8.32
+       and  later  there will be no pcre_jit_exec() stub function defined when
+       PCRE is compiled with --disable-jit, which is the default, and  there's
+       no  way  to  detect  whether  PCRE was compiled with --enable-jit via a
+       macro.
+
+       If you need to support versions older than 8.32, or versions  that  may
+       not   build   with   --enable-jit,  you  must  either  use  the  slower
+       pcre_exec(), or switch between the two codepaths by checking the values
+       of PCRE_MAJOR and PCRE_MINOR.
+
+       Switching  between the two by checking the version assumes that all the
+       versions being targeted are built with --enable-jit.  To  also  support
+       builds that may use --disable-jit either pcre_exec() must be used, or a
+       compile-time check for JIT via pcre_config() (which assumes the runtime
+       environment  will  be  the  same), or as the Git project decided to do,
+       simply assume that pcre_jit_exec() is present in 8.32 or later unless a
+       compile-time  flag  is  provided, see the "grep: un-break building with
+       PCRE >= 8.32 without --enable-jit" commit in git.git for an example  of
+       that.
+
 
 SEE ALSO
 
@@ -8707,8 +8754,8 @@ AUTHOR
 
 REVISION
 
-       Last updated: 17 March 2013
-       Copyright (c) 1997-2013 University of Cambridge.
+       Last updated: 05 July 2017
+       Copyright (c) 1997-2017 University of Cambridge.
 ------------------------------------------------------------------------------
 
 
index bf6351f8837b474c4cdcfd64bdab93ffd30ae466..442c6bdb5fe5c8801387671e8120a95c757b98df 100644 (file)
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
 /* The current PCRE version information. */
 
 #define PCRE_MAJOR          8
-#define PCRE_MINOR          38
+#define PCRE_MINOR          41
 #define PCRE_PRERELEASE     
-#define PCRE_DATE           2015-11-23
+#define PCRE_DATE           2017-07-05
 
 /* When an application links to a PCRE DLL in Windows, the symbols that are
 imported have to be identified as such. When building PCRE, the appropriate
index 11a9d26ff6a0c732a4fdd1e32f3fdf513c85f4a0..42f204cdfff63b135a31bb9fab02a8169eac1382 100644 (file)
@@ -6,7 +6,7 @@
 and semantics are as close as possible to those of the Perl 5 language.
 
                        Written by Philip Hazel
-           Copyright (c) 1997-2014 University of Cambridge
+           Copyright (c) 1997-2016 University of Cambridge
 
 -----------------------------------------------------------------------------
 Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
 supporting internal functions that are not used by other modules. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #define NLBLOCK cd             /* Block containing newline information */
 #define PSSTART start_pattern  /* Field containing pattern start */
@@ -483,7 +485,7 @@ static const char error_texts[] =
   "lookbehind assertion is not fixed length\0"
   "malformed number or name after (?(\0"
   "conditional group contains more than two branches\0"
-  "assertion expected after (?(\0"
+  "assertion expected after (?( or (?(?C)\0"
   "(?R or (?[+-]digits must be followed by )\0"
   /* 30 */
   "unknown POSIX class name\0"
@@ -558,6 +560,7 @@ static const char error_texts[] =
   /* 85 */
   "parentheses are too deeply nested (stack check)\0"
   "digits missing in \\x{} or \\o{}\0"
+  "regular expression is too complicated\0"
   ;
 
 /* Table to identify digits and hex digits. This is used when compiling
@@ -4564,6 +4567,10 @@ for (;; ptr++)
   pcre_uint32 ec;
   pcre_uchar mcbuffer[8];
 
+  /* Come here to restart the loop without advancing the pointer. */
+
+  REDO_LOOP:
+
   /* Get next character in the pattern */
 
   c = *ptr;
@@ -4589,7 +4596,8 @@ for (;; ptr++)
     if (code > cd->start_workspace + cd->workspace_size -
         WORK_SIZE_SAFETY_MARGIN)                       /* Check for overrun */
       {
-      *errorcodeptr = ERR52;
+      *errorcodeptr = (code >= cd->start_workspace + cd->workspace_size)?
+        ERR52 : ERR87;
       goto FAILED;
       }
 
@@ -4643,9 +4651,10 @@ for (;; ptr++)
     goto FAILED;
     }
 
-  /* If in \Q...\E, check for the end; if not, we have a literal */
+  /* If in \Q...\E, check for the end; if not, we have a literal. Otherwise an
+  isolated \E is ignored. */
 
-  if (inescq && c != CHAR_NULL)
+  if (c != CHAR_NULL)
     {
     if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)
       {
@@ -4653,7 +4662,7 @@ for (;; ptr++)
       ptr++;
       continue;
       }
-    else
+    else if (inescq)
       {
       if (previous_callout != NULL)
         {
@@ -4668,18 +4677,27 @@ for (;; ptr++)
         }
       goto NORMAL_CHAR;
       }
-    /* Control does not reach here. */
+
+    /* Check for the start of a \Q...\E sequence. We must do this here rather
+    than later in case it is immediately followed by \E, which turns it into a
+    "do nothing" sequence. */
+
+    if (c == CHAR_BACKSLASH && ptr[1] == CHAR_Q)
+      {
+      inescq = TRUE;
+      ptr++;
+      continue;
+      }
     }
 
-  /* In extended mode, skip white space and comments. We need a loop in order
-  to check for more white space and more comments after a comment. */
+  /* In extended mode, skip white space and comments. */
 
   if ((options & PCRE_EXTENDED) != 0)
     {
-    for (;;)
+    const pcre_uchar *wscptr = ptr;
+    while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr);
+    if (c == CHAR_NUMBER_SIGN)
       {
-      while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr);
-      if (c != CHAR_NUMBER_SIGN) break;
       ptr++;
       while (*ptr != CHAR_NULL)
         {
@@ -4693,8 +4711,29 @@ for (;; ptr++)
         if (utf) FORWARDCHAR(ptr);
 #endif
         }
-      c = *ptr;     /* Either NULL or the char after a newline */
       }
+
+    /* If we skipped any characters, restart the loop. Otherwise, we didn't see
+    a comment. */
+
+    if (ptr > wscptr) goto REDO_LOOP;
+    }
+
+  /* Skip over (?# comments. We need to do this here because we want to know if
+  the next thing is a quantifier, and these comments may come between an item
+  and its quantifier. */
+
+  if (c == CHAR_LEFT_PARENTHESIS && ptr[1] == CHAR_QUESTION_MARK &&
+      ptr[2] == CHAR_NUMBER_SIGN)
+    {
+    ptr += 3;
+    while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+    if (*ptr == CHAR_NULL)
+      {
+      *errorcodeptr = ERR18;
+      goto FAILED;
+      }
+    continue;
     }
 
   /* See if the next thing is a quantifier. */
@@ -4818,15 +4857,15 @@ for (;; ptr++)
     if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0)
       {
       nestptr = ptr + 7;
-      ptr = sub_start_of_word - 1;
-      continue;
+      ptr = sub_start_of_word;
+      goto REDO_LOOP;
       }
 
     if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0)
       {
       nestptr = ptr + 7;
-      ptr = sub_end_of_word - 1;
-      continue;
+      ptr = sub_end_of_word;
+      goto REDO_LOOP;
       }
 
     /* Handle a real character class. */
@@ -5044,20 +5083,22 @@ for (;; ptr++)
             ptr = tempptr + 1;
             continue;
 
-            /* For the other POSIX classes (ascii, xdigit) we are going to fall
-            through to the non-UCP case and build a bit map for characters with
-            code points less than 256. If we are in a negated POSIX class
-            within a non-negated overall class, characters with code points
-            greater than 255 must all match. In the special case where we have
-            not yet generated any xclass data, and this is the final item in
-            the overall class, we need do nothing: later on, the opcode
+            /* For the other POSIX classes (ascii, cntrl, xdigit) we are going
+            to fall through to the non-UCP case and build a bit map for
+            characters with code points less than 256. If we are in a negated
+            POSIX class, characters with code points greater than 255 must
+            either all match or all not match. In the special case where we
+            have not yet generated any xclass data, and this is the final item
+            in the overall class, we need do nothing: later on, the opcode
             OP_NCLASS will be used to indicate that characters greater than 255
             are acceptable. If we have already seen an xclass item or one may
             follow (we have to assume that it might if this is not the end of
-            the class), explicitly match all wide codepoints. */
+            the class), explicitly list all wide codepoints, which will then
+            either not match or match, depending on whether the class is or is
+            not negated. */
 
             default:
-            if (!negate_class && local_negate &&
+            if (local_negate &&
                 (xclass || tempptr[2] != CHAR_RIGHT_SQUARE_BRACKET))
               {
               *class_uchardata++ = XCL_RANGE;
@@ -5538,6 +5579,34 @@ for (;; ptr++)
 #endif
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
       {
+      /* For non-UCP wide characters, in a non-negative class containing \S or
+      similar (should_flip_negation is set), all characters greater than 255
+      must be in the class. */
+
+      if (
+#if defined COMPILE_PCRE8
+           utf &&
+#endif
+           should_flip_negation && !negate_class && (options & PCRE_UCP) == 0)
+        {
+        *class_uchardata++ = XCL_RANGE;
+        if (utf)   /* Will always be utf in the 8-bit library */
+          {
+          class_uchardata += PRIV(ord2utf)(0x100, class_uchardata);
+          class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
+          }
+        else       /* Can only happen for the 16-bit & 32-bit libraries */
+          {
+#if defined COMPILE_PCRE16
+          *class_uchardata++ = 0x100;
+          *class_uchardata++ = 0xffffu;
+#elif defined COMPILE_PCRE32
+          *class_uchardata++ = 0x100;
+          *class_uchardata++ = 0xffffffffu;
+#endif
+          }
+        }
+
       *class_uchardata++ = XCL_END;    /* Marks the end of extra data */
       *code++ = OP_XCLASS;
       code += LINK_SIZE;
@@ -5670,6 +5739,21 @@ for (;; ptr++)
       ptr = p - 1;    /* Character before the next significant one. */
       }
 
+    /* We also need to skip over (?# comments, which are not dependent on
+    extended mode. */
+
+    if (ptr[1] == CHAR_LEFT_PARENTHESIS && ptr[2] == CHAR_QUESTION_MARK &&
+        ptr[3] == CHAR_NUMBER_SIGN)
+      {
+      ptr += 4;
+      while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+      if (*ptr == CHAR_NULL)
+        {
+        *errorcodeptr = ERR18;
+        goto FAILED;
+        }
+      }
+
     /* If the next character is '+', we have a possessive quantifier. This
     implies greediness, whatever the setting of the PCRE_UNGREEDY option.
     If the next character is '?' this is a minimizing repeat, by default,
@@ -5770,7 +5854,7 @@ for (;; ptr++)
     /* If previous was a character type match (\d or similar), abolish it and
     create a suitable repeat item. The code is shared with single-character
     repeats by setting op_type to add a suitable offset into repeat_type. Note
-    that the Unicode property types will be present only when SUPPORT_UCP is
+    the the Unicode property types will be present only when SUPPORT_UCP is
     defined, but we don't wrap the little bits of code here because it just
     makes it horribly messy. */
 
@@ -6527,21 +6611,6 @@ for (;; ptr++)
     case CHAR_LEFT_PARENTHESIS:
     ptr++;
 
-    /* First deal with comments. Putting this code right at the start ensures
-    that comments have no bad side effects. */
-
-    if (ptr[0] == CHAR_QUESTION_MARK && ptr[1] == CHAR_NUMBER_SIGN)
-      {
-      ptr += 2;
-      while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
-      if (*ptr == CHAR_NULL)
-        {
-        *errorcodeptr = ERR18;
-        goto FAILED;
-        }
-      continue;
-      }
-
     /* Now deal with various "verbs" that can be introduced by '*'. */
 
     if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':'
@@ -6602,8 +6671,21 @@ for (;; ptr++)
             cd->had_accept = TRUE;
             for (oc = cd->open_caps; oc != NULL; oc = oc->next)
               {
-              *code++ = OP_CLOSE;
-              PUT2INC(code, 0, oc->number);
+              if (lengthptr != NULL)
+                {
+#ifdef COMPILE_PCRE8
+                *lengthptr += 1 + IMM2_SIZE;
+#elif defined COMPILE_PCRE16
+                *lengthptr += 2 + IMM2_SIZE;
+#elif defined COMPILE_PCRE32
+                *lengthptr += 4 + IMM2_SIZE;
+#endif
+                }
+              else
+                {
+                *code++ = OP_CLOSE;
+                PUT2INC(code, 0, oc->number);
+                }
               }
             setverb = *code++ =
               (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;
@@ -6732,6 +6814,15 @@ for (;; ptr++)
           for (i = 3;; i++) if (!IS_DIGIT(ptr[i])) break;
           if (ptr[i] == CHAR_RIGHT_PARENTHESIS)
             tempptr += i + 1;
+
+          /* tempptr should now be pointing to the opening parenthesis of the
+          assertion condition. */
+
+          if (*tempptr != CHAR_LEFT_PARENTHESIS)
+            {
+            *errorcodeptr = ERR28;
+            goto FAILED;
+            }
           }
 
         /* For conditions that are assertions, check the syntax, and then exit
@@ -6875,7 +6966,8 @@ for (;; ptr++)
         slot = cd->name_table;
         for (i = 0; i < cd->names_found; i++)
           {
-          if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0) break;
+          if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0 &&
+            slot[IMM2_SIZE+namelen] == 0) break;
           slot += cd->name_entry_size;
           }
 
@@ -7256,7 +7348,7 @@ for (;; ptr++)
           issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance
           only mode, we finesse the bug by allowing more memory always. */
 
-          *lengthptr += 2 + 2*LINK_SIZE;
+          *lengthptr += 4 + 4*LINK_SIZE;
 
           /* It is even worse than that. The current reference may be to an
           existing named group with a different number (so apparently not
@@ -7272,7 +7364,12 @@ for (;; ptr++)
           so far in order to get the number. If the name is not found, leave
           the value of recno as 0 for a forward reference. */
 
-          else
+          /* This patch (removing "else") fixes a problem when a reference is
+          to multiple identically named nested groups from within the nest.
+          Once again, it is not the "proper" fix, and it results in an
+          over-allocation of memory. */
+
+          /* else */
             {
             ng = cd->named_groups;
             for (i = 0; i < cd->names_found; i++, ng++)
@@ -7583,39 +7680,15 @@ for (;; ptr++)
         newoptions = (options | set) & (~unset);
 
         /* If the options ended with ')' this is not the start of a nested
-        group with option changes, so the options change at this level. If this
-        item is right at the start of the pattern, the options can be
-        abstracted and made external in the pre-compile phase, and ignored in
-        the compile phase. This can be helpful when matching -- for instance in
-        caseless checking of required bytes.
-
-        If the code pointer is not (cd->start_code + 1 + LINK_SIZE), we are
-        definitely *not* at the start of the pattern because something has been
-        compiled. In the pre-compile phase, however, the code pointer can have
-        that value after the start, because it gets reset as code is discarded
-        during the pre-compile. However, this can happen only at top level - if
-        we are within parentheses, the starting BRA will still be present. At
-        any parenthesis level, the length value can be used to test if anything
-        has been compiled at that level. Thus, a test for both these conditions
-        is necessary to ensure we correctly detect the start of the pattern in
-        both phases.
-
+        group with option changes, so the options change at this level.
         If we are not at the pattern start, reset the greedy defaults and the
         case value for firstchar and reqchar. */
 
         if (*ptr == CHAR_RIGHT_PARENTHESIS)
           {
-          if (code == cd->start_code + 1 + LINK_SIZE &&
-               (lengthptr == NULL || *lengthptr == 2 + 2*LINK_SIZE))
-            {
-            cd->external_options = newoptions;
-            }
-          else
-            {
-            greedy_default = ((newoptions & PCRE_UNGREEDY) != 0);
-            greedy_non_default = greedy_default ^ 1;
-            req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0;
-            }
+          greedy_default = ((newoptions & PCRE_UNGREEDY) != 0);
+          greedy_non_default = greedy_default ^ 1;
+          req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0;
 
           /* Change options at this level, and pass them back for use
           in subsequent branches. */
@@ -7860,15 +7933,17 @@ for (;; ptr++)
         }
       }
 
-    /* For a forward assertion, we take the reqchar, if set. This can be
-    helpful if the pattern that follows the assertion doesn't set a different
-    char. For example, it's useful for /(?=abcde).+/. We can't set firstchar
-    for an assertion, however because it leads to incorrect effect for patterns
-    such as /(?=a)a.+/ when the "real" "a" would then become a reqchar instead
-    of a firstchar. This is overcome by a scan at the end if there's no
-    firstchar, looking for an asserted first char. */
-
-    else if (bravalue == OP_ASSERT && subreqcharflags >= 0)
+    /* For a forward assertion, we take the reqchar, if set, provided that the
+    group has also set a first char. This can be helpful if the pattern that
+    follows the assertion doesn't set a different char. For example, it's
+    useful for /(?=abcde).+/. We can't set firstchar for an assertion, however
+    because it leads to incorrect effect for patterns such as /(?=a)a.+/ when
+    the "real" "a" would then become a reqchar instead of a firstchar. This is
+    overcome by a scan at the end if there's no firstchar, looking for an
+    asserted first char. */
+
+    else if (bravalue == OP_ASSERT && subreqcharflags >= 0 &&
+             subfirstcharflags >= 0)
       {
       reqchar = subreqchar;
       reqcharflags = subreqcharflags;
@@ -7894,16 +7969,6 @@ for (;; ptr++)
       c = ec;
     else
       {
-      if (escape == ESC_Q)            /* Handle start of quoted string */
-        {
-        if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
-          ptr += 2;               /* avoid empty string */
-            else inescq = TRUE;
-        continue;
-        }
-
-      if (escape == ESC_E) continue;  /* Perl ignores an orphan \E */
-
       /* For metasequences that actually match a character, we disable the
       setting of a first character if it hasn't already been set. */
 
@@ -8160,7 +8225,6 @@ for (;; ptr++)
 
       if (mclength == 1 || req_caseopt == 0)
         {
-        firstchar = mcbuffer[0] | req_caseopt;
         firstchar = mcbuffer[0];
         firstcharflags = req_caseopt;
 
@@ -8667,8 +8731,8 @@ matching and for non-DOTALL patterns that start with .* (which must start at
 the beginning or after \n). As in the case of is_anchored() (see above), we
 have to take account of back references to capturing brackets that contain .*
 because in that case we can't make the assumption. Also, the appearance of .*
-inside atomic brackets or in a pattern that contains *PRUNE or *SKIP does not
-count, because once again the assumption no longer holds.
+inside atomic brackets or in an assertion, or in a pattern that contains *PRUNE
+or *SKIP does not count, because once again the assumption no longer holds.
 
 Arguments:
   code           points to start of expression (the bracket)
@@ -8677,13 +8741,14 @@ Arguments:
                   the less precise approach
   cd             points to the compile data
   atomcount      atomic group level
+  inassert       TRUE if in an assertion
 
 Returns:         TRUE or FALSE
 */
 
 static BOOL
 is_startline(const pcre_uchar *code, unsigned int bracket_map,
-  compile_data *cd, int atomcount)
+  compile_data *cd, int atomcount, BOOL inassert)
 {
 do {
    const pcre_uchar *scode = first_significant_code(
@@ -8710,7 +8775,7 @@ do {
        return FALSE;
 
        default:     /* Assertion */
-       if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
+       if (!is_startline(scode, bracket_map, cd, atomcount, TRUE)) return FALSE;
        do scode += GET(scode, 1); while (*scode == OP_ALT);
        scode += 1 + LINK_SIZE;
        break;
@@ -8724,7 +8789,7 @@ do {
    if (op == OP_BRA  || op == OP_BRAPOS ||
        op == OP_SBRA || op == OP_SBRAPOS)
      {
-     if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
+     if (!is_startline(scode, bracket_map, cd, atomcount, inassert)) return FALSE;
      }
 
    /* Capturing brackets */
@@ -8734,33 +8799,33 @@ do {
      {
      int n = GET2(scode, 1+LINK_SIZE);
      int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
-     if (!is_startline(scode, new_map, cd, atomcount)) return FALSE;
+     if (!is_startline(scode, new_map, cd, atomcount, inassert)) return FALSE;
      }
 
    /* Positive forward assertions */
 
    else if (op == OP_ASSERT)
      {
-     if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
+     if (!is_startline(scode, bracket_map, cd, atomcount, TRUE)) return FALSE;
      }
 
    /* Atomic brackets */
 
    else if (op == OP_ONCE || op == OP_ONCE_NC)
      {
-     if (!is_startline(scode, bracket_map, cd, atomcount + 1)) return FALSE;
+     if (!is_startline(scode, bracket_map, cd, atomcount + 1, inassert)) return FALSE;
      }
 
    /* .* means "start at start or after \n" if it isn't in atomic brackets or
-   brackets that may be referenced, as long as the pattern does not contain
-   *PRUNE or *SKIP, because these break the feature. Consider, for example,
-   /.*?a(*PRUNE)b/ with the subject "aab", which matches "ab", i.e. not at the
-   start of a line. */
+   brackets that may be referenced or an assertion, as long as the pattern does
+   not contain *PRUNE or *SKIP, because these break the feature. Consider, for
+   example, /.*?a(*PRUNE)b/ with the subject "aab", which matches "ab", i.e.
+   not at the start of a line. */
 
    else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)
      {
      if (scode[1] != OP_ANY || (bracket_map & cd->backref_map) != 0 ||
-         atomcount > 0 || cd->had_pruneorskip)
+         atomcount > 0 || cd->had_pruneorskip || inassert)
        return FALSE;
      }
 
@@ -9615,7 +9680,7 @@ if ((re->options & PCRE_ANCHORED) == 0)
       re->flags |= PCRE_FIRSTSET;
       }
 
-    else if (is_startline(codestart, 0, cd, 0)) re->flags |= PCRE_STARTLINE;
+    else if (is_startline(codestart, 0, cd, 0, FALSE)) re->flags |= PCRE_STARTLINE;
     }
   }
 
index 92e3f0ebdb037a57d95158c8465d405e5068cbea..1cbdd9c960cec53fe064151aa63c154e4ccec14e 100644 (file)
@@ -41,7 +41,9 @@ POSSIBILITY OF SUCH DAMAGE.
 /* This module contains the external function pcre_config(). */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 /* Keep the original link size. */
 static int real_link_size = LINK_SIZE;
index c783ff6e7e7112f640601263d31db363ee93d553..1a9bdd546ee2f9c346b68a9a4b6a85986e732f61 100644 (file)
@@ -41,7 +41,9 @@ POSSIBILITY OF SUCH DAMAGE.
 pattern matching using an NFA algorithm, trying to mimic Perl as closely as
 possible. There are also some static supporting functions. */
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #define NLBLOCK md             /* Block containing newline information */
 #define PSSTART start_subject  /* Field containing processed string start */
@@ -667,7 +669,7 @@ if (ecode == NULL)
     return match((PCRE_PUCHAR)&rdepth, NULL, NULL, 0, NULL, NULL, 1);
   else
     {
-    int len = (char *)&rdepth - (char *)eptr;
+    int len = (int)((char *)&rdepth - (char *)eptr);
     return (len > 0)? -len : len;
     }
   }
index 3af0cec60b1f3cba920dd9c15f635f5a4ef7dfd3..a6c2ece6ca5a71ef382e6339875a682e6c76498a 100644 (file)
@@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
 information about a compiled pattern. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
index e7ea3a56a9c67d26dcda0388536a2d79663608c2..9475d5e88cdccc175303ca944f8f459d07822408 100644 (file)
@@ -43,7 +43,9 @@ from the subject string after a regex match has succeeded. The original idea
 for these functions came from Scott Wimer. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
@@ -248,6 +250,7 @@ Arguments:
   code         the compiled regex
   stringname   the name of the capturing substring
   ovector      the vector of matched substrings
+  stringcount  number of captured substrings
 
 Returns:       the number of the first that is set,
                or the number of the last one if none are set,
@@ -256,13 +259,16 @@ Returns:       the number of the first that is set,
 
 #if defined COMPILE_PCRE8
 static int
-get_first_set(const pcre *code, const char *stringname, int *ovector)
+get_first_set(const pcre *code, const char *stringname, int *ovector,
+  int stringcount)
 #elif defined COMPILE_PCRE16
 static int
-get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector)
+get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector,
+  int stringcount)
 #elif defined COMPILE_PCRE32
 static int
-get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector)
+get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector,
+  int stringcount)
 #endif
 {
 const REAL_PCRE *re = (const REAL_PCRE *)code;
@@ -293,7 +299,7 @@ if (entrysize <= 0) return entrysize;
 for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize)
   {
   int n = GET2(entry, 0);
-  if (ovector[n*2] >= 0) return n;
+  if (n < stringcount && ovector[n*2] >= 0) return n;
   }
 return GET2(entry, 0);
 }
@@ -400,7 +406,7 @@ pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
   PCRE_UCHAR32 *buffer, int size)
 #endif
 {
-int n = get_first_set(code, stringname, ovector);
+int n = get_first_set(code, stringname, ovector, stringcount);
 if (n <= 0) return n;
 #if defined COMPILE_PCRE8
 return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
@@ -455,7 +461,10 @@ pcre_uchar **stringlist;
 pcre_uchar *p;
 
 for (i = 0; i < double_count; i += 2)
-  size += sizeof(pcre_uchar *) + IN_UCHARS(ovector[i+1] - ovector[i] + 1);
+  {
+  size += sizeof(pcre_uchar *) + IN_UCHARS(1);
+  if (ovector[i+1] > ovector[i]) size += IN_UCHARS(ovector[i+1] - ovector[i]);
+  }
 
 stringlist = (pcre_uchar **)(PUBL(malloc))(size);
 if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;
@@ -471,7 +480,7 @@ p = (pcre_uchar *)(stringlist + stringcount + 1);
 
 for (i = 0; i < double_count; i += 2)
   {
-  int len = ovector[i+1] - ovector[i];
+  int len = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0;
   memcpy(p, subject + ovector[i], IN_UCHARS(len));
   *stringlist++ = p;
   p += len;
@@ -617,7 +626,7 @@ pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
   PCRE_SPTR32 *stringptr)
 #endif
 {
-int n = get_first_set(code, stringname, ovector);
+int n = get_first_set(code, stringname, ovector, stringcount);
 if (n <= 0) return n;
 #if defined COMPILE_PCRE8
 return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
index 4aab651c526e245c38ff1a23f0baa47dbf0a52a2..0f106aa9013c1606b820af4d28ce77bf1b910958 100644 (file)
@@ -52,7 +52,9 @@ a local function is used.
 Also, when compiling for Virtual Pascal, things are done differently, and
 global variables are not used. */
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
index f7a5ee7aa6f3b543851eee09bf5a7c7df2a6408e..97ff55d03b329814296d009f49fdbe48bdf0c798 100644 (file)
@@ -7,7 +7,7 @@
 and semantics are as close as possible to those of the Perl 5 language.
 
                        Written by Philip Hazel
-           Copyright (c) 1997-2014 University of Cambridge
+           Copyright (c) 1997-2016 University of Cambridge
 
 -----------------------------------------------------------------------------
 Redistribution and use in source and binary forms, with or without
@@ -275,7 +275,7 @@ pcre.h(.in) and disable (comment out) this message. */
 
 typedef pcre_uint16 pcre_uchar;
 #define UCHAR_SHIFT (1)
-#define IN_UCHARS(x) ((x) << UCHAR_SHIFT)
+#define IN_UCHARS(x) ((x) * 2)
 #define MAX_255(c) ((c) <= 255u)
 #define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))
 
@@ -283,7 +283,7 @@ typedef pcre_uint16 pcre_uchar;
 
 typedef pcre_uint32 pcre_uchar;
 #define UCHAR_SHIFT (2)
-#define IN_UCHARS(x) ((x) << UCHAR_SHIFT)
+#define IN_UCHARS(x) ((x) * 4)
 #define MAX_255(c) ((c) <= 255u)
 #define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))
 
@@ -2289,7 +2289,7 @@ enum { ERR0,  ERR1,  ERR2,  ERR3,  ERR4,  ERR5,  ERR6,  ERR7,  ERR8,  ERR9,
        ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59,
        ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69,
        ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79,
-       ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERRCOUNT };
+       ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERRCOUNT };
 
 /* JIT compiling modes. The function list is indexed by them. */
 
@@ -2772,6 +2772,9 @@ extern const pcre_uint8  PRIV(ucd_stage1)[];
 extern const pcre_uint16 PRIV(ucd_stage2)[];
 extern const pcre_uint32 PRIV(ucp_gentype)[];
 extern const pcre_uint32 PRIV(ucp_gbtable)[];
+#ifdef COMPILE_PCRE32
+extern const ucd_record  PRIV(dummy_ucd_record)[];
+#endif
 #ifdef SUPPORT_JIT
 extern const int         PRIV(ucp_typerange)[];
 #endif
@@ -2780,10 +2783,16 @@ extern const int         PRIV(ucp_typerange)[];
 /* UCD access macros */
 
 #define UCD_BLOCK_SIZE 128
-#define GET_UCD(ch) (PRIV(ucd_records) + \
+#define REAL_GET_UCD(ch) (PRIV(ucd_records) + \
         PRIV(ucd_stage2)[PRIV(ucd_stage1)[(int)(ch) / UCD_BLOCK_SIZE] * \
         UCD_BLOCK_SIZE + (int)(ch) % UCD_BLOCK_SIZE])
 
+#ifdef COMPILE_PCRE32
+#define GET_UCD(ch) ((ch > 0x10ffff)? PRIV(dummy_ucd_record) : REAL_GET_UCD(ch))
+#else
+#define GET_UCD(ch) REAL_GET_UCD(ch)
+#endif
+
 #define UCD_CHARTYPE(ch)    GET_UCD(ch)->chartype
 #define UCD_SCRIPT(ch)      GET_UCD(ch)->script
 #define UCD_CATEGORY(ch)    PRIV(ucp_gentype)[UCD_CHARTYPE(ch)]
index 4684be751a05697c087c3259dee970c2446700f2..249edbe8e7f4f0e5820693bd7fa9e172b264bff6 100644 (file)
@@ -168,13 +168,13 @@ typedef struct jit_arguments {
   pcre_uchar *mark_ptr;
   void *callout_data;
   /* Everything else after. */
-  pcre_uint32 limit_match;
+  sljit_u32 limit_match;
   int real_offset_count;
   int offset_count;
-  pcre_uint8 notbol;
-  pcre_uint8 noteol;
-  pcre_uint8 notempty;
-  pcre_uint8 notempty_atstart;
+  sljit_u8 notbol;
+  sljit_u8 noteol;
+  sljit_u8 notempty;
+  sljit_u8 notempty_atstart;
 } jit_arguments;
 
 typedef struct executable_functions {
@@ -183,8 +183,8 @@ typedef struct executable_functions {
   sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
   PUBL(jit_callback) callback;
   void *userdata;
-  pcre_uint32 top_bracket;
-  pcre_uint32 limit_match;
+  sljit_u32 top_bracket;
+  sljit_u32 limit_match;
 } executable_functions;
 
 typedef struct jump_list {
@@ -277,11 +277,25 @@ typedef struct braminzero_backtrack {
   struct sljit_label *matchingpath;
 } braminzero_backtrack;
 
-typedef struct iterator_backtrack {
+typedef struct char_iterator_backtrack {
   backtrack_common common;
   /* Next iteration. */
   struct sljit_label *matchingpath;
-} iterator_backtrack;
+  union {
+    jump_list *backtracks;
+    struct {
+      unsigned int othercasebit;
+      pcre_uchar chr;
+      BOOL enabled;
+    } charpos;
+  } u;
+} char_iterator_backtrack;
+
+typedef struct ref_iterator_backtrack {
+  backtrack_common common;
+  /* Next iteration. */
+  struct sljit_label *matchingpath;
+} ref_iterator_backtrack;
 
 typedef struct recurse_entry {
   struct recurse_entry *next;
@@ -321,40 +335,46 @@ typedef struct compiler_common {
   /* First byte code. */
   pcre_uchar *start;
   /* Maps private data offset to each opcode. */
-  sljit_si *private_data_ptrs;
+  sljit_s32 *private_data_ptrs;
   /* Chain list of read-only data ptrs. */
   void *read_only_data_head;
   /* Tells whether the capturing bracket is optimized. */
-  pcre_uint8 *optimized_cbracket;
+  sljit_u8 *optimized_cbracket;
   /* Tells whether the starting offset is a target of then. */
-  pcre_uint8 *then_offsets;
+  sljit_u8 *then_offsets;
   /* Current position where a THEN must jump. */
   then_trap_backtrack *then_trap;
   /* Starting offset of private data for capturing brackets. */
-  int cbra_ptr;
+  sljit_s32 cbra_ptr;
   /* Output vector starting point. Must be divisible by 2. */
-  int ovector_start;
+  sljit_s32 ovector_start;
+  /* Points to the starting character of the current match. */
+  sljit_s32 start_ptr;
   /* Last known position of the requested byte. */
-  int req_char_ptr;
+  sljit_s32 req_char_ptr;
   /* Head of the last recursion. */
-  int recursive_head_ptr;
-  /* First inspected character for partial matching. */
-  int start_used_ptr;
+  sljit_s32 recursive_head_ptr;
+  /* First inspected character for partial matching.
+     (Needed for avoiding zero length partial matches.) */
+  sljit_s32 start_used_ptr;
   /* Starting pointer for partial soft matches. */
-  int hit_start;
-  /* End pointer of the first line. */
-  int first_line_end;
+  sljit_s32 hit_start;
+  /* Pointer of the match end position. */
+  sljit_s32 match_end_ptr;
   /* Points to the marked string. */
-  int mark_ptr;
+  sljit_s32 mark_ptr;
   /* Recursive control verb management chain. */
-  int control_head_ptr;
+  sljit_s32 control_head_ptr;
   /* Points to the last matched capture block index. */
-  int capture_last_ptr;
-  /* Points to the starting position of the current match. */
-  int start_ptr;
+  sljit_s32 capture_last_ptr;
+  /* Fast forward skipping byte code pointer. */
+  pcre_uchar *fast_forward_bc_ptr;
+  /* Locals used by fast fail optimization. */
+  sljit_s32 fast_fail_start_ptr;
+  sljit_s32 fast_fail_end_ptr;
 
   /* Flipped and lower case tables. */
-  const pcre_uint8 *fcc;
+  const sljit_u8 *fcc;
   sljit_sw lcc;
   /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */
   int mode;
@@ -366,20 +386,20 @@ typedef struct compiler_common {
   BOOL has_skip_arg;
   /* (*THEN) is found in the pattern. */
   BOOL has_then;
-  /* Needs to know the start position anytime. */
-  BOOL needs_start_ptr;
+  /* (*SKIP) or (*SKIP:arg) is found in lookbehind assertion. */
+  BOOL has_skip_in_assert_back;
   /* Currently in recurse or negative assert. */
   BOOL local_exit;
   /* Currently in a positive assert. */
   BOOL positive_assert;
   /* Newline control. */
   int nltype;
-  pcre_uint32 nlmax;
-  pcre_uint32 nlmin;
+  sljit_u32 nlmax;
+  sljit_u32 nlmin;
   int newline;
   int bsr_nltype;
-  pcre_uint32 bsr_nlmax;
-  pcre_uint32 bsr_nlmin;
+  sljit_u32 bsr_nlmax;
+  sljit_u32 bsr_nlmin;
   /* Dollar endonly. */
   int endonly;
   /* Tables. */
@@ -419,6 +439,7 @@ typedef struct compiler_common {
   BOOL utf;
 #ifdef SUPPORT_UCP
   BOOL use_ucp;
+  jump_list *getucd;
 #endif
 #ifdef COMPILE_PCRE8
   jump_list *utfreadchar;
@@ -426,9 +447,6 @@ typedef struct compiler_common {
   jump_list *utfreadtype8;
 #endif
 #endif /* SUPPORT_UTF */
-#ifdef SUPPORT_UCP
-  jump_list *getucd;
-#endif
 } compiler_common;
 
 /* For byte_sequence_compare. */
@@ -439,27 +457,27 @@ typedef struct compare_context {
 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
   int ucharptr;
   union {
-    sljit_si asint;
-    sljit_uh asushort;
+    sljit_s32 asint;
+    sljit_u16 asushort;
 #if defined COMPILE_PCRE8
-    sljit_ub asbyte;
-    sljit_ub asuchars[4];
+    sljit_u8 asbyte;
+    sljit_u8 asuchars[4];
 #elif defined COMPILE_PCRE16
-    sljit_uh asuchars[2];
+    sljit_u16 asuchars[2];
 #elif defined COMPILE_PCRE32
-    sljit_ui asuchars[1];
+    sljit_u32 asuchars[1];
 #endif
   } c;
   union {
-    sljit_si asint;
-    sljit_uh asushort;
+    sljit_s32 asint;
+    sljit_u16 asushort;
 #if defined COMPILE_PCRE8
-    sljit_ub asbyte;
-    sljit_ub asuchars[4];
+    sljit_u8 asbyte;
+    sljit_u8 asuchars[4];
 #elif defined COMPILE_PCRE16
-    sljit_uh asuchars[2];
+    sljit_u16 asuchars[2];
 #elif defined COMPILE_PCRE32
-    sljit_ui asuchars[1];
+    sljit_u32 asuchars[1];
 #endif
   } oc;
 #endif
@@ -469,7 +487,7 @@ typedef struct compare_context {
 #undef CMP
 
 /* Used for accessing the elements of the stack. */
-#define STACK(i)      ((-(i) - 1) * (int)sizeof(sljit_sw))
+#define STACK(i)      ((i) * (int)sizeof(sljit_sw))
 
 #define TMP1          SLJIT_R0
 #define TMP2          SLJIT_R2
@@ -501,14 +519,14 @@ the start pointers when the end of the capturing group has not yet reached. */
 #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])
 
 #if defined COMPILE_PCRE8
-#define MOV_UCHAR  SLJIT_MOV_UB
-#define MOVU_UCHAR SLJIT_MOVU_UB
+#define MOV_UCHAR  SLJIT_MOV_U8
+#define MOVU_UCHAR SLJIT_MOVU_U8
 #elif defined COMPILE_PCRE16
-#define MOV_UCHAR  SLJIT_MOV_UH
-#define MOVU_UCHAR SLJIT_MOVU_UH
+#define MOV_UCHAR  SLJIT_MOV_U16
+#define MOVU_UCHAR SLJIT_MOVU_U16
 #elif defined COMPILE_PCRE32
-#define MOV_UCHAR  SLJIT_MOV_UI
-#define MOVU_UCHAR SLJIT_MOVU_UI
+#define MOV_UCHAR  SLJIT_MOV_U32
+#define MOVU_UCHAR SLJIT_MOVU_U32
 #else
 #error Unsupported compiling mode
 #endif
@@ -534,13 +552,15 @@ the start pointers when the end of the capturing group has not yet reached. */
   sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
 #define CMPTO(type, src1, src1w, src2, src2w, label) \
   sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
-#define OP_FLAGS(op, dst, dstw, src, srcw, type) \
-  sljit_emit_op_flags(compiler, (op), (dst), (dstw), (src), (srcw), (type))
+#define OP_FLAGS(op, dst, dstw, type) \
+  sljit_emit_op_flags(compiler, (op), (dst), (dstw), (type))
 #define GET_LOCAL_BASE(dst, dstw, offset) \
   sljit_get_local_base(compiler, (dst), (dstw), (offset))
 
 #define READ_CHAR_MAX 0x7fffffff
 
+#define INVALID_UTF_CHAR 888
+
 static pcre_uchar *bracketend(pcre_uchar *cc)
 {
 SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
@@ -564,11 +584,6 @@ SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
 return count;
 }
 
-static int ones_in_half_byte[16] = {
-  /* 0 */ 0, 1, 1, 2, /* 4 */ 1, 2, 2, 3,
-  /* 8 */ 1, 2, 2, 3, /* 12 */ 2, 3, 3, 4
-};
-
 /* Functions whose might need modification for all new supported opcodes:
  next_opcode
  check_opcode_types
@@ -771,7 +786,7 @@ switch(*cc)
 
   default:
   /* All opcodes are supported now! */
-  SLJIT_ASSERT_STOP();
+  SLJIT_UNREACHABLE();
   return NULL;
   }
 }
@@ -780,6 +795,7 @@ static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uch
 {
 int count;
 pcre_uchar *slot;
+pcre_uchar *assert_back_end = cc - 1;
 
 /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
 while (cc < ccend)
@@ -850,15 +866,19 @@ while (cc < ccend)
     cc += 2 + 2 * LINK_SIZE;
     break;
 
+    case OP_ASSERTBACK:
+    slot = bracketend(cc);
+    if (slot > assert_back_end)
+      assert_back_end = slot;
+    cc += 1 + LINK_SIZE;
+    break;
+
     case OP_THEN_ARG:
     common->has_then = TRUE;
     common->control_head_ptr = 1;
     /* Fall through. */
 
     case OP_PRUNE_ARG:
-    common->needs_start_ptr = TRUE;
-    /* Fall through. */
-
     case OP_MARK:
     if (common->mark_ptr == 0)
       {
@@ -871,17 +891,20 @@ while (cc < ccend)
     case OP_THEN:
     common->has_then = TRUE;
     common->control_head_ptr = 1;
-    /* Fall through. */
+    cc += 1;
+    break;
 
-    case OP_PRUNE:
     case OP_SKIP:
-    common->needs_start_ptr = TRUE;
+    if (cc < assert_back_end)
+      common->has_skip_in_assert_back = TRUE;
     cc += 1;
     break;
 
     case OP_SKIP_ARG:
     common->control_head_ptr = 1;
     common->has_skip_arg = TRUE;
+    if (cc < assert_back_end)
+      common->has_skip_in_assert_back = TRUE;
     cc += 1 + 2 + cc[1];
     break;
 
@@ -895,8 +918,189 @@ while (cc < ccend)
 return TRUE;
 }
 
+static BOOL is_accelerated_repeat(pcre_uchar *cc)
+{
+switch(*cc)
+  {
+  case OP_TYPESTAR:
+  case OP_TYPEMINSTAR:
+  case OP_TYPEPLUS:
+  case OP_TYPEMINPLUS:
+  case OP_TYPEPOSSTAR:
+  case OP_TYPEPOSPLUS:
+  return (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI);
+
+  case OP_STAR:
+  case OP_MINSTAR:
+  case OP_PLUS:
+  case OP_MINPLUS:
+  case OP_POSSTAR:
+  case OP_POSPLUS:
+
+  case OP_STARI:
+  case OP_MINSTARI:
+  case OP_PLUSI:
+  case OP_MINPLUSI:
+  case OP_POSSTARI:
+  case OP_POSPLUSI:
+
+  case OP_NOTSTAR:
+  case OP_NOTMINSTAR:
+  case OP_NOTPLUS:
+  case OP_NOTMINPLUS:
+  case OP_NOTPOSSTAR:
+  case OP_NOTPOSPLUS:
+
+  case OP_NOTSTARI:
+  case OP_NOTMINSTARI:
+  case OP_NOTPLUSI:
+  case OP_NOTMINPLUSI:
+  case OP_NOTPOSSTARI:
+  case OP_NOTPOSPLUSI:
+  return TRUE;
+
+  case OP_CLASS:
+  case OP_NCLASS:
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+  case OP_XCLASS:
+  cc += (*cc == OP_XCLASS) ? GET(cc, 1) : (int)(1 + (32 / sizeof(pcre_uchar)));
+#else
+  cc += (1 + (32 / sizeof(pcre_uchar)));
+#endif
+
+  switch(*cc)
+    {
+    case OP_CRSTAR:
+    case OP_CRMINSTAR:
+    case OP_CRPLUS:
+    case OP_CRMINPLUS:
+    case OP_CRPOSSTAR:
+    case OP_CRPOSPLUS:
+    return TRUE;
+    }
+  break;
+  }
+return FALSE;
+}
+
+static SLJIT_INLINE BOOL detect_fast_forward_skip(compiler_common *common, int *private_data_start)
+{
+pcre_uchar *cc = common->start;
+pcre_uchar *end;
+
+/* Skip not repeated brackets. */
+while (TRUE)
+  {
+  switch(*cc)
+    {
+    case OP_SOD:
+    case OP_SOM:
+    case OP_SET_SOM:
+    case OP_NOT_WORD_BOUNDARY:
+    case OP_WORD_BOUNDARY:
+    case OP_EODN:
+    case OP_EOD:
+    case OP_CIRC:
+    case OP_CIRCM:
+    case OP_DOLL:
+    case OP_DOLLM:
+    /* Zero width assertions. */
+    cc++;
+    continue;
+    }
+
+  if (*cc != OP_BRA && *cc != OP_CBRA)
+    break;
+
+  end = cc + GET(cc, 1);
+  if (*end != OP_KET || PRIVATE_DATA(end) != 0)
+    return FALSE;
+  if (*cc == OP_CBRA)
+    {
+    if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
+      return FALSE;
+    cc += IMM2_SIZE;
+    }
+  cc += 1 + LINK_SIZE;
+  }
+
+if (is_accelerated_repeat(cc))
+  {
+  common->fast_forward_bc_ptr = cc;
+  common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start;
+  *private_data_start += sizeof(sljit_sw);
+  return TRUE;
+  }
+return FALSE;
+}
+
+static SLJIT_INLINE void detect_fast_fail(compiler_common *common, pcre_uchar *cc, int *private_data_start, sljit_s32 depth)
+{
+  pcre_uchar *next_alt;
+
+  SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA);
+
+  if (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
+    return;
+
+  next_alt = bracketend(cc) - (1 + LINK_SIZE);
+  if (*next_alt != OP_KET || PRIVATE_DATA(next_alt) != 0)
+    return;
+
+  do
+    {
+    next_alt = cc + GET(cc, 1);
+
+    cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0);
+
+    while (TRUE)
+      {
+      switch(*cc)
+        {
+        case OP_SOD:
+        case OP_SOM:
+        case OP_SET_SOM:
+        case OP_NOT_WORD_BOUNDARY:
+        case OP_WORD_BOUNDARY:
+        case OP_EODN:
+        case OP_EOD:
+        case OP_CIRC:
+        case OP_CIRCM:
+        case OP_DOLL:
+        case OP_DOLLM:
+        /* Zero width assertions. */
+        cc++;
+        continue;
+        }
+      break;
+      }
+
+    if (depth > 0 && (*cc == OP_BRA || *cc == OP_CBRA))
+      detect_fast_fail(common, cc, private_data_start, depth - 1);
+
+    if (is_accelerated_repeat(cc))
+      {
+      common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start;
+
+      if (common->fast_fail_start_ptr == 0)
+        common->fast_fail_start_ptr = *private_data_start;
+
+      *private_data_start += sizeof(sljit_sw);
+      common->fast_fail_end_ptr = *private_data_start;
+
+      if (*private_data_start > SLJIT_MAX_LOCAL_SIZE)
+        return;
+      }
+
+    cc = next_alt;
+    }
+  while (*cc == OP_ALT);
+}
+
 static int get_class_iterator_size(pcre_uchar *cc)
 {
+sljit_u32 min;
+sljit_u32 max;
 switch(*cc)
   {
   case OP_CRSTAR:
@@ -911,9 +1115,14 @@ switch(*cc)
 
   case OP_CRRANGE:
   case OP_CRMINRANGE:
-  if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE))
-    return 0;
-  return 2;
+  min = GET2(cc, 1);
+  max = GET2(cc, 1 + IMM2_SIZE);
+  if (max == 0)
+    return (*cc == OP_CRRANGE) ? 2 : 1;
+  max -= min;
+  if (max > 2)
+    max = 2;
+  return max;
 
   default:
   return 0;
@@ -1186,14 +1395,14 @@ while (cc < ccend)
 
     case OP_CLASS:
     case OP_NCLASS:
-    size += 1 + 32 / sizeof(pcre_uchar);
     space = get_class_iterator_size(cc + size);
+    size = 1 + 32 / sizeof(pcre_uchar);
     break;
 
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
     case OP_XCLASS:
-    size = GET(cc, 1);
     space = get_class_iterator_size(cc + size);
+    size = GET(cc, 1);
     break;
 #endif
 
@@ -1406,6 +1615,7 @@ while (cc < ccend)
     case OP_CLASS:
     case OP_NCLASS:
     case OP_XCLASS:
+    case OP_CALLOUT:
 
     cc = next_opcode(common, cc);
     SLJIT_ASSERT(cc != NULL);
@@ -1452,9 +1662,9 @@ while (cc < ccend)
       {
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       setsom_found = TRUE;
       }
     cc += 1;
@@ -1468,9 +1678,9 @@ while (cc < ccend)
       {
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       setmark_found = TRUE;
       }
     cc += 1 + 2 + cc[1];
@@ -1481,27 +1691,27 @@ while (cc < ccend)
       {
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       setsom_found = TRUE;
       }
     if (common->mark_ptr != 0 && !setmark_found)
       {
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       setmark_found = TRUE;
       }
     if (common->capture_last_ptr != 0 && !capture_last_found)
       {
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       capture_last_found = TRUE;
       }
     cc += 1 + LINK_SIZE;
@@ -1515,20 +1725,20 @@ while (cc < ccend)
       {
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
-      stackpos += (int)sizeof(sljit_sw);
+      stackpos -= (int)sizeof(sljit_sw);
       capture_last_found = TRUE;
       }
     offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
-    stackpos += (int)sizeof(sljit_sw);
+    stackpos -= (int)sizeof(sljit_sw);
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
-    stackpos += (int)sizeof(sljit_sw);
+    stackpos -= (int)sizeof(sljit_sw);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
-    stackpos += (int)sizeof(sljit_sw);
+    stackpos -= (int)sizeof(sljit_sw);
 
     cc += 1 + LINK_SIZE + IMM2_SIZE;
     break;
@@ -1679,18 +1889,17 @@ BOOL tmp1empty = TRUE;
 BOOL tmp2empty = TRUE;
 pcre_uchar *alternative;
 enum {
-  start,
   loop,
   end
 } status;
 
-status = save ? start : loop;
-stackptr = STACK(stackptr - 2);
+status = loop;
+stackptr = STACK(stackptr);
 stacktop = STACK(stacktop - 1);
 
 if (!save)
   {
-  stackptr += (needs_control_head ? 2 : 1) * sizeof(sljit_sw);
+  stacktop -= (needs_control_head ? 2 : 1) * sizeof(sljit_sw);
   if (stackptr < stacktop)
     {
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
@@ -1706,196 +1915,186 @@ if (!save)
   /* The tmp1next must be TRUE in either way. */
   }
 
+SLJIT_ASSERT(common->recursive_head_ptr != 0);
+
 do
   {
   count = 0;
-  switch(status)
+  if (cc >= ccend)
     {
-    case start:
-    SLJIT_ASSERT(save && common->recursive_head_ptr != 0);
+    if (!save)
+      break;
+
     count = 1;
     srcw[0] = common->recursive_head_ptr;
     if (needs_control_head)
       {
       SLJIT_ASSERT(common->control_head_ptr != 0);
       count = 2;
-      srcw[1] = common->control_head_ptr;
+      srcw[0] = common->control_head_ptr;
+      srcw[1] = common->recursive_head_ptr;
+      }
+    status = end;
+    }
+  else switch(*cc)
+    {
+    case OP_KET:
+    if (PRIVATE_DATA(cc) != 0)
+      {
+      count = 1;
+      srcw[0] = PRIVATE_DATA(cc);
+      SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
+      cc += PRIVATE_DATA(cc + 1);
       }
-    status = loop;
+    cc += 1 + LINK_SIZE;
+    break;
+
+    case OP_ASSERT:
+    case OP_ASSERT_NOT:
+    case OP_ASSERTBACK:
+    case OP_ASSERTBACK_NOT:
+    case OP_ONCE:
+    case OP_ONCE_NC:
+    case OP_BRAPOS:
+    case OP_SBRA:
+    case OP_SBRAPOS:
+    case OP_SCOND:
+    count = 1;
+    srcw[0] = PRIVATE_DATA(cc);
+    SLJIT_ASSERT(srcw[0] != 0);
+    cc += 1 + LINK_SIZE;
     break;
 
-    case loop:
-    if (cc >= ccend)
+    case OP_CBRA:
+    case OP_SCBRA:
+    if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
       {
-      status = end;
-      break;
+      count = 1;
+      srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
       }
+    cc += 1 + LINK_SIZE + IMM2_SIZE;
+    break;
 
-    switch(*cc)
-      {
-      case OP_KET:
-      if (PRIVATE_DATA(cc) != 0)
-        {
-        count = 1;
-        srcw[0] = PRIVATE_DATA(cc);
-        SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
-        cc += PRIVATE_DATA(cc + 1);
-        }
-      cc += 1 + LINK_SIZE;
-      break;
+    case OP_CBRAPOS:
+    case OP_SCBRAPOS:
+    count = 2;
+    srcw[0] = PRIVATE_DATA(cc);
+    srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
+    SLJIT_ASSERT(srcw[0] != 0 && srcw[1] != 0);
+    cc += 1 + LINK_SIZE + IMM2_SIZE;
+    break;
 
-      case OP_ASSERT:
-      case OP_ASSERT_NOT:
-      case OP_ASSERTBACK:
-      case OP_ASSERTBACK_NOT:
-      case OP_ONCE:
-      case OP_ONCE_NC:
-      case OP_BRAPOS:
-      case OP_SBRA:
-      case OP_SBRAPOS:
-      case OP_SCOND:
+    case OP_COND:
+    /* Might be a hidden SCOND. */
+    alternative = cc + GET(cc, 1);
+    if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
+      {
       count = 1;
       srcw[0] = PRIVATE_DATA(cc);
       SLJIT_ASSERT(srcw[0] != 0);
-      cc += 1 + LINK_SIZE;
-      break;
-
-      case OP_CBRA:
-      case OP_SCBRA:
-      if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
-        {
-        count = 1;
-        srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
-        }
-      cc += 1 + LINK_SIZE + IMM2_SIZE;
-      break;
+      }
+    cc += 1 + LINK_SIZE;
+    break;
 
-      case OP_CBRAPOS:
-      case OP_SCBRAPOS:
-      count = 2;
+    CASE_ITERATOR_PRIVATE_DATA_1
+    if (PRIVATE_DATA(cc))
+      {
+      count = 1;
       srcw[0] = PRIVATE_DATA(cc);
-      srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
-      SLJIT_ASSERT(srcw[0] != 0 && srcw[1] != 0);
-      cc += 1 + LINK_SIZE + IMM2_SIZE;
-      break;
-
-      case OP_COND:
-      /* Might be a hidden SCOND. */
-      alternative = cc + GET(cc, 1);
-      if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
-        {
-        count = 1;
-        srcw[0] = PRIVATE_DATA(cc);
-        SLJIT_ASSERT(srcw[0] != 0);
-        }
-      cc += 1 + LINK_SIZE;
-      break;
-
-      CASE_ITERATOR_PRIVATE_DATA_1
-      if (PRIVATE_DATA(cc))
-        {
-        count = 1;
-        srcw[0] = PRIVATE_DATA(cc);
-        }
-      cc += 2;
+      }
+    cc += 2;
 #ifdef SUPPORT_UTF
-      if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+    if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
 #endif
-      break;
+    break;
 
-      CASE_ITERATOR_PRIVATE_DATA_2A
-      if (PRIVATE_DATA(cc))
-        {
-        count = 2;
-        srcw[0] = PRIVATE_DATA(cc);
-        srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
-        }
-      cc += 2;
+    CASE_ITERATOR_PRIVATE_DATA_2A
+    if (PRIVATE_DATA(cc))
+      {
+      count = 2;
+      srcw[0] = PRIVATE_DATA(cc);
+      srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+      }
+    cc += 2;
 #ifdef SUPPORT_UTF
-      if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+    if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
 #endif
-      break;
+    break;
 
-      CASE_ITERATOR_PRIVATE_DATA_2B
-      if (PRIVATE_DATA(cc))
-        {
-        count = 2;
-        srcw[0] = PRIVATE_DATA(cc);
-        srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
-        }
-      cc += 2 + IMM2_SIZE;
+    CASE_ITERATOR_PRIVATE_DATA_2B
+    if (PRIVATE_DATA(cc))
+      {
+      count = 2;
+      srcw[0] = PRIVATE_DATA(cc);
+      srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+      }
+    cc += 2 + IMM2_SIZE;
 #ifdef SUPPORT_UTF
-      if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+    if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
 #endif
-      break;
+    break;
+
+    CASE_ITERATOR_TYPE_PRIVATE_DATA_1
+    if (PRIVATE_DATA(cc))
+      {
+      count = 1;
+      srcw[0] = PRIVATE_DATA(cc);
+      }
+    cc += 1;
+    break;
+
+    CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
+    if (PRIVATE_DATA(cc))
+      {
+      count = 2;
+      srcw[0] = PRIVATE_DATA(cc);
+      srcw[1] = srcw[0] + sizeof(sljit_sw);
+      }
+    cc += 1;
+    break;
+
+    CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
+    if (PRIVATE_DATA(cc))
+      {
+      count = 2;
+      srcw[0] = PRIVATE_DATA(cc);
+      srcw[1] = srcw[0] + sizeof(sljit_sw);
+      }
+    cc += 1 + IMM2_SIZE;
+    break;
 
-      CASE_ITERATOR_TYPE_PRIVATE_DATA_1
-      if (PRIVATE_DATA(cc))
+    case OP_CLASS:
+    case OP_NCLASS:
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+    case OP_XCLASS:
+    size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
+#else
+    size = 1 + 32 / (int)sizeof(pcre_uchar);
+#endif
+    if (PRIVATE_DATA(cc))
+      switch(get_class_iterator_size(cc + size))
         {
+        case 1:
         count = 1;
         srcw[0] = PRIVATE_DATA(cc);
-        }
-      cc += 1;
-      break;
+        break;
 
-      CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
-      if (PRIVATE_DATA(cc))
-        {
+        case 2:
         count = 2;
         srcw[0] = PRIVATE_DATA(cc);
         srcw[1] = srcw[0] + sizeof(sljit_sw);
-        }
-      cc += 1;
-      break;
+        break;
 
-      CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
-      if (PRIVATE_DATA(cc))
-        {
-        count = 2;
-        srcw[0] = PRIVATE_DATA(cc);
-        srcw[1] = srcw[0] + sizeof(sljit_sw);
+        default:
+        SLJIT_UNREACHABLE();
+        break;
         }
-      cc += 1 + IMM2_SIZE;
-      break;
-
-      case OP_CLASS:
-      case OP_NCLASS:
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
-      case OP_XCLASS:
-      size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
-#else
-      size = 1 + 32 / (int)sizeof(pcre_uchar);
-#endif
-      if (PRIVATE_DATA(cc))
-        switch(get_class_iterator_size(cc + size))
-          {
-          case 1:
-          count = 1;
-          srcw[0] = PRIVATE_DATA(cc);
-          break;
-
-          case 2:
-          count = 2;
-          srcw[0] = PRIVATE_DATA(cc);
-          srcw[1] = srcw[0] + sizeof(sljit_sw);
-          break;
-
-          default:
-          SLJIT_ASSERT_STOP();
-          break;
-          }
-      cc += size;
-      break;
-
-      default:
-      cc = next_opcode(common, cc);
-      SLJIT_ASSERT(cc != NULL);
-      break;
-      }
+    cc += size;
     break;
 
-    case end:
-    SLJIT_ASSERT_STOP();
+    default:
+    cc = next_opcode(common, cc);
+    SLJIT_ASSERT(cc != NULL);
     break;
     }
 
@@ -1990,7 +2189,7 @@ if (save)
 SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
 }
 
-static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, pcre_uint8 *current_offset)
+static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, sljit_u8 *current_offset)
 {
 pcre_uchar *end = bracketend(cc);
 BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT;
@@ -2104,7 +2303,7 @@ static SLJIT_INLINE void count_match(compiler_common *common)
 {
 DEFINE_COMPILER;
 
-OP2(SLJIT_SUB | SLJIT_SET_E, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);
+OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);
 add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO));
 }
 
@@ -2113,7 +2312,8 @@ static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
 /* May destroy all locals and registers except TMP2. */
 DEFINE_COMPILER;
 
-OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
+SLJIT_ASSERT(size > 0);
+OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
 #ifdef DESTROY_REGISTERS
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
 OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
@@ -2121,13 +2321,15 @@ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP1, 0);
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0);
 #endif
-add_stub(common, CMP(SLJIT_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
+add_stub(common, CMP(SLJIT_LESS, STACK_TOP, 0, STACK_LIMIT, 0));
 }
 
 static SLJIT_INLINE void free_stack(compiler_common *common, int size)
 {
 DEFINE_COMPILER;
-OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
+
+SLJIT_ASSERT(size > 0);
+OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
 }
 
 static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size)
@@ -2185,11 +2387,23 @@ else
   OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
   loop = LABEL();
   OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
   JUMPTO(SLJIT_NOT_ZERO, loop);
   }
 }
 
+static SLJIT_INLINE void reset_fast_fail(compiler_common *common)
+{
+DEFINE_COMPILER;
+sljit_s32 i;
+
+SLJIT_ASSERT(common->fast_fail_start_ptr < common->fast_fail_end_ptr);
+
+OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+for (i = common->fast_fail_start_ptr; i < common->fast_fail_end_ptr; i += sizeof(sljit_sw))
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, TMP1, 0);
+}
+
 static SLJIT_INLINE void do_reset_match(compiler_common *common, int length)
 {
 DEFINE_COMPILER;
@@ -2211,7 +2425,7 @@ else
   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
   loop = LABEL();
   OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
-  OP2(SLJIT_SUB | SLJIT_SET_E, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
   JUMPTO(SLJIT_NOT_ZERO, loop);
   }
 
@@ -2229,22 +2443,22 @@ static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *s
 {
 while (current != NULL)
   {
-  switch (current[-2])
+  switch (current[1])
     {
     case type_then_trap:
     break;
 
     case type_mark:
-    if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0)
-      return current[-4];
+    if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[2]) == 0)
+      return current[3];
     break;
 
     default:
-    SLJIT_ASSERT_STOP();
+    SLJIT_UNREACHABLE();
     break;
     }
-  SLJIT_ASSERT(current > (sljit_sw*)current[-1]);
-  current = (sljit_sw*)current[-1];
+  SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]);
+  current = (sljit_sw*)current[0];
   }
 return -1;
 }
@@ -2262,7 +2476,7 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0);
 OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
 if (common->mark_ptr != 0)
   OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
-OP1(SLJIT_MOV_SI, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offset_count));
+OP1(SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offset_count));
 if (common->mark_ptr != 0)
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);
 OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
@@ -2277,8 +2491,8 @@ OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));
 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
 OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
 #endif
-OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_R2), sizeof(int), SLJIT_S1, 0);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
+OP1(SLJIT_MOVU_S32, SLJIT_MEM1(SLJIT_R2), sizeof(int), SLJIT_S1, 0);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
 JUMPTO(SLJIT_NOT_ZERO, loop);
 JUMPHERE(early_quit);
 
@@ -2310,7 +2524,7 @@ SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0
 
 OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0);
 OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL);
-OP1(SLJIT_MOV_SI, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, real_offset_count));
+OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, real_offset_count));
 CMPTO(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 2, quit);
 
 /* Store match begin and end. */
@@ -2322,7 +2536,7 @@ OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HA
 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
 OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);
 #endif
-OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(int), SLJIT_R2, 0);
+OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(int), SLJIT_R2, 0);
 JUMPHERE(jump);
 
 OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start);
@@ -2330,13 +2544,13 @@ OP2(SLJIT_SUB, SLJIT_S1, 0, STR_END, 0, SLJIT_S0, 0);
 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
 OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
 #endif
-OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_R1), sizeof(int), SLJIT_S1, 0);
+OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), sizeof(int), SLJIT_S1, 0);
 
 OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S0, 0);
 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
 OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);
 #endif
-OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
+OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
 
 JUMPTO(SLJIT_JUMP, quit);
 }
@@ -2573,7 +2787,7 @@ else
 JUMPHERE(jump);
 }
 
-static void peek_char(compiler_common *common, pcre_uint32 max)
+static void peek_char(compiler_common *common, sljit_u32 max)
 {
 /* Reads the character into TMP1, keeps STR_PTR.
 Does not check STR_END. TMP2 Destroyed. */
@@ -2618,12 +2832,12 @@ if (common->utf)
 
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
 
-static BOOL is_char7_bitset(const pcre_uint8 *bitset, BOOL nclass)
+static BOOL is_char7_bitset(const sljit_u8 *bitset, BOOL nclass)
 {
 /* Tells whether the character codes below 128 are enough
 to determine a match. */
-const pcre_uint8 value = nclass ? 0xff : 0;
-const pcre_uint8 *end = bitset + 32;
+const sljit_u8 value = nclass ? 0xff : 0;
+const sljit_u8 *end = bitset + 32;
 
 bitset += 16;
 do
@@ -2648,12 +2862,12 @@ SLJIT_ASSERT(common->utf);
 OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
 
-OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
 
 if (full_read)
   {
   jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
-  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
   JUMPHERE(jump);
   }
@@ -2661,7 +2875,7 @@ if (full_read)
 
 #endif /* SUPPORT_UTF && COMPILE_PCRE8 */
 
-static void read_char_range(compiler_common *common, pcre_uint32 min, pcre_uint32 max, BOOL update_str_ptr)
+static void read_char_range(compiler_common *common, sljit_u32 min, sljit_u32 max, BOOL update_str_ptr)
 {
 /* Reads the precise value of a character into TMP1, if the character is
 between min and max (c >= min && c <= max). Otherwise it returns with a value
@@ -2692,7 +2906,7 @@ if (common->utf)
     {
     OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0);
     if (update_str_ptr)
-      OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+      OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
     jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x7);
     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
@@ -2716,7 +2930,7 @@ if (common->utf)
     {
     OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0);
     if (update_str_ptr)
-      OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+      OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
     jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xf);
     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
@@ -2736,7 +2950,7 @@ if (common->utf)
     add_jump(compiler, (max < 0x10000) ? &common->utfreadchar16 : &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
   else if (max < 128)
     {
-    OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+    OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
     }
   else
@@ -2745,7 +2959,7 @@ if (common->utf)
     if (!update_str_ptr)
       OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
     else
-      OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+      OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
@@ -2815,7 +3029,7 @@ if (common->utf)
   {
   /* This can be an extra read in some situations, but hopefully
   it is needed in most cases. */
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+  OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
   jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
   if (!update_str_ptr)
     {
@@ -2827,7 +3041,7 @@ if (common->utf)
     OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
     jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);
-    OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+    OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
     JUMPHERE(jump2);
     }
   else
@@ -2842,7 +3056,7 @@ if (common->utf)
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
 jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);
 #endif
-OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
 #if !defined COMPILE_PCRE8
 JUMPHERE(jump);
 #endif
@@ -2883,8 +3097,8 @@ if (common->utf)
   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
   /* Skip low surrogate if necessary. */
   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
-  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
+  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
   OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
   return;
@@ -2903,6 +3117,7 @@ struct sljit_jump *jump;
 if (nltype == NLTYPE_ANY)
   {
   add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
+  sljit_set_current_flags(compiler, SLJIT_SET_Z);
   add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_NOT_ZERO : SLJIT_ZERO));
   }
 else if (nltype == NLTYPE_ANYCRLF)
@@ -2944,7 +3159,7 @@ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
 
 /* Searching for the first zero. */
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
 jump = JUMP(SLJIT_NOT_ZERO);
 /* Two byte sequence. */
 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
@@ -2958,7 +3173,7 @@ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
 
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
 jump = JUMP(SLJIT_NOT_ZERO);
 /* Three byte sequence. */
 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
@@ -2992,15 +3207,15 @@ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
 
 /* Searching for the first zero. */
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
 jump = JUMP(SLJIT_NOT_ZERO);
 /* Two byte sequence. */
 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
 
 JUMPHERE(jump);
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_NOT_ZERO);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO);
 /* This code runs only in 8 bit mode. No need to shift the value. */
 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
 OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
@@ -3023,7 +3238,7 @@ struct sljit_jump *compare;
 
 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 
-OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
 jump = JUMP(SLJIT_NOT_ZERO);
 /* Two byte sequence. */
 OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
@@ -3034,7 +3249,7 @@ compare = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x3);
 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
 OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
-OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
 
 JUMPHERE(compare);
@@ -3043,7 +3258,7 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
 
 /* We only have types for characters less than 256. */
 JUMPHERE(jump);
-OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
@@ -3064,31 +3279,51 @@ static void do_getucd(compiler_common *common)
 /* Search the UCD record for the character comes in TMP1.
 Returns chartype in TMP1 and UCD offset in TMP2. */
 DEFINE_COMPILER;
+#ifdef COMPILE_PCRE32
+struct sljit_jump *jump;
+#endif
+
+#if defined SLJIT_DEBUG && SLJIT_DEBUG
+/* dummy_ucd_record */
+const ucd_record *record = GET_UCD(INVALID_UTF_CHAR);
+SLJIT_ASSERT(record->script == ucp_Common && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther);
+SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0);
+#endif
 
 SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
 
 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+#ifdef COMPILE_PCRE32
+if (!common->utf)
+  {
+  jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10ffff + 1);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+  JUMPHERE(jump);
+  }
+#endif
+
 OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
-OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
+OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
-OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
-OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
 }
 #endif
 
-static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline)
+static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf)
 {
 DEFINE_COMPILER;
 struct sljit_label *mainloop;
 struct sljit_label *newlinelabel = NULL;
 struct sljit_jump *start;
 struct sljit_jump *end = NULL;
-struct sljit_jump *nl = NULL;
+struct sljit_jump *end2 = NULL;
 #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
 struct sljit_jump *singlechar;
 #endif
@@ -3096,14 +3331,13 @@ jump_list *newline = NULL;
 BOOL newlinecheck = FALSE;
 BOOL readuchar = FALSE;
 
-if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY ||
-    common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
+if (!(hascrorlf || (common->match_end_ptr != 0)) &&
+    (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
   newlinecheck = TRUE;
 
-if (firstline)
+if (common->match_end_ptr != 0)
   {
   /* Search for the end of the first line. */
-  SLJIT_ASSERT(common->first_line_end != 0);
   OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
 
   if (common->nltype == NLTYPE_FIXED && common->newline > 255)
@@ -3116,19 +3350,19 @@ if (firstline)
     CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
     CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
     JUMPHERE(end);
-    OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+    OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
     }
   else
     {
     end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
     mainloop = LABEL();
     /* Continual stores does not cause data dependency. */
-    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->first_line_end, STR_PTR, 0);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);
     read_char_range(common, common->nlmin, common->nlmax, TRUE);
     check_newlinechar(common, common->nltype, &newline, TRUE);
     CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, mainloop);
     JUMPHERE(end);
-    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->first_line_end, STR_PTR, 0);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);
     set_jumps(newline, LABEL());
     }
 
@@ -3143,13 +3377,13 @@ if (newlinecheck)
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
   end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
-  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
+  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
 #endif
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-  nl = JUMP(SLJIT_JUMP);
+  end2 = JUMP(SLJIT_JUMP);
   }
 
 mainloop = LABEL();
@@ -3172,7 +3406,7 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
 if (common->utf)
   {
   singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+  OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
   JUMPHERE(singlechar);
   }
@@ -3181,8 +3415,8 @@ if (common->utf)
   {
   singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
-  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
   JUMPHERE(singlechar);
@@ -3194,51 +3428,52 @@ JUMPHERE(start);
 if (newlinecheck)
   {
   JUMPHERE(end);
-  JUMPHERE(nl);
+  JUMPHERE(end2);
   }
 
 return mainloop;
 }
 
 #define MAX_N_CHARS 16
-#define MAX_N_BYTES 8
+#define MAX_DIFF_CHARS 6
 
-static SLJIT_INLINE void add_prefix_byte(pcre_uint8 byte, pcre_uint8 *bytes)
+static SLJIT_INLINE void add_prefix_char(pcre_uchar chr, pcre_uchar *chars)
 {
-pcre_uint8 len = bytes[0];
-int i;
+pcre_uchar i, len;
 
+len = chars[0];
 if (len == 255)
   return;
 
 if (len == 0)
   {
-  bytes[0] = 1;
-  bytes[1] = byte;
+  chars[0] = 1;
+  chars[1] = chr;
   return;
   }
 
 for (i = len; i > 0; i--)
-  if (bytes[i] == byte)
+  if (chars[i] == chr)
     return;
 
-if (len >= MAX_N_BYTES - 1)
+if (len >= MAX_DIFF_CHARS - 1)
   {
-  bytes[0] = 255;
+  chars[0] = 255;
   return;
   }
 
 len++;
-bytes[len] = byte;
-bytes[0] = len;
+chars[len] = chr;
+chars[0] = len;
 }
 
-static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars, pcre_uint32 *rec_count)
+static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uchar *chars, int max_chars, sljit_u32 *rec_count)
 {
 /* Recursive function, which scans prefix literals. */
-BOOL last, any, caseless;
+BOOL last, any, class, caseless;
 int len, repeat, len_save, consumed = 0;
-pcre_uint32 chr, mask;
+sljit_u32 chr; /* Any unicode character. */
+sljit_u8 *bytes, *bytes_end, byte;
 pcre_uchar *alternative, *cc_save, *oc;
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
 pcre_uchar othercase[8];
@@ -3257,6 +3492,7 @@ while (TRUE)
 
   last = TRUE;
   any = FALSE;
+  class = FALSE;
   caseless = FALSE;
 
   switch (*cc)
@@ -3320,7 +3556,7 @@ while (TRUE)
 #ifdef SUPPORT_UTF
     if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
 #endif
-    max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars, rec_count);
+    max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count);
     if (max_chars == 0)
       return consumed;
     last = FALSE;
@@ -3343,7 +3579,7 @@ while (TRUE)
     alternative = cc + GET(cc, 1);
     while (*alternative == OP_ALT)
       {
-      max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars, rec_count);
+      max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, max_chars, rec_count);
       if (max_chars == 0)
         return consumed;
       alternative += GET(alternative, 1);
@@ -3356,18 +3592,17 @@ while (TRUE)
 
     case OP_CLASS:
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
-    if (common->utf && !is_char7_bitset((const pcre_uint8 *)(cc + 1), FALSE)) return consumed;
+    if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE))
+      return consumed;
 #endif
-    any = TRUE;
-    cc += 1 + 32 / sizeof(pcre_uchar);
+    class = TRUE;
     break;
 
     case OP_NCLASS:
 #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
     if (common->utf) return consumed;
 #endif
-    any = TRUE;
-    cc += 1 + 32 / sizeof(pcre_uchar);
+    class = TRUE;
     break;
 
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
@@ -3382,7 +3617,7 @@ while (TRUE)
 
     case OP_DIGIT:
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
-    if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_digit, FALSE))
+    if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE))
       return consumed;
 #endif
     any = TRUE;
@@ -3391,7 +3626,7 @@ while (TRUE)
 
     case OP_WHITESPACE:
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
-    if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_space, FALSE))
+    if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE))
       return consumed;
 #endif
     any = TRUE;
@@ -3400,7 +3635,7 @@ while (TRUE)
 
     case OP_WORDCHAR:
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
-    if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_word, FALSE))
+    if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE))
       return consumed;
 #endif
     any = TRUE;
@@ -3423,10 +3658,10 @@ while (TRUE)
     cc++;
     break;
 
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UTF
     case OP_NOTPROP:
     case OP_PROP:
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#ifndef COMPILE_PCRE32
     if (common->utf) return consumed;
 #endif
     any = TRUE;
@@ -3455,30 +3690,114 @@ while (TRUE)
 
   if (any)
     {
-#if defined COMPILE_PCRE8
-    mask = 0xff;
-#elif defined COMPILE_PCRE16
-    mask = 0xffff;
-#elif defined COMPILE_PCRE32
-    mask = 0xffffffff;
-#else
-    SLJIT_ASSERT_STOP();
-#endif
+    do
+      {
+      chars[0] = 255;
+
+      consumed++;
+      if (--max_chars == 0)
+        return consumed;
+      chars += MAX_DIFF_CHARS;
+      }
+    while (--repeat > 0);
+
+    repeat = 1;
+    continue;
+    }
+
+  if (class)
+    {
+    bytes = (sljit_u8*) (cc + 1);
+    cc += 1 + 32 / sizeof(pcre_uchar);
+
+    switch (*cc)
+      {
+      case OP_CRSTAR:
+      case OP_CRMINSTAR:
+      case OP_CRPOSSTAR:
+      case OP_CRQUERY:
+      case OP_CRMINQUERY:
+      case OP_CRPOSQUERY:
+      max_chars = scan_prefix(common, cc + 1, chars, max_chars, rec_count);
+      if (max_chars == 0)
+        return consumed;
+      break;
+
+      default:
+      case OP_CRPLUS:
+      case OP_CRMINPLUS:
+      case OP_CRPOSPLUS:
+      break;
+
+      case OP_CRRANGE:
+      case OP_CRMINRANGE:
+      case OP_CRPOSRANGE:
+      repeat = GET2(cc, 1);
+      if (repeat <= 0)
+        return consumed;
+      break;
+      }
 
     do
       {
-      chars[0] = mask;
-      chars[1] = mask;
-      bytes[0] = 255;
+      if (bytes[31] & 0x80)
+        chars[0] = 255;
+      else if (chars[0] != 255)
+        {
+        bytes_end = bytes + 32;
+        chr = 0;
+        do
+          {
+          byte = *bytes++;
+          SLJIT_ASSERT((chr & 0x7) == 0);
+          if (byte == 0)
+            chr += 8;
+          else
+            {
+            do
+              {
+              if ((byte & 0x1) != 0)
+                add_prefix_char(chr, chars);
+              byte >>= 1;
+              chr++;
+              }
+            while (byte != 0);
+            chr = (chr + 7) & ~7;
+            }
+          }
+        while (chars[0] != 255 && bytes < bytes_end);
+        bytes = bytes_end - 32;
+        }
 
       consumed++;
       if (--max_chars == 0)
         return consumed;
-      chars += 2;
-      bytes += MAX_N_BYTES;
+      chars += MAX_DIFF_CHARS;
       }
     while (--repeat > 0);
 
+    switch (*cc)
+      {
+      case OP_CRSTAR:
+      case OP_CRMINSTAR:
+      case OP_CRPOSSTAR:
+      return consumed;
+
+      case OP_CRQUERY:
+      case OP_CRMINQUERY:
+      case OP_CRPOSQUERY:
+      cc++;
+      break;
+
+      case OP_CRRANGE:
+      case OP_CRMINRANGE:
+      case OP_CRPOSRANGE:
+      if (GET2(cc, 1) != GET2(cc, 1 + IMM2_SIZE))
+        return consumed;
+      cc += 1 + 2 * IMM2_SIZE;
+      break;
+      }
+
     repeat = 1;
     continue;
     }
@@ -3505,7 +3824,10 @@ while (TRUE)
       }
     }
   else
+    {
     caseless = FALSE;
+    othercase[0] = 0; /* Stops compiler warning - PH */
+    }
 
   len_save = len;
   cc_save = cc;
@@ -3515,43 +3837,16 @@ while (TRUE)
     do
       {
       chr = *cc;
-#ifdef COMPILE_PCRE32
-      if (SLJIT_UNLIKELY(chr == NOTACHAR))
-        return consumed;
-#endif
-      add_prefix_byte((pcre_uint8)chr, bytes);
+      add_prefix_char(*cc, chars);
 
-      mask = 0;
       if (caseless)
-        {
-        add_prefix_byte((pcre_uint8)*oc, bytes);
-        mask = *cc ^ *oc;
-        chr |= mask;
-        }
-
-#ifdef COMPILE_PCRE32
-      if (chars[0] == NOTACHAR && chars[1] == 0)
-#else
-      if (chars[0] == NOTACHAR)
-#endif
-        {
-        chars[0] = chr;
-        chars[1] = mask;
-        }
-      else
-        {
-        mask |= chars[0] ^ chr;
-        chr |= mask;
-        chars[0] = chr;
-        chars[1] |= mask;
-        }
+        add_prefix_char(*oc, chars);
 
       len--;
       consumed++;
       if (--max_chars == 0)
         return consumed;
-      chars += 2;
-      bytes += MAX_N_BYTES;
+      chars += MAX_DIFF_CHARS;
       cc++;
       oc++;
       }
@@ -3570,163 +3865,568 @@ while (TRUE)
   }
 }
 
-static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common, BOOL firstline)
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
+
+static sljit_s32 character_to_int32(pcre_uchar chr)
+{
+sljit_s32 value = (sljit_s32)chr;
+#if defined COMPILE_PCRE8
+#define SSE2_COMPARE_TYPE_INDEX 0
+return (value << 24) | (value << 16) | (value << 8) | value;
+#elif defined COMPILE_PCRE16
+#define SSE2_COMPARE_TYPE_INDEX 1
+return (value << 16) | value;
+#elif defined COMPILE_PCRE32
+#define SSE2_COMPARE_TYPE_INDEX 2
+return value;
+#else
+#error "Unsupported unit width"
+#endif
+}
+
+static SLJIT_INLINE void fast_forward_first_char2_sse2(compiler_common *common, pcre_uchar char1, pcre_uchar char2)
 {
 DEFINE_COMPILER;
 struct sljit_label *start;
-struct sljit_jump *quit;
-pcre_uint32 chars[MAX_N_CHARS * 2];
-pcre_uint8 bytes[MAX_N_CHARS * MAX_N_BYTES];
-pcre_uint8 ones[MAX_N_CHARS];
-int offsets[3];
-pcre_uint32 mask;
-pcre_uint8 *byte_set, *byte_set_end;
-int i, max, from;
-int range_right = -1, range_len = 3 - 1;
-sljit_ub *update_table = NULL;
-BOOL in_range;
-pcre_uint32 rec_count;
+struct sljit_jump *quit[3];
+struct sljit_jump *nomatch;
+sljit_u8 instruction[8];
+sljit_s32 tmp1_ind = sljit_get_register_index(TMP1);
+sljit_s32 tmp2_ind = sljit_get_register_index(TMP2);
+sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR);
+BOOL load_twice = FALSE;
+pcre_uchar bit;
+
+bit = char1 ^ char2;
+if (!is_powerof2(bit))
+  bit = 0;
 
-for (i = 0; i < MAX_N_CHARS; i++)
+if ((char1 != char2) && bit == 0)
+  load_twice = TRUE;
+
+quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+
+/* First part (unaligned start) */
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
+
+SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1);
+
+/* MOVD xmm, r/m32 */
+instruction[0] = 0x66;
+instruction[1] = 0x0f;
+instruction[2] = 0x6e;
+instruction[3] = 0xc0 | (2 << 3) | tmp1_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (char1 != char2)
   {
-  chars[i << 1] = NOTACHAR;
-  chars[(i << 1) + 1] = 0;
-  bytes[i * MAX_N_BYTES] = 0;
-  }
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
 
-rec_count = 10000;
-max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS, &rec_count);
+  /* MOVD xmm, r/m32 */
+  instruction[3] = 0xc0 | (3 << 3) | tmp1_ind;
+  sljit_emit_op_custom(compiler, instruction, 4);
+  }
 
-if (max <= 1)
-  return FALSE;
+/* PSHUFD xmm1, xmm2/m128, imm8 */
+instruction[2] = 0x70;
+instruction[3] = 0xc0 | (2 << 3) | 2;
+instruction[4] = 0;
+sljit_emit_op_custom(compiler, instruction, 5);
 
-for (i = 0; i < max; i++)
+if (char1 != char2)
   {
-  mask = chars[(i << 1) + 1];
-  ones[i] = ones_in_half_byte[mask & 0xf];
-  mask >>= 4;
-  while (mask != 0)
-    {
-    ones[i] += ones_in_half_byte[mask & 0xf];
-    mask >>= 4;
-    }
+  /* PSHUFD xmm1, xmm2/m128, imm8 */
+  instruction[3] = 0xc0 | (3 << 3) | 3;
+  instruction[4] = 0;
+  sljit_emit_op_custom(compiler, instruction, 5);
   }
 
-in_range = FALSE;
-from = 0;   /* Prevent compiler "uninitialized" warning */
-for (i = 0; i <= max; i++)
+OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 0xf);
+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
+
+/* MOVDQA xmm1, xmm2/m128 */
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+
+if (str_ptr_ind < 8)
   {
-  if (in_range && (i - from) > range_len && (bytes[(i - 1) * MAX_N_BYTES] <= 4))
-    {
-    range_len = i - from;
-    range_right = i - 1;
-    }
+  instruction[2] = 0x6f;
+  instruction[3] = (0 << 3) | str_ptr_ind;
+  sljit_emit_op_custom(compiler, instruction, 4);
 
-  if (i < max && bytes[i * MAX_N_BYTES] < 255)
+  if (load_twice)
     {
-    if (!in_range)
-      {
-      in_range = TRUE;
-      from = i;
-      }
+    instruction[3] = (1 << 3) | str_ptr_ind;
+    sljit_emit_op_custom(compiler, instruction, 4);
     }
-  else if (in_range)
-    in_range = FALSE;
   }
-
-if (range_right >= 0)
+else
   {
-  update_table = (sljit_ub *)allocate_read_only_data(common, 256);
-  if (update_table == NULL)
-    return TRUE;
-  memset(update_table, IN_UCHARS(range_len), 256);
+  instruction[1] = 0x41;
+  instruction[2] = 0x0f;
+  instruction[3] = 0x6f;
+  instruction[4] = (0 << 3) | (str_ptr_ind & 0x7);
+  sljit_emit_op_custom(compiler, instruction, 5);
 
-  for (i = 0; i < range_len; i++)
+  if (load_twice)
     {
-    byte_set = bytes + ((range_right - i) * MAX_N_BYTES);
-    SLJIT_ASSERT(byte_set[0] > 0 && byte_set[0] < 255);
-    byte_set_end = byte_set + byte_set[0];
-    byte_set++;
-    while (byte_set <= byte_set_end)
-      {
-      if (update_table[*byte_set] > IN_UCHARS(i))
-        update_table[*byte_set] = IN_UCHARS(i);
-      byte_set++;
-      }
+    instruction[4] = (1 << 3) | str_ptr_ind;
+    sljit_emit_op_custom(compiler, instruction, 5);
     }
+  instruction[1] = 0x0f;
   }
 
-offsets[0] = -1;
-/* Scan forward. */
-for (i = 0; i < max; i++)
-  if (ones[i] <= 2) {
-    offsets[0] = i;
-    break;
+#else
+
+instruction[2] = 0x6f;
+instruction[3] = (0 << 3) | str_ptr_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (load_twice)
+  {
+  instruction[3] = (1 << 3) | str_ptr_ind;
+  sljit_emit_op_custom(compiler, instruction, 4);
   }
 
-if (offsets[0] < 0 && range_right < 0)
-  return FALSE;
+#endif
 
-if (offsets[0] >= 0)
+if (bit != 0)
   {
-  /* Scan backward. */
-  offsets[1] = -1;
-  for (i = max - 1; i > offsets[0]; i--)
-    if (ones[i] <= 2 && i != range_right)
-      {
-      offsets[1] = i;
-      break;
-      }
+  /* POR xmm1, xmm2/m128 */
+  instruction[2] = 0xeb;
+  instruction[3] = 0xc0 | (0 << 3) | 3;
+  sljit_emit_op_custom(compiler, instruction, 4);
+  }
 
-  /* This case is handled better by fast_forward_first_char. */
-  if (offsets[1] == -1 && offsets[0] == 0 && range_right < 0)
-    return FALSE;
+/* PCMPEQB/W/D xmm1, xmm2/m128 */
+instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
+instruction[3] = 0xc0 | (0 << 3) | 2;
+sljit_emit_op_custom(compiler, instruction, 4);
 
-  offsets[2] = -1;
-  /* We only search for a middle character if there is no range check. */
-  if (offsets[1] >= 0 && range_right == -1)
-    {
-    /* Scan from middle. */
-    for (i = (offsets[0] + offsets[1]) / 2 + 1; i < offsets[1]; i++)
-      if (ones[i] <= 2)
-        {
-        offsets[2] = i;
-        break;
-        }
+if (load_twice)
+  {
+  instruction[3] = 0xc0 | (1 << 3) | 3;
+  sljit_emit_op_custom(compiler, instruction, 4);
+  }
 
-    if (offsets[2] == -1)
-      {
-      for (i = (offsets[0] + offsets[1]) / 2; i > offsets[0]; i--)
-        if (ones[i] <= 2)
-          {
-          offsets[2] = i;
-          break;
-          }
-      }
-    }
+/* PMOVMSKB reg, xmm */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
+sljit_emit_op_custom(compiler, instruction, 4);
 
-  SLJIT_ASSERT(offsets[1] == -1 || (offsets[0] < offsets[1]));
-  SLJIT_ASSERT(offsets[2] == -1 || (offsets[0] < offsets[2] && offsets[1] > offsets[2]));
+if (load_twice)
+  {
+  OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0);
+  instruction[3] = 0xc0 | (tmp2_ind << 3) | 1;
+  sljit_emit_op_custom(compiler, instruction, 4);
 
-  chars[0] = chars[offsets[0] << 1];
-  chars[1] = chars[(offsets[0] << 1) + 1];
-  if (offsets[2] >= 0)
+  OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+  OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0);
+  }
+
+OP2(SLJIT_ASHR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+/* BSF r32, r/m32 */
+instruction[0] = 0x0f;
+instruction[1] = 0xbc;
+instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
+sljit_emit_op_custom(compiler, instruction, 3);
+sljit_set_current_flags(compiler, SLJIT_SET_Z);
+
+nomatch = JUMP(SLJIT_ZERO);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+quit[1] = JUMP(SLJIT_JUMP);
+
+JUMPHERE(nomatch);
+
+start = LABEL();
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
+quit[2] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+
+/* Second part (aligned) */
+
+instruction[0] = 0x66;
+instruction[1] = 0x0f;
+
+/* MOVDQA xmm1, xmm2/m128 */
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+
+if (str_ptr_ind < 8)
+  {
+  instruction[2] = 0x6f;
+  instruction[3] = (0 << 3) | str_ptr_ind;
+  sljit_emit_op_custom(compiler, instruction, 4);
+
+  if (load_twice)
+    {
+    instruction[3] = (1 << 3) | str_ptr_ind;
+    sljit_emit_op_custom(compiler, instruction, 4);
+    }
+  }
+else
+  {
+  instruction[1] = 0x41;
+  instruction[2] = 0x0f;
+  instruction[3] = 0x6f;
+  instruction[4] = (0 << 3) | (str_ptr_ind & 0x7);
+  sljit_emit_op_custom(compiler, instruction, 5);
+
+  if (load_twice)
+    {
+    instruction[4] = (1 << 3) | str_ptr_ind;
+    sljit_emit_op_custom(compiler, instruction, 5);
+    }
+  instruction[1] = 0x0f;
+  }
+
+#else
+
+instruction[2] = 0x6f;
+instruction[3] = (0 << 3) | str_ptr_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (load_twice)
+  {
+  instruction[3] = (1 << 3) | str_ptr_ind;
+  sljit_emit_op_custom(compiler, instruction, 4);
+  }
+
+#endif
+
+if (bit != 0)
+  {
+  /* POR xmm1, xmm2/m128 */
+  instruction[2] = 0xeb;
+  instruction[3] = 0xc0 | (0 << 3) | 3;
+  sljit_emit_op_custom(compiler, instruction, 4);
+  }
+
+/* PCMPEQB/W/D xmm1, xmm2/m128 */
+instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
+instruction[3] = 0xc0 | (0 << 3) | 2;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (load_twice)
+  {
+  instruction[3] = 0xc0 | (1 << 3) | 3;
+  sljit_emit_op_custom(compiler, instruction, 4);
+  }
+
+/* PMOVMSKB reg, xmm */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (load_twice)
+  {
+  instruction[3] = 0xc0 | (tmp2_ind << 3) | 1;
+  sljit_emit_op_custom(compiler, instruction, 4);
+
+  OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+  }
+
+/* BSF r32, r/m32 */
+instruction[0] = 0x0f;
+instruction[1] = 0xbc;
+instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
+sljit_emit_op_custom(compiler, instruction, 3);
+sljit_set_current_flags(compiler, SLJIT_SET_Z);
+
+JUMPTO(SLJIT_ZERO, start);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+
+start = LABEL();
+SET_LABEL(quit[0], start);
+SET_LABEL(quit[1], start);
+SET_LABEL(quit[2], start);
+}
+
+#undef SSE2_COMPARE_TYPE_INDEX
+
+#endif
+
+static void fast_forward_first_char2(compiler_common *common, pcre_uchar char1, pcre_uchar char2, sljit_s32 offset)
+{
+DEFINE_COMPILER;
+struct sljit_label *start;
+struct sljit_jump *quit;
+struct sljit_jump *found;
+pcre_uchar mask;
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+struct sljit_label *utf_start = NULL;
+struct sljit_jump *utf_quit = NULL;
+#endif
+BOOL has_match_end = (common->match_end_ptr != 0);
+
+if (offset > 0)
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
+
+if (has_match_end)
+  {
+  OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
+
+  OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, SLJIT_IMM, IN_UCHARS(offset + 1));
+  OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0);
+  sljit_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0);
+  }
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+if (common->utf && offset > 0)
+  utf_start = LABEL();
+#endif
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
+
+/* SSE2 accelerated first character search. */
+
+if (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
+  {
+  fast_forward_first_char2_sse2(common, char1, char2);
+
+  SLJIT_ASSERT(common->mode == JIT_COMPILE || offset == 0);
+  if (common->mode == JIT_COMPILE)
+    {
+    /* In complete mode, we don't need to run a match when STR_PTR == STR_END. */
+    SLJIT_ASSERT(common->forced_quit_label == NULL);
+    OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
+    add_jump(compiler, &common->forced_quit, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+    if (common->utf && offset > 0)
+      {
+      SLJIT_ASSERT(common->mode == JIT_COMPILE);
+
+      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
+      OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+#if defined COMPILE_PCRE8
+      OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
+      CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start);
+#elif defined COMPILE_PCRE16
+      OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
+      CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start);
+#else
+#error "Unknown code width"
+#endif
+      OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+      }
+#endif
+
+    if (offset > 0)
+      OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
+    }
+  else
+    {
+    OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+    if (has_match_end)
+      {
+      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+      sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, TMP1, 0);
+      }
+    else
+      sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, STR_END, 0);
+    }
+
+  if (has_match_end)
+    OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+  return;
+  }
+
+#endif
+
+quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+
+start = LABEL();
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+
+if (char1 == char2)
+  found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1);
+else
+  {
+  mask = char1 ^ char2;
+  if (is_powerof2(mask))
+    {
+    OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);
+    found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask);
+    }
+  else
+    {
+    OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char1);
+    OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char2);
+    OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
+    found = JUMP(SLJIT_NOT_ZERO);
+    }
+  }
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, start);
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+if (common->utf && offset > 0)
+  utf_quit = JUMP(SLJIT_JUMP);
+#endif
+
+JUMPHERE(found);
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+if (common->utf && offset > 0)
+  {
+  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+#if defined COMPILE_PCRE8
+  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
+  CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start);
+#elif defined COMPILE_PCRE16
+  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
+  CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start);
+#else
+#error "Unknown code width"
+#endif
+  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+  JUMPHERE(utf_quit);
+  }
+#endif
+
+JUMPHERE(quit);
+
+if (has_match_end)
+  {
+  quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+  if (offset > 0)
+    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
+  JUMPHERE(quit);
+  OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+  }
+
+if (offset > 0)
+  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
+}
+
+static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common)
+{
+DEFINE_COMPILER;
+struct sljit_label *start;
+struct sljit_jump *quit;
+struct sljit_jump *match;
+/* bytes[0] represent the number of characters between 0
+and MAX_N_BYTES - 1, 255 represents any character. */
+pcre_uchar chars[MAX_N_CHARS * MAX_DIFF_CHARS];
+sljit_s32 offset;
+pcre_uchar mask;
+pcre_uchar *char_set, *char_set_end;
+int i, max, from;
+int range_right = -1, range_len;
+sljit_u8 *update_table = NULL;
+BOOL in_range;
+sljit_u32 rec_count;
+
+for (i = 0; i < MAX_N_CHARS; i++)
+  chars[i * MAX_DIFF_CHARS] = 0;
+
+rec_count = 10000;
+max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count);
+
+if (max < 1)
+  return FALSE;
+
+in_range = FALSE;
+/* Prevent compiler "uninitialized" warning */
+from = 0;
+range_len = 4 /* minimum length */ - 1;
+for (i = 0; i <= max; i++)
+  {
+  if (in_range && (i - from) > range_len && (chars[(i - 1) * MAX_DIFF_CHARS] < 255))
     {
-    chars[2] = chars[offsets[2] << 1];
-    chars[3] = chars[(offsets[2] << 1) + 1];
+    range_len = i - from;
+    range_right = i - 1;
     }
-  if (offsets[1] >= 0)
+
+  if (i < max && chars[i * MAX_DIFF_CHARS] < 255)
     {
-    chars[4] = chars[offsets[1] << 1];
-    chars[5] = chars[(offsets[1] << 1) + 1];
+    SLJIT_ASSERT(chars[i * MAX_DIFF_CHARS] > 0);
+    if (!in_range)
+      {
+      in_range = TRUE;
+      from = i;
+      }
     }
+  else
+    in_range = FALSE;
   }
 
+if (range_right >= 0)
+  {
+  update_table = (sljit_u8 *)allocate_read_only_data(common, 256);
+  if (update_table == NULL)
+    return TRUE;
+  memset(update_table, IN_UCHARS(range_len), 256);
+
+  for (i = 0; i < range_len; i++)
+    {
+    char_set = chars + ((range_right - i) * MAX_DIFF_CHARS);
+    SLJIT_ASSERT(char_set[0] > 0 && char_set[0] < 255);
+    char_set_end = char_set + char_set[0];
+    char_set++;
+    while (char_set <= char_set_end)
+      {
+      if (update_table[(*char_set) & 0xff] > IN_UCHARS(i))
+        update_table[(*char_set) & 0xff] = IN_UCHARS(i);
+      char_set++;
+      }
+    }
+  }
+
+offset = -1;
+/* Scan forward. */
+for (i = 0; i < max; i++)
+  {
+  if (offset == -1)
+    {
+    if (chars[i * MAX_DIFF_CHARS] <= 2)
+      offset = i;
+    }
+  else if (chars[offset * MAX_DIFF_CHARS] == 2 && chars[i * MAX_DIFF_CHARS] <= 2)
+    {
+    if (chars[i * MAX_DIFF_CHARS] == 1)
+      offset = i;
+    else
+      {
+      mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2];
+      if (!is_powerof2(mask))
+        {
+        mask = chars[i * MAX_DIFF_CHARS + 1] ^ chars[i * MAX_DIFF_CHARS + 2];
+        if (is_powerof2(mask))
+          offset = i;
+        }
+      }
+    }
+  }
+
+if (range_right < 0)
+  {
+  if (offset < 0)
+    return FALSE;
+  SLJIT_ASSERT(chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2);
+  /* Works regardless the value is 1 or 2. */
+  mask = chars[offset * MAX_DIFF_CHARS + chars[offset * MAX_DIFF_CHARS]];
+  fast_forward_first_char2(common, chars[offset * MAX_DIFF_CHARS + 1], mask, offset);
+  return TRUE;
+  }
+
+if (range_right == offset)
+  offset = -1;
+
+SLJIT_ASSERT(offset == -1 || (chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2));
+
 max -= 1;
-if (firstline)
+SLJIT_ASSERT(max > 0);
+if (common->match_end_ptr != 0)
   {
-  SLJIT_ASSERT(common->first_line_end != 0);
-  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
   OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
   OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
   quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP1, 0);
@@ -3736,68 +4436,86 @@ if (firstline)
 else
   OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
 
+SLJIT_ASSERT(range_right >= 0);
+
 #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-if (range_right >= 0)
-  OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
+OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
 #endif
 
 start = LABEL();
 quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
 
-SLJIT_ASSERT(range_right >= 0 || offsets[0] >= 0);
-
-if (range_right >= 0)
-  {
 #if defined COMPILE_PCRE8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));
 #else
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);
 #endif
 
 #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);
 #else
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);
 #endif
-  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-  CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);
-  }
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);
 
-if (offsets[0] >= 0)
+if (offset >= 0)
   {
-  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[0]));
-  if (offsets[1] >= 0)
-    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[1]));
+  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offset));
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
 
-  if (chars[1] != 0)
-    OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[1]);
-  CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[0], start);
-  if (offsets[2] >= 0)
-    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[2] - 1));
-
-  if (offsets[1] >= 0)
+  if (chars[offset * MAX_DIFF_CHARS] == 1)
+    CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1], start);
+  else
     {
-    if (chars[5] != 0)
-      OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, chars[5]);
-    CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, chars[4], start);
+    mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2];
+    if (is_powerof2(mask))
+      {
+      OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);
+      CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1] | mask, start);
+      }
+    else
+      {
+      match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1]);
+      CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 2], start);
+      JUMPHERE(match);
+      }
     }
+  }
 
-  if (offsets[2] >= 0)
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+if (common->utf && offset != 0)
+  {
+  if (offset < 0)
     {
-    if (chars[3] != 0)
-      OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[3]);
-    CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[2], start);
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
     }
-  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+  else
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
+#if defined COMPILE_PCRE8
+  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
+  CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, start);
+#elif defined COMPILE_PCRE16
+  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
+  CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, start);
+#else
+#error "Unknown code width"
+#endif
+  if (offset < 0)
+    OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
   }
+#endif
+
+if (offset >= 0)
+  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
 
 JUMPHERE(quit);
 
-if (firstline)
+if (common->match_end_ptr != 0)
   {
   if (range_right >= 0)
-    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
   OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
   if (range_right >= 0)
     {
@@ -3812,66 +4530,26 @@ return TRUE;
 }
 
 #undef MAX_N_CHARS
-#undef MAX_N_BYTES
+#undef MAX_DIFF_CHARS
 
-static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline)
+static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless)
 {
-DEFINE_COMPILER;
-struct sljit_label *start;
-struct sljit_jump *quit;
-struct sljit_jump *found;
-pcre_uchar oc, bit;
-
-if (firstline)
-  {
-  SLJIT_ASSERT(common->first_line_end != 0);
-  OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
-  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);
-  }
-
-start = LABEL();
-quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
-OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+pcre_uchar oc;
 
 oc = first_char;
 if (caseless)
   {
   oc = TABLE_GET(first_char, common->fcc, first_char);
-#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+#if defined SUPPORT_UCP && !defined COMPILE_PCRE8
   if (first_char > 127 && common->utf)
     oc = UCD_OTHERCASE(first_char);
 #endif
   }
-if (first_char == oc)
-  found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, first_char);
-else
-  {
-  bit = first_char ^ oc;
-  if (is_powerof2(bit))
-    {
-    OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit);
-    found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit);
-    }
-  else
-    {
-    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char);
-    OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
-    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
-    OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
-    found = JUMP(SLJIT_NOT_ZERO);
-    }
-  }
 
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-JUMPTO(SLJIT_JUMP, start);
-JUMPHERE(found);
-JUMPHERE(quit);
-
-if (firstline)
-  OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+fast_forward_first_char2(common, first_char, oc, 0);
 }
 
-static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline)
+static SLJIT_INLINE void fast_forward_newline(compiler_common *common)
 {
 DEFINE_COMPILER;
 struct sljit_label *loop;
@@ -3882,11 +4560,10 @@ struct sljit_jump *foundcr = NULL;
 struct sljit_jump *notfoundnl;
 jump_list *newline = NULL;
 
-if (firstline)
+if (common->match_end_ptr != 0)
   {
-  SLJIT_ASSERT(common->first_line_end != 0);
   OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
-  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);
+  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
   }
 
 if (common->nltype == NLTYPE_FIXED && common->newline > 255)
@@ -3898,8 +4575,8 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
   firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
 
   OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
-  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
-  OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
+  OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL);
 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
   OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);
 #endif
@@ -3917,7 +4594,7 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
   JUMPHERE(firstchar);
   JUMPHERE(lastchar);
 
-  if (firstline)
+  if (common->match_end_ptr != 0)
     OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
   return;
   }
@@ -3943,8 +4620,8 @@ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
   JUMPHERE(foundcr);
   notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
   OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
-  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
+  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
 #endif
@@ -3955,13 +4632,13 @@ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
 JUMPHERE(lastchar);
 JUMPHERE(firstchar);
 
-if (firstline)
+if (common->match_end_ptr != 0)
   OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
 }
 
-static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks);
+static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks);
 
-static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, pcre_uint8 *start_bits, BOOL firstline)
+static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, const sljit_u8 *start_bits)
 {
 DEFINE_COMPILER;
 struct sljit_label *start;
@@ -3972,11 +4649,10 @@ jump_list *matches = NULL;
 struct sljit_jump *jump;
 #endif
 
-if (firstline)
+if (common->match_end_ptr != 0)
   {
-  SLJIT_ASSERT(common->first_line_end != 0);
   OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0);
-  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);
+  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
   }
 
 start = LABEL();
@@ -3996,9 +4672,9 @@ if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE,
 #endif
   OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
   OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);
+  OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);
   OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
-  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+  OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
   found = JUMP(SLJIT_NOT_ZERO);
   }
 
@@ -4012,7 +4688,7 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
 if (common->utf)
   {
   CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+  OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
   }
 #elif defined COMPILE_PCRE16
@@ -4020,8 +4696,8 @@ if (common->utf)
   {
   CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
-  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+  OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
   OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
   }
@@ -4034,7 +4710,7 @@ if (matches != NULL)
   set_jumps(matches, LABEL());
 JUMPHERE(quit);
 
-if (firstline)
+if (common->match_end_ptr != 0)
   OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0);
 }
 
@@ -4047,7 +4723,7 @@ struct sljit_jump *alreadyfound;
 struct sljit_jump *found;
 struct sljit_jump *foundoc = NULL;
 struct sljit_jump *notfound;
-pcre_uint32 oc, bit;
+sljit_u32 oc, bit;
 
 SLJIT_ASSERT(common->req_char_ptr != 0);
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr);
@@ -4108,31 +4784,31 @@ struct sljit_jump *jump;
 struct sljit_label *mainloop;
 
 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
-OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0);
-GET_LOCAL_BASE(TMP3, 0, 0);
+OP1(SLJIT_MOV, TMP3, 0, STACK_TOP, 0);
+GET_LOCAL_BASE(TMP1, 0, 0);
 
 /* Drop frames until we reach STACK_TOP. */
 mainloop = LABEL();
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
-OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0);
-jump = JUMP(SLJIT_SIG_LESS_EQUAL);
-
-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0);
-OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw));
-OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_sw));
-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -sizeof(sljit_sw));
+jump = CMP(SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0);
+
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -2 * sizeof(sljit_sw));
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -3 * sizeof(sljit_sw));
+OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));
 JUMPTO(SLJIT_JUMP, mainloop);
 
 JUMPHERE(jump);
-jump = JUMP(SLJIT_SIG_LESS);
-/* End of dropping frames. */
+jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0);
+/* End of reverting values. */
+OP1(SLJIT_MOV, STACK_TOP, 0, TMP3, 0);
 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
 
 JUMPHERE(jump);
 OP1(SLJIT_NEG, TMP2, 0, TMP2, 0);
-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0);
-OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw));
-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -2 * sizeof(sljit_sw));
+OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));
 JUMPTO(SLJIT_JUMP, mainloop);
 }
 
@@ -4165,11 +4841,11 @@ if (common->use_ucp)
   jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
   add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
-  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
-  OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+  OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
-  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
-  OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
   JUMPHERE(jump);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0);
   }
@@ -4184,7 +4860,7 @@ else
   if (common->utf)
     jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
 #endif /* COMPILE_PCRE8 */
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
+  OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
   OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
   OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0);
@@ -4209,11 +4885,11 @@ if (common->use_ucp)
   jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
   add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
-  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
-  OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+  OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
-  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
-  OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
   JUMPHERE(jump);
   }
 else
@@ -4229,7 +4905,7 @@ else
   if (common->utf)
     jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
 #endif
-  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
   OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
   OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
 #ifndef COMPILE_PCRE8
@@ -4241,15 +4917,16 @@ else
   }
 set_jumps(skipread_list, LABEL());
 
-OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
+OP2(SLJIT_XOR | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
 sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
 }
 
-static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)
+static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)
 {
+/* May destroy TMP1. */
 DEFINE_COMPILER;
 int ranges[MAX_RANGE_SIZE];
-pcre_uint8 bit, cbit, all;
+sljit_u8 bit, cbit, all;
 int i, byte, length = 0;
 
 bit = bits[0] & 0x1;
@@ -4391,7 +5068,7 @@ switch(length)
   return TRUE;
 
   default:
-  SLJIT_ASSERT_STOP();
+  SLJIT_UNREACHABLE();
   return FALSE;
   }
 }
@@ -4404,22 +5081,22 @@ DEFINE_COMPILER;
 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 
 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
-OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
 #ifdef COMPILE_PCRE8
 if (common->utf)
   {
 #endif
-  OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
   OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
 #ifdef COMPILE_PCRE8
   }
 #endif
 #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
-OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
 }
 
@@ -4430,34 +5107,34 @@ DEFINE_COMPILER;
 
 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
-OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
 #ifdef COMPILE_PCRE8
 if (common->utf)
   {
 #endif
-  OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
-  OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
-  OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
   OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
-  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
-  OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
-  OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
-  OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
+  OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
 #ifdef COMPILE_PCRE8
   }
 #endif
 #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
-OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
 
 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
 }
@@ -4470,22 +5147,22 @@ DEFINE_COMPILER;
 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
 
 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
-OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
 #ifdef COMPILE_PCRE8
 if (common->utf)
   {
 #endif
-  OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+  OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
   OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
 #ifdef COMPILE_PCRE8
   }
 #endif
 #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
-OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
 
 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
 }
@@ -4510,7 +5187,7 @@ label = LABEL();
 OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
 OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
 jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
-OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
+OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
 JUMPTO(SLJIT_NOT_ZERO, label);
 
 JUMPHERE(jump);
@@ -4544,17 +5221,17 @@ OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
 #ifndef COMPILE_PCRE8
 jump = CMP(SLJIT_GREATER, CHAR1, 0, SLJIT_IMM, 255);
 #endif
-OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
+OP1(SLJIT_MOV_U8, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
 #ifndef COMPILE_PCRE8
 JUMPHERE(jump);
 jump = CMP(SLJIT_GREATER, CHAR2, 0, SLJIT_IMM, 255);
 #endif
-OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
+OP1(SLJIT_MOV_U8, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
 #ifndef COMPILE_PCRE8
 JUMPHERE(jump);
 #endif
 jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
-OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
+OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
 JUMPTO(SLJIT_NOT_ZERO, label);
 
 JUMPHERE(jump);
@@ -4574,11 +5251,11 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
 static const pcre_uchar * SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1)
 {
 /* This function would be ineffective to do in JIT level. */
-pcre_uint32 c1, c2;
+sljit_u32 c1, c2;
 const pcre_uchar *src2 = args->uchar_ptr;
 const pcre_uchar *end2 = args->end;
 const ucd_record *ur;
-const pcre_uint32 *pp;
+const sljit_u32 *pp;
 
 while (src1 < end1)
   {
@@ -4638,16 +5315,16 @@ if (context->sourcereg == -1)
 #if defined COMPILE_PCRE8
 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
   if (context->length >= 4)
-    OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+    OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
   else if (context->length >= 2)
-    OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+    OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
   else
 #endif
-    OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+    OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
 #elif defined COMPILE_PCRE16
 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
   if (context->length >= 4)
-    OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+    OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
   else
 #endif
     OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
@@ -4689,12 +5366,12 @@ do
 #endif
     {
     if (context->length >= 4)
-      OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+      OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
     else if (context->length >= 2)
-      OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+      OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
 #if defined COMPILE_PCRE8
     else if (context->length >= 1)
-      OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+      OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
 #endif /* COMPILE_PCRE8 */
     context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
 
@@ -4721,7 +5398,7 @@ do
 #endif
 
       default:
-      SLJIT_ASSERT_STOP();
+      SLJIT_UNREACHABLE();
       break;
       }
     context->ucharptr = 0;
@@ -4777,6 +5454,8 @@ return cc;
     } \
   charoffset = (value);
 
+static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr);
+
 static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
 {
 DEFINE_COMPILER;
@@ -4793,8 +5472,8 @@ BOOL utf = common->utf;
 #ifdef SUPPORT_UCP
 BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
 BOOL charsaved = FALSE;
-int typereg = TMP1, scriptreg = TMP1;
-const pcre_uint32 *other_cases;
+int typereg = TMP1;
+const sljit_u32 *other_cases;
 sljit_uw typeoffset;
 #endif
 
@@ -4856,6 +5535,14 @@ while (*cc != XCL_END)
     switch(*cc)
       {
       case PT_ANY:
+      /* Any either accepts everything or ignored. */
+      if (cc[-1] == XCL_PROP)
+        {
+        compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE);
+        if (list == backtracks)
+          add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+        return;
+        }
       break;
 
       case PT_LAMP:
@@ -4885,17 +5572,17 @@ while (*cc != XCL_END)
       break;
 
       default:
-      SLJIT_ASSERT_STOP();
+      SLJIT_UNREACHABLE();
       break;
       }
     cc += 2;
     }
 #endif
   }
+SLJIT_ASSERT(compares > 0);
 
 /* We are not necessary in utf mode even in 8 bit mode. */
 cc = ccbegin;
-detect_partial_match(common, backtracks);
 read_char_range(common, min, max, (cc[-1] & XCL_NOT) != 0);
 
 if ((cc[-1] & XCL_HASPROP) == 0)
@@ -4903,13 +5590,13 @@ if ((cc[-1] & XCL_HASPROP) == 0)
   if ((cc[-1] & XCL_MAP) != 0)
     {
     jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
-    if (!check_class_ranges(common, (const pcre_uint8 *)cc, (((const pcre_uint8 *)cc)[31] & 0x80) != 0, TRUE, &found))
+    if (!check_class_ranges(common, (const sljit_u8 *)cc, (((const sljit_u8 *)cc)[31] & 0x80) != 0, TRUE, &found))
       {
       OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
       OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
-      OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
+      OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
       OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
-      OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+      OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
       add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO));
       }
 
@@ -4926,11 +5613,11 @@ if ((cc[-1] & XCL_HASPROP) == 0)
   }
 else if ((cc[-1] & XCL_MAP) != 0)
   {
-  OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
+  OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
 #ifdef SUPPORT_UCP
   charsaved = TRUE;
 #endif
-  if (!check_class_ranges(common, (const pcre_uint8 *)cc, FALSE, TRUE, list))
+  if (!check_class_ranges(common, (const sljit_u8 *)cc, FALSE, TRUE, list))
     {
 #ifdef COMPILE_PCRE8
     jump = NULL;
@@ -4940,9 +5627,9 @@ else if ((cc[-1] & XCL_MAP) != 0)
 
     OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
-    OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
+    OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
     OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
-    OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+    OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
     add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO));
 
 #ifdef COMPILE_PCRE8
@@ -4951,45 +5638,91 @@ else if ((cc[-1] & XCL_MAP) != 0)
       JUMPHERE(jump);
     }
 
-  OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+  OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
   cc += 32 / sizeof(pcre_uchar);
   }
 
 #ifdef SUPPORT_UCP
-/* Simple register allocation. TMP1 is preferred if possible. */
 if (needstype || needsscript)
   {
   if (needschar && !charsaved)
-    OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
-  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
-  if (needschar)
+    OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
+
+#ifdef COMPILE_PCRE32
+  if (!common->utf)
+    {
+    jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10ffff + 1);
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+    JUMPHERE(jump);
+    }
+#endif
+
+  OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
+  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
+  OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
+  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+  OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
+  OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
+
+  /* Before anything else, we deal with scripts. */
+  if (needsscript)
     {
-    if (needstype)
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
+    OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
+
+    ccbegin = cc;
+
+    while (*cc != XCL_END)
       {
-      OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
-      typereg = RETURN_ADDR;
+      if (*cc == XCL_SINGLE)
+        {
+        cc ++;
+        GETCHARINCTEST(c, cc);
+        }
+      else if (*cc == XCL_RANGE)
+        {
+        cc ++;
+        GETCHARINCTEST(c, cc);
+        GETCHARINCTEST(c, cc);
+        }
+      else
+        {
+        SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
+        cc++;
+        if (*cc == PT_SC)
+          {
+          compares--;
+          invertcmp = (compares == 0 && list != backtracks);
+          if (cc[-1] == XCL_NOTPROP)
+            invertcmp ^= 0x1;
+          jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]);
+          add_jump(compiler, compares > 0 ? list : backtracks, jump);
+          }
+        cc += 2;
+        }
       }
 
-    if (needsscript)
-      scriptreg = TMP3;
-    OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+    cc = ccbegin;
     }
-  else if (needstype && needsscript)
-    scriptreg = TMP3;
-  /* In all other cases only one of them was specified, and that can goes to TMP1. */
 
-  if (needsscript)
+  if (needschar)
     {
-    if (scriptreg == TMP1)
+    OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
+    }
+
+  if (needstype)
+    {
+    if (!needschar)
       {
-      OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
-      OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3);
+      OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
+      OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
       }
     else
       {
       OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
-      OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
-      OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);
+      OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
+      typereg = RETURN_ADDR;
       }
     }
   }
@@ -5015,14 +5748,14 @@ while (*cc != XCL_END)
 
     if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
       {
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
-      OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+      OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
       numberofcmps++;
       }
     else if (numberofcmps > 0)
       {
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+      OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
       numberofcmps = 0;
       }
@@ -5041,14 +5774,14 @@ while (*cc != XCL_END)
 
     if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
       {
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
-      OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_LESS_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+      OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
       numberofcmps++;
       }
     else if (numberofcmps > 0)
       {
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+      OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
       numberofcmps = 0;
       }
@@ -5061,29 +5794,24 @@ while (*cc != XCL_END)
 #ifdef SUPPORT_UCP
   else
     {
+    SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
     if (*cc == XCL_NOTPROP)
       invertcmp ^= 0x1;
     cc++;
     switch(*cc)
       {
       case PT_ANY:
-      if (list != backtracks)
-        {
-        if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))
-          continue;
-        }
-      else if (cc[-1] == XCL_NOTPROP)
-        continue;
-      jump = JUMP(SLJIT_JUMP);
+      if (!invertcmp)
+        jump = JUMP(SLJIT_JUMP);
       break;
 
       case PT_LAMP:
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
-      OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
+      OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
+      OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
       break;
 
@@ -5098,39 +5826,40 @@ while (*cc != XCL_END)
       break;
 
       case PT_SC:
-      jump = CMP(SLJIT_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]);
+      compares++;
+      /* Do nothing. */
       break;
 
       case PT_SPACE:
       case PT_PXSPACE:
       SET_CHAR_OFFSET(9);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9);
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9);
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
 
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);
+      OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
 
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);
+      OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
 
       SET_TYPE_OFFSET(ucp_Zl);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
+      OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
       break;
 
       case PT_WORD:
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
       /* Fall through. */
 
       case PT_ALNUM:
       SET_TYPE_OFFSET(ucp_Ll);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
-      OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, (*cc == PT_ALNUM) ? SLJIT_UNUSED : TMP2, 0, SLJIT_LESS_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+      OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
       SET_TYPE_OFFSET(ucp_Nd);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+      OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
       break;
 
@@ -5152,8 +5881,8 @@ while (*cc != XCL_END)
           OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
           OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
           }
-        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]);
-        OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+        OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]);
+        OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
         other_cases += 2;
         }
       else if (is_powerof2(other_cases[2] ^ other_cases[1]))
@@ -5165,63 +5894,63 @@ while (*cc != XCL_END)
           OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
           OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
           }
-        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]);
-        OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+        OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]);
+        OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
 
-        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));
-        OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+        OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));
+        OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);
 
         other_cases += 3;
         }
       else
         {
-        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
-        OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+        OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
+        OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
         }
 
       while (*other_cases != NOTACHAR)
         {
-        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
-        OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+        OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
+        OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);
         }
       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
       break;
 
       case PT_UCNC:
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));
-      OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));
-      OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));
+      OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));
+      OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
 
       SET_CHAR_OFFSET(0xa0);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));
-      OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));
+      OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
       SET_CHAR_OFFSET(0);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0);
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_GREATER_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0);
+      OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_GREATER_EQUAL);
       jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
       break;
 
       case PT_PXGRAPH:
       /* C and Z groups are the farthest two groups. */
       SET_TYPE_OFFSET(ucp_Ll);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER);
+      OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);
 
       jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
 
       /* In case of ucp_Cf, we overwrite the result. */
       SET_CHAR_OFFSET(0x2066);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
 
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
-      OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
+      OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
 
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);
-      OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);
+      OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
 
       JUMPHERE(jump);
       jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);
@@ -5230,65 +5959,290 @@ while (*cc != XCL_END)
       case PT_PXPRINT:
       /* C and Z groups are the farthest two groups. */
       SET_TYPE_OFFSET(ucp_Ll);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER);
+      OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);
 
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll);
-      OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_NOT_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll);
+      OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_NOT_EQUAL);
 
       jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
 
       /* In case of ucp_Cf, we overwrite the result. */
       SET_CHAR_OFFSET(0x2066);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
+
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
+      OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+
+      JUMPHERE(jump);
+      jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);
+      break;
+
+      case PT_PXPUNCT:
+      SET_TYPE_OFFSET(ucp_Sc);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
+
+      SET_CHAR_OFFSET(0);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f);
+      OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL);
+
+      SET_TYPE_OFFSET(ucp_Pc);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc);
+      OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
+      jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
+      break;
+
+      default:
+      SLJIT_UNREACHABLE();
+      break;
+      }
+    cc += 2;
+    }
+#endif
+
+  if (jump != NULL)
+    add_jump(compiler, compares > 0 ? list : backtracks, jump);
+  }
+
+if (found != NULL)
+  set_jumps(found, LABEL());
+}
+
+#undef SET_TYPE_OFFSET
+#undef SET_CHAR_OFFSET
+
+#endif
+
+static pcre_uchar *compile_simple_assertion_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks)
+{
+DEFINE_COMPILER;
+int length;
+struct sljit_jump *jump[4];
+#ifdef SUPPORT_UTF
+struct sljit_label *label;
+#endif /* SUPPORT_UTF */
+
+switch(type)
+  {
+  case OP_SOD:
+  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
+  return cc;
+
+  case OP_SOM:
+  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
+  return cc;
+
+  case OP_NOT_WORD_BOUNDARY:
+  case OP_WORD_BOUNDARY:
+  add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
+  sljit_set_current_flags(compiler, SLJIT_SET_Z);
+  add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO));
+  return cc;
 
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
-      OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
+  case OP_EODN:
+  /* Requires rather complex checks. */
+  jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
+    {
+    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+    if (common->mode == JIT_COMPILE)
+      add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));
+    else
+      {
+      jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0);
+      OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
+      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
+      OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_EQUAL);
+      add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL));
+      check_partial(common, TRUE);
+      add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+      JUMPHERE(jump[1]);
+      }
+    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
+    }
+  else if (common->nltype == NLTYPE_FIXED)
+    {
+    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));
+    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
+    }
+  else
+    {
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+    jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
+    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+    OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
+    jump[2] = JUMP(SLJIT_GREATER);
+    add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL) /* LESS */);
+    /* Equal. */
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+    jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
+    add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+
+    JUMPHERE(jump[1]);
+    if (common->nltype == NLTYPE_ANYCRLF)
+      {
+      OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+      add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, STR_END, 0));
+      add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
+      }
+    else
+      {
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0);
+      read_char_range(common, common->nlmin, common->nlmax, TRUE);
+      add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
+      add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
+      sljit_set_current_flags(compiler, SLJIT_SET_Z);
+      add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
+      }
+    JUMPHERE(jump[2]);
+    JUMPHERE(jump[3]);
+    }
+  JUMPHERE(jump[0]);
+  check_partial(common, FALSE);
+  return cc;
+
+  case OP_EOD:
+  add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));
+  check_partial(common, FALSE);
+  return cc;
+
+  case OP_DOLL:
+  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
+  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+
+  if (!common->endonly)
+    compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks);
+  else
+    {
+    add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));
+    check_partial(common, FALSE);
+    }
+  return cc;
+
+  case OP_DOLLM:
+  jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
+  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
+  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+  check_partial(common, FALSE);
+  jump[0] = JUMP(SLJIT_JUMP);
+  JUMPHERE(jump[1]);
+
+  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
+    {
+    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+    if (common->mode == JIT_COMPILE)
+      add_jump(compiler, backtracks, CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0));
+    else
+      {
+      jump[1] = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);
+      /* STR_PTR = STR_END - IN_UCHARS(1) */
+      add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+      check_partial(common, TRUE);
+      add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+      JUMPHERE(jump[1]);
+      }
+
+    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
+    }
+  else
+    {
+    peek_char(common, common->nlmax);
+    check_newlinechar(common, common->nltype, backtracks, FALSE);
+    }
+  JUMPHERE(jump[0]);
+  return cc;
 
-      JUMPHERE(jump);
-      jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);
-      break;
+  case OP_CIRC:
+  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+  add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
+  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+  return cc;
 
-      case PT_PXPUNCT:
-      SET_TYPE_OFFSET(ucp_Sc);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
+  case OP_CIRCM:
+  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+  jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0);
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
+  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+  jump[0] = JUMP(SLJIT_JUMP);
+  JUMPHERE(jump[1]);
 
-      SET_CHAR_OFFSET(0);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f);
-      OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
+  add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
+    {
+    OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+    add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, TMP1, 0));
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
+    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
+    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
+    }
+  else
+    {
+    skip_char_back(common);
+    read_char_range(common, common->nlmin, common->nlmax, TRUE);
+    check_newlinechar(common, common->nltype, backtracks, FALSE);
+    }
+  JUMPHERE(jump[0]);
+  return cc;
 
-      SET_TYPE_OFFSET(ucp_Pc);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc);
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL);
-      jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
-      break;
-      }
-    cc += 2;
+  case OP_REVERSE:
+  length = GET(cc, 0);
+  if (length == 0)
+    return cc + LINK_SIZE;
+  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+#ifdef SUPPORT_UTF
+  if (common->utf)
+    {
+    OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+    OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
+    label = LABEL();
+    add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
+    skip_char_back(common);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+    JUMPTO(SLJIT_NOT_ZERO, label);
     }
+  else
 #endif
-
-  if (jump != NULL)
-    add_jump(compiler, compares > 0 ? list : backtracks, jump);
+    {
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+    OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
+    add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0));
+    }
+  check_start_used_ptr(common);
+  return cc + LINK_SIZE;
   }
-
-if (found != NULL)
-  set_jumps(found, LABEL());
+SLJIT_UNREACHABLE();
+return cc;
 }
 
-#undef SET_TYPE_OFFSET
-#undef SET_CHAR_OFFSET
-
-#endif
-
-static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks)
+static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr)
 {
 DEFINE_COMPILER;
 int length;
 unsigned int c, oc, bit;
 compare_context context;
-struct sljit_jump *jump[4];
+struct sljit_jump *jump[3];
 jump_list *end_list;
 #ifdef SUPPORT_UTF
 struct sljit_label *label;
@@ -5299,67 +6253,53 @@ pcre_uchar propdata[5];
 
 switch(type)
   {
-  case OP_SOD:
-  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
-  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
-  return cc;
-
-  case OP_SOM:
-  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
-  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
-  return cc;
-
-  case OP_NOT_WORD_BOUNDARY:
-  case OP_WORD_BOUNDARY:
-  add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
-  add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO));
-  return cc;
-
   case OP_NOT_DIGIT:
   case OP_DIGIT:
   /* Digits are usually 0-9, so it is worth to optimize them. */
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
-  if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_digit, FALSE))
+  if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE))
     read_char7_type(common, type == OP_NOT_DIGIT);
   else
 #endif
     read_char8_type(common, type == OP_NOT_DIGIT);
     /* Flip the starting bit in the negative case. */
-  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
+  OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
   add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO));
   return cc;
 
   case OP_NOT_WHITESPACE:
   case OP_WHITESPACE:
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
-  if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_space, FALSE))
+  if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE))
     read_char7_type(common, type == OP_NOT_WHITESPACE);
   else
 #endif
     read_char8_type(common, type == OP_NOT_WHITESPACE);
-  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
+  OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
   add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO));
   return cc;
 
   case OP_NOT_WORDCHAR:
   case OP_WORDCHAR:
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
-  if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_word, FALSE))
+  if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE))
     read_char7_type(common, type == OP_NOT_WORDCHAR);
   else
 #endif
     read_char8_type(common, type == OP_NOT_WORDCHAR);
-  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
+  OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
   add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO));
   return cc;
 
   case OP_ANY:
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
   read_char_range(common, common->nlmin, common->nlmax, TRUE);
   if (common->nltype == NLTYPE_FIXED && common->newline > 255)
     {
@@ -5380,7 +6320,8 @@ switch(type)
   return cc;
 
   case OP_ALLANY:
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
 #ifdef SUPPORT_UTF
   if (common->utf)
     {
@@ -5389,13 +6330,13 @@ switch(type)
 #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
 #if defined COMPILE_PCRE8
     jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
-    OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+    OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
 #elif defined COMPILE_PCRE16
     jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
-    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
-    OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+    OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
 #endif
@@ -5408,7 +6349,8 @@ switch(type)
   return cc;
 
   case OP_ANYBYTE:
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
   OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
   return cc;
 
@@ -5421,246 +6363,94 @@ switch(type)
   propdata[2] = cc[0];
   propdata[3] = cc[1];
   propdata[4] = XCL_END;
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
   compile_xclass_matchingpath(common, propdata, backtracks);
   return cc + 2;
 #endif
 #endif
 
   case OP_ANYNL:
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
   read_char_range(common, common->bsr_nlmin, common->bsr_nlmax, FALSE);
-  jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
-  /* We don't need to handle soft partial matching case. */
-  end_list = NULL;
-  if (common->mode != JIT_PARTIAL_HARD_COMPILE)
-    add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-  else
-    check_str_end(common, &end_list);
-  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
-  jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
-  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-  jump[2] = JUMP(SLJIT_JUMP);
-  JUMPHERE(jump[0]);
-  check_newlinechar(common, common->bsr_nltype, backtracks, FALSE);
-  set_jumps(end_list, LABEL());
-  JUMPHERE(jump[1]);
-  JUMPHERE(jump[2]);
-  return cc;
-
-  case OP_NOT_HSPACE:
-  case OP_HSPACE:
-  detect_partial_match(common, backtracks);
-  read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE);
-  add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
-  add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
-  return cc;
-
-  case OP_NOT_VSPACE:
-  case OP_VSPACE:
-  detect_partial_match(common, backtracks);
-  read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE);
-  add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
-  add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
-  return cc;
-
-#ifdef SUPPORT_UCP
-  case OP_EXTUNI:
-  detect_partial_match(common, backtracks);
-  read_char(common);
-  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
-  OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
-  /* Optimize register allocation: use a real register. */
-  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
-  OP1(SLJIT_MOV_UB, STACK_TOP, 0, SLJIT_MEM2(TMP1, TMP2), 3);
-
-  label = LABEL();
-  jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
-  OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
-  read_char(common);
-  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
-  OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
-  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM2(TMP1, TMP2), 3);
-
-  OP2(SLJIT_SHL, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2);
-  OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable));
-  OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0);
-  OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
-  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
-  JUMPTO(SLJIT_NOT_ZERO, label);
-
-  OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
-  JUMPHERE(jump[0]);
-  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
-
-  if (common->mode == JIT_PARTIAL_HARD_COMPILE)
-    {
-    jump[0] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
-    /* Since we successfully read a char above, partial matching must occure. */
-    check_partial(common, TRUE);
-    JUMPHERE(jump[0]);
-    }
-  return cc;
-#endif
-
-  case OP_EODN:
-  /* Requires rather complex checks. */
-  jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
-  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
-    {
-    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
-    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
-    if (common->mode == JIT_COMPILE)
-      add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));
-    else
-      {
-      jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0);
-      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
-      OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS);
-      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
-      OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_NOT_EQUAL);
-      add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL));
-      check_partial(common, TRUE);
-      add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
-      JUMPHERE(jump[1]);
-      }
-    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
-    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
-    }
-  else if (common->nltype == NLTYPE_FIXED)
-    {
-    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
-    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));
-    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
-    }
-  else
-    {
-    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
-    jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
-    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
-    OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
-    jump[2] = JUMP(SLJIT_GREATER);
-    add_jump(compiler, backtracks, JUMP(SLJIT_LESS));
-    /* Equal. */
-    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-    jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
-    add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
-
-    JUMPHERE(jump[1]);
-    if (common->nltype == NLTYPE_ANYCRLF)
-      {
-      OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-      add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, STR_END, 0));
-      add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
-      }
-    else
-      {
-      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0);
-      read_char_range(common, common->nlmin, common->nlmax, TRUE);
-      add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
-      add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
-      add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
-      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
-      }
-    JUMPHERE(jump[2]);
-    JUMPHERE(jump[3]);
-    }
-  JUMPHERE(jump[0]);
-  check_partial(common, FALSE);
-  return cc;
-
-  case OP_EOD:
-  add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));
-  check_partial(common, FALSE);
-  return cc;
-
-  case OP_CIRC:
-  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
-  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
-  add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
-  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
-  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
-  return cc;
-
-  case OP_CIRCM:
-  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
-  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
-  jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0);
-  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
-  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
-  jump[0] = JUMP(SLJIT_JUMP);
-  JUMPHERE(jump[1]);
-
-  add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
-    {
-    OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
-    add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, TMP1, 0));
-    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
-    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
-    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
-    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
-    }
+  jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
+  /* We don't need to handle soft partial matching case. */
+  end_list = NULL;
+  if (common->mode != JIT_PARTIAL_HARD_COMPILE)
+    add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
   else
-    {
-    skip_char_back(common);
-    read_char_range(common, common->nlmin, common->nlmax, TRUE);
-    check_newlinechar(common, common->nltype, backtracks, FALSE);
-    }
+    check_str_end(common, &end_list);
+  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+  jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+  jump[2] = JUMP(SLJIT_JUMP);
   JUMPHERE(jump[0]);
+  check_newlinechar(common, common->bsr_nltype, backtracks, FALSE);
+  set_jumps(end_list, LABEL());
+  JUMPHERE(jump[1]);
+  JUMPHERE(jump[2]);
   return cc;
 
-  case OP_DOLL:
-  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
-  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
-  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+  case OP_NOT_HSPACE:
+  case OP_HSPACE:
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
+  read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE);
+  add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
+  sljit_set_current_flags(compiler, SLJIT_SET_Z);
+  add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
+  return cc;
 
-  if (!common->endonly)
-    compile_char1_matchingpath(common, OP_EODN, cc, backtracks);
-  else
-    {
-    add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));
-    check_partial(common, FALSE);
-    }
+  case OP_NOT_VSPACE:
+  case OP_VSPACE:
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
+  read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE);
+  add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
+  sljit_set_current_flags(compiler, SLJIT_SET_Z);
+  add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
   return cc;
 
-  case OP_DOLLM:
-  jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
-  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
-  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
-  add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
-  check_partial(common, FALSE);
-  jump[0] = JUMP(SLJIT_JUMP);
-  JUMPHERE(jump[1]);
+#ifdef SUPPORT_UCP
+  case OP_EXTUNI:
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
+  read_char(common);
+  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
+  /* Optimize register allocation: use a real register. */
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
+  OP1(SLJIT_MOV_U8, STACK_TOP, 0, SLJIT_MEM2(TMP1, TMP2), 3);
 
-  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
-    {
-    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
-    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
-    if (common->mode == JIT_COMPILE)
-      add_jump(compiler, backtracks, CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0));
-    else
-      {
-      jump[1] = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);
-      /* STR_PTR = STR_END - IN_UCHARS(1) */
-      add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
-      check_partial(common, TRUE);
-      add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
-      JUMPHERE(jump[1]);
-      }
+  label = LABEL();
+  jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+  OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
+  read_char(common);
+  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM2(TMP1, TMP2), 3);
 
-    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
-    add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
-    }
-  else
+  OP2(SLJIT_SHL, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2);
+  OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable));
+  OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0);
+  OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
+  OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+  JUMPTO(SLJIT_NOT_ZERO, label);
+
+  OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
+  JUMPHERE(jump[0]);
+  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+
+  if (common->mode == JIT_PARTIAL_HARD_COMPILE)
     {
-    peek_char(common, common->nlmax);
-    check_newlinechar(common, common->nltype, backtracks, FALSE);
+    jump[0] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
+    /* Since we successfully read a char above, partial matching must occure. */
+    check_partial(common, TRUE);
+    JUMPHERE(jump[0]);
     }
-  JUMPHERE(jump[0]);
   return cc;
+#endif
 
   case OP_CHAR:
   case OP_CHARI:
@@ -5668,7 +6458,8 @@ switch(type)
 #ifdef SUPPORT_UTF
   if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);
 #endif
-  if (common->mode == JIT_COMPILE && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0))
+  if (common->mode == JIT_COMPILE && check_str_ptr
+      && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0))
     {
     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
     add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));
@@ -5681,7 +6472,8 @@ switch(type)
     return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);
     }
 
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
 #ifdef SUPPORT_UTF
   if (common->utf)
     {
@@ -5713,7 +6505,8 @@ switch(type)
 
   case OP_NOT:
   case OP_NOTI:
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
   length = 1;
 #ifdef SUPPORT_UTF
   if (common->utf)
@@ -5722,7 +6515,7 @@ switch(type)
     c = *cc;
     if (c < 128)
       {
-      OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+      OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
       if (type == OP_NOT || !char_has_othercase(common, cc))
         add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));
       else
@@ -5774,16 +6567,17 @@ switch(type)
 
   case OP_CLASS:
   case OP_NCLASS:
-  detect_partial_match(common, backtracks);
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
 
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
-  bit = (common->utf && is_char7_bitset((const pcre_uint8 *)cc, type == OP_NCLASS)) ? 127 : 255;
+  bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255;
   read_char_range(common, 0, bit, type == OP_NCLASS);
 #else
   read_char_range(common, 0, 255, type == OP_NCLASS);
 #endif
 
-  if (check_class_ranges(common, (const pcre_uint8 *)cc, type == OP_NCLASS, FALSE, backtracks))
+  if (check_class_ranges(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks))
     return cc + 32 / sizeof(pcre_uchar);
 
 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
@@ -5808,51 +6602,26 @@ switch(type)
 
   OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
   OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
-  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
+  OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
   OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
-  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+  OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
   add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
 
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
   if (jump[0] != NULL)
     JUMPHERE(jump[0]);
 #endif
-
   return cc + 32 / sizeof(pcre_uchar);
 
 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
   case OP_XCLASS:
+  if (check_str_ptr)
+    detect_partial_match(common, backtracks);
   compile_xclass_matchingpath(common, cc + LINK_SIZE, backtracks);
   return cc + GET(cc, 0) - 1;
 #endif
-
-  case OP_REVERSE:
-  length = GET(cc, 0);
-  if (length == 0)
-    return cc + LINK_SIZE;
-  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-#ifdef SUPPORT_UTF
-  if (common->utf)
-    {
-    OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
-    OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
-    label = LABEL();
-    add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
-    skip_char_back(common);
-    OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
-    JUMPTO(SLJIT_NOT_ZERO, label);
-    }
-  else
-#endif
-    {
-    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
-    OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
-    add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0));
-    }
-  check_start_used_ptr(common);
-  return cc + LINK_SIZE;
   }
-SLJIT_ASSERT_STOP();
+SLJIT_UNREACHABLE();
 return cc;
 }
 
@@ -5919,7 +6688,7 @@ if (context.length > 0)
   }
 
 /* A non-fixed length character will be checked if length == 0. */
-return compile_char1_matchingpath(common, *cc, cc + 1, backtracks);
+return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE);
 }
 
 /* Forward definitions. */
@@ -6038,9 +6807,9 @@ else
 #endif /* SUPPORT_UTF && SUPPORT_UCP */
   {
   if (ref)
-    OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);
   else
-    OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
 
   if (withchecks)
     jump = JUMP(SLJIT_ZERO);
@@ -6094,7 +6863,7 @@ pcre_uchar *ccbegin = cc;
 int min = 0, max = 0;
 BOOL minimize;
 
-PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);
+PUSH_BACKTRACK(sizeof(ref_iterator_backtrack), cc, NULL);
 
 if (ref)
   offset = GET2(cc, 1) << 1;
@@ -6131,7 +6900,7 @@ switch(type)
   cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;
   break;
   default:
-  SLJIT_ASSERT_STOP();
+  SLJIT_UNREACHABLE();
   break;
   }
 
@@ -6145,7 +6914,7 @@ if (!minimize)
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
     /* Temporary release of STR_PTR. */
-    OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+    OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
     /* Handles both invalid and empty cases. Since the minimum repeat,
     is zero the invalid case is basically the same as an empty case. */
     if (ref)
@@ -6158,7 +6927,7 @@ if (!minimize)
       zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
       }
     /* Restore if not zero length. */
-    OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+    OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
     }
   else
     {
@@ -6214,7 +6983,7 @@ if (!minimize)
     }
 
   JUMPHERE(zerolength);
-  BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+  BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();
 
   count_match(common);
   return cc;
@@ -6260,7 +7029,7 @@ else
     }
   }
 
-BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();
 if (max > 0)
   add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
 
@@ -6274,7 +7043,7 @@ if (min > 1)
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
   OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
-  CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(iterator_backtrack)->matchingpath);
+  CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(ref_iterator_backtrack)->matchingpath);
   }
 else if (max > 0)
   OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
@@ -6405,7 +7174,7 @@ return (*PUBL(callout))(callout_block);
     (((int)sizeof(PUBL(callout_block)) + 7) & ~7)
 
 #define CALLOUT_ARG_OFFSET(arg) \
-    (-CALLOUT_ARG_SIZE + SLJIT_OFFSETOF(PUBL(callout_block), arg))
+    SLJIT_OFFSETOF(PUBL(callout_block), arg)
 
 static SLJIT_INLINE pcre_uchar *compile_callout_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
 {
@@ -6419,8 +7188,8 @@ allocate_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw));
 SLJIT_ASSERT(common->capture_last_ptr != 0);
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]);
-OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0);
+OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]);
+OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0);
 
 /* These pointer sized fields temporarly stores internal variables. */
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
@@ -6429,32 +7198,59 @@ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(subject), TMP2, 0);
 
 if (common->mark_ptr != 0)
   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr));
-OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2));
-OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE));
+OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2));
+OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE));
 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0);
 
 /* Needed to save important temporary registers. */
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
-OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_TOP, 0, SLJIT_IMM, CALLOUT_ARG_SIZE);
+/* SLJIT_R0 = arguments */
+OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0);
 GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START);
 sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout));
-OP1(SLJIT_MOV_SI, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0);
+OP1(SLJIT_MOV_S32, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0);
 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
 free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw));
 
 /* Check return value. */
-OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
 add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER));
 if (common->forced_quit_label == NULL)
-  add_jump(compiler, &common->forced_quit, JUMP(SLJIT_SIG_LESS));
+  add_jump(compiler, &common->forced_quit, JUMP(SLJIT_NOT_EQUAL) /* SIG_LESS */);
 else
-  JUMPTO(SLJIT_SIG_LESS, common->forced_quit_label);
+  JUMPTO(SLJIT_NOT_EQUAL /* SIG_LESS */, common->forced_quit_label);
 return cc + 2 + 2 * LINK_SIZE;
 }
 
 #undef CALLOUT_ARG_SIZE
 #undef CALLOUT_ARG_OFFSET
 
+static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(pcre_uchar *cc)
+{
+while (TRUE)
+  {
+  switch (*cc)
+    {
+    case OP_NOT_WORD_BOUNDARY:
+    case OP_WORD_BOUNDARY:
+    case OP_CIRC:
+    case OP_CIRCM:
+    case OP_DOLL:
+    case OP_DOLLM:
+    case OP_CALLOUT:
+    case OP_ALT:
+    cc += PRIV(OP_lengths)[*cc];
+    break;
+
+    case OP_KET:
+    return FALSE;
+
+    default:
+    return TRUE;
+    }
+  }
+}
+
 static pcre_uchar *compile_assert_matchingpath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional)
 {
 DEFINE_COMPILER;
@@ -6511,15 +7307,28 @@ if (bra == OP_BRAMINZERO)
 
 if (framesize < 0)
   {
-  extrasize = needs_control_head ? 2 : 1;
+  extrasize = 1;
+  if (bra == OP_BRA && !assert_needs_str_ptr_saving(ccbegin + 1 + LINK_SIZE))
+    extrasize = 0;
+
+  if (needs_control_head)
+    extrasize++;
+
   if (framesize == no_frame)
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);
-  allocate_stack(common, extrasize);
+
+  if (extrasize > 0)
+    allocate_stack(common, extrasize);
+
   if (needs_control_head)
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
-  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
+  if (extrasize > 0)
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
   if (needs_control_head)
     {
+    SLJIT_ASSERT(extrasize == 2);
     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
     }
@@ -6528,12 +7337,14 @@ else
   {
   extrasize = needs_control_head ? 3 : 2;
   allocate_stack(common, framesize + extrasize);
+
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
-  OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
+  OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);
   if (needs_control_head)
     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
   if (needs_control_head)
     {
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
@@ -6542,6 +7353,7 @@ else
     }
   else
     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
+
   init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE);
   }
 
@@ -6565,7 +7377,7 @@ while (1)
   altbacktrack.top = NULL;
   altbacktrack.topbacktracks = NULL;
 
-  if (*ccbegin == OP_ALT)
+  if (*ccbegin == OP_ALT && extrasize > 0)
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
 
   altbacktrack.cc = ccbegin;
@@ -6594,25 +7406,26 @@ while (1)
     {
     if (framesize == no_frame)
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
-    else
+    else if (extrasize > 0)
       free_stack(common, extrasize);
+
     if (needs_control_head)
-      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));
     }
   else
     {
     if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional)
       {
       /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
-      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
+      OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
       if (needs_control_head)
-        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0);
+        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));
       }
     else
       {
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
       if (needs_control_head)
-        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw));
+        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 2));
       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
       }
     }
@@ -6621,24 +7434,27 @@ while (1)
     {
     /* We know that STR_PTR was stored on the top of the stack. */
     if (conditional)
-      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0);
+      {
+      if (extrasize > 0)
+        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? STACK(-2) : STACK(-1));
+      }
     else if (bra == OP_BRAZERO)
       {
       if (framesize < 0)
-        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
+        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize));
       else
         {
-        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw));
-        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + extrasize - 1) * sizeof(sljit_sw));
+        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));
+        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - extrasize));
         OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);
         }
-      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+      OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
       }
     else if (framesize >= 0)
       {
       /* For OP_BRA and OP_BRAMINZERO. */
-      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw));
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));
       }
     }
   add_jump(compiler, found, JUMP(SLJIT_JUMP));
@@ -6682,12 +7498,12 @@ if (common->positive_assert_quit != NULL)
   set_jumps(common->positive_assert_quit, LABEL());
   SLJIT_ASSERT(framesize != no_stack);
   if (framesize < 0)
-    OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));
+    OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));
   else
     {
     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
-    OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
+    OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
     }
   JUMPHERE(jump);
   }
@@ -6698,7 +7514,7 @@ if (needs_control_head)
 if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
   {
   /* Assert is failed. */
-  if (conditional || bra == OP_BRAZERO)
+  if ((conditional && extrasize > 0) || bra == OP_BRAZERO)
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
 
   if (framesize < 0)
@@ -6710,7 +7526,7 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
         free_stack(common, 1);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
       }
-    else
+    else if (extrasize > 0)
       free_stack(common, extrasize);
     }
   else
@@ -6735,17 +7551,19 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
   if (framesize < 0)
     {
     /* We know that STR_PTR was stored on the top of the stack. */
-    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
+    if (extrasize > 0)
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize));
+
     /* Keep the STR_PTR on the top of the stack. */
     if (bra == OP_BRAZERO)
       {
-      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+      OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
       if (extrasize == 2)
         OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
       }
     else if (bra == OP_BRAMINZERO)
       {
-      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+      OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
       }
     }
@@ -6754,13 +7572,13 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
     if (bra == OP_BRA)
       {
       /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
-      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
-      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 2) * sizeof(sljit_sw));
+      OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize + 1));
       }
     else
       {
       /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
-      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw));
+      OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw));
       if (extrasize == 2)
         {
         OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
@@ -6788,7 +7606,7 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
       {
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
-      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw));
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));
       }
     set_jumps(backtrack->common.topbacktracks, LABEL());
     }
@@ -6798,14 +7616,16 @@ else
   /* AssertNot is successful. */
   if (framesize < 0)
     {
-    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+    if (extrasize > 0)
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+
     if (bra != OP_BRA)
       {
       if (extrasize == 2)
         free_stack(common, 1);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
       }
-    else
+    else if (extrasize > 0)
       free_stack(common, extrasize);
     }
   else
@@ -6867,27 +7687,29 @@ if (framesize < 0)
     stacksize = needs_control_head ? 1 : 0;
     if (ket != OP_KET || has_alternatives)
       stacksize++;
-    free_stack(common, stacksize);
+
+    if (stacksize > 0)
+      free_stack(common, stacksize);
     }
 
   if (needs_control_head)
-    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? sizeof(sljit_sw) : 0);
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? STACK(-2) : STACK(-1));
 
   /* TMP2 which is set here used by OP_KETRMAX below. */
   if (ket == OP_KETRMAX)
-    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
+    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));
   else if (ket == OP_KETRMIN)
     {
     /* Move the STR_PTR to the private_data_ptr. */
-    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));
     }
   }
 else
   {
   stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1;
-  OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw));
+  OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw));
   if (needs_control_head)
-    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 0);
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));
 
   if (ket == OP_KETRMAX)
     {
@@ -7123,7 +7945,7 @@ if (bra == OP_BRAMINZERO)
         {
         /* Except when the whole stack frame must be saved. */
         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
-        braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw));
+        braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2));
         }
       JUMPHERE(skip);
       }
@@ -7196,7 +8018,7 @@ if (opcode == OP_ONCE)
         OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
       if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)
-        OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw));
+        OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw));
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);
       }
     else if (ket == OP_KETRMAX || has_alternatives)
@@ -7214,7 +8036,7 @@ if (opcode == OP_ONCE)
       OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
 
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
-    OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
+    OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
 
     stacksize = needs_control_head ? 1 : 0;
     if (ket != OP_KET || has_alternatives)
@@ -7286,13 +8108,13 @@ if (opcode == OP_COND || opcode == OP_SCOND)
     slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;
     OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
-    OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
     slot += common->name_entry_size;
     i--;
     while (i-- > 0)
       {
       OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
-      OP2(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, STR_PTR, 0);
+      OP2(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, STR_PTR, 0);
       slot += common->name_entry_size;
       }
     OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
@@ -7440,7 +8262,7 @@ if (ket == OP_KETRMAX)
     {
     if (has_alternatives)
       BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
-    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
     JUMPTO(SLJIT_NOT_ZERO, rmax_label);
     /* Drop STR_PTR for greedy plus quantifier. */
     if (opcode != OP_ONCE)
@@ -7470,7 +8292,7 @@ if (ket == OP_KETRMAX)
 if (repeat_type == OP_EXACT)
   {
   count_match(common);
-  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);
   JUMPTO(SLJIT_NOT_ZERO, rmax_label);
   }
 else if (repeat_type == OP_UPTO)
@@ -7513,9 +8335,13 @@ while (*cc == OP_ALT)
   cc += GET(cc, 1);
 cc += 1 + LINK_SIZE;
 
-/* Temporarily encoding the needs_control_head in framesize. */
 if (opcode == OP_ONCE)
+  {
+  /* We temporarily encode the needs_control_head in the lowest bit.
+     Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns
+     the same value for small signed numbers (including negative numbers). */
   BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
+  }
 return cc + repeat_length;
 }
 
@@ -7566,7 +8392,7 @@ switch(opcode)
   break;
 
   default:
-  SLJIT_ASSERT_STOP();
+  SLJIT_UNREACHABLE();
   break;
   }
 
@@ -7644,7 +8470,7 @@ else
   OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
   if (needs_control_head)
     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
-  OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1));
+  OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
 
   stack = 0;
   if (!zero)
@@ -7716,7 +8542,7 @@ while (*cc != OP_KETRPOS)
     {
     if (offset != 0)
       {
-      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw));
+      OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw));
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);
@@ -7727,10 +8553,10 @@ while (*cc != OP_KETRPOS)
     else
       {
       OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
-      OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
+      OP2(SLJIT_SUB, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
       if (opcode == OP_SBRAPOS)
-        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw));
-      OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0);
+        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));
+      OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(-framesize - 2), STR_PTR, 0);
       }
 
     /* Even if the match is empty, we need to reset the control head. */
@@ -7776,7 +8602,7 @@ while (*cc != OP_KETRPOS)
     else
       {
       OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
-      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw));
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));
       }
     }
 
@@ -7793,7 +8619,7 @@ if (!zero)
   if (framesize < 0)
     add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
   else /* TMP2 is set to [private_data_ptr] above. */
-    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_sw), SLJIT_IMM, 0));
+    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), STACK(-stacksize), SLJIT_IMM, 0));
   }
 
 /* None of them matched. */
@@ -7802,11 +8628,13 @@ count_match(common);
 return cc + 1 + LINK_SIZE;
 }
 
-static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, int *max, int *min, pcre_uchar **end)
+static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, sljit_u32 *max, sljit_u32 *exact, pcre_uchar **end)
 {
 int class_len;
 
 *opcode = *cc;
+*exact = 0;
+
 if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)
   {
   cc++;
@@ -7834,7 +8662,7 @@ else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)
   {
   cc++;
   *opcode -= OP_TYPESTAR - OP_STAR;
-  *type = 0;
+  *type = OP_END;
   }
 else
   {
@@ -7843,157 +8671,217 @@ else
   cc++;
   class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0);
   *opcode = cc[class_len - 1];
+
   if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)
     {
     *opcode -= OP_CRSTAR - OP_STAR;
-    if (end != NULL)
-      *end = cc + class_len;
+    *end = cc + class_len;
+
+    if (*opcode == OP_PLUS || *opcode == OP_MINPLUS)
+      {
+      *exact = 1;
+      *opcode -= OP_PLUS - OP_STAR;
+      }
     }
   else if (*opcode >= OP_CRPOSSTAR && *opcode <= OP_CRPOSQUERY)
     {
     *opcode -= OP_CRPOSSTAR - OP_POSSTAR;
-    if (end != NULL)
-      *end = cc + class_len;
+    *end = cc + class_len;
+
+    if (*opcode == OP_POSPLUS)
+      {
+      *exact = 1;
+      *opcode = OP_POSSTAR;
+      }
     }
   else
     {
     SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE || *opcode == OP_CRPOSRANGE);
     *max = GET2(cc, (class_len + IMM2_SIZE));
-    *min = GET2(cc, class_len);
+    *exact = GET2(cc, class_len);
 
-    if (*min == 0)
+    if (*max == 0)
       {
-      SLJIT_ASSERT(*max != 0);
-      *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : (*opcode == OP_CRMINRANGE ? OP_MINUPTO : OP_POSUPTO);
+      if (*opcode == OP_CRPOSRANGE)
+        *opcode = OP_POSSTAR;
+      else
+        *opcode -= OP_CRRANGE - OP_STAR;
       }
-    if (*max == *min)
-      *opcode = OP_EXACT;
-
-    if (end != NULL)
-      *end = cc + class_len + 2 * IMM2_SIZE;
+    else
+      {
+      *max -= *exact;
+      if (*max == 0)
+        *opcode = OP_EXACT;
+      else if (*max == 1)
+        {
+        if (*opcode == OP_CRPOSRANGE)
+          *opcode = OP_POSQUERY;
+        else
+          *opcode -= OP_CRRANGE - OP_QUERY;
+        }
+      else
+        {
+        if (*opcode == OP_CRPOSRANGE)
+          *opcode = OP_POSUPTO;
+        else
+          *opcode -= OP_CRRANGE - OP_UPTO;
+        }
+      }
+    *end = cc + class_len + 2 * IMM2_SIZE;
     }
   return cc;
   }
 
-if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO)
+switch(*opcode)
   {
+  case OP_EXACT:
+  *exact = GET2(cc, 0);
+  cc += IMM2_SIZE;
+  break;
+
+  case OP_PLUS:
+  case OP_MINPLUS:
+  *exact = 1;
+  *opcode -= OP_PLUS - OP_STAR;
+  break;
+
+  case OP_POSPLUS:
+  *exact = 1;
+  *opcode = OP_POSSTAR;
+  break;
+
+  case OP_UPTO:
+  case OP_MINUPTO:
+  case OP_POSUPTO:
   *max = GET2(cc, 0);
   cc += IMM2_SIZE;
+  break;
   }
 
-if (*type == 0)
+if (*type == OP_END)
   {
   *type = *cc;
-  if (end != NULL)
-    *end = next_opcode(common, cc);
+  *end = next_opcode(common, cc);
   cc++;
   return cc;
   }
 
-if (end != NULL)
-  {
-  *end = cc + 1;
+*end = cc + 1;
 #ifdef SUPPORT_UTF
-  if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);
+if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);
 #endif
-  }
 return cc;
 }
 
 static pcre_uchar *compile_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
-{
-DEFINE_COMPILER;
-backtrack_common *backtrack;
-pcre_uchar opcode;
-pcre_uchar type;
-int max = -1, min = -1;
-pcre_uchar *end;
-jump_list *nomatch = NULL;
-struct sljit_jump *jump = NULL;
-struct sljit_label *label;
-int private_data_ptr = PRIVATE_DATA(cc);
-int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP);
-int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;
-int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);
-int tmp_base, tmp_offset;
-
-PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);
-
-cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &min, &end);
-
-switch(type)
-  {
-  case OP_NOT_DIGIT:
-  case OP_DIGIT:
-  case OP_NOT_WHITESPACE:
-  case OP_WHITESPACE:
-  case OP_NOT_WORDCHAR:
-  case OP_WORDCHAR:
-  case OP_ANY:
-  case OP_ALLANY:
-  case OP_ANYBYTE:
-  case OP_ANYNL:
-  case OP_NOT_HSPACE:
-  case OP_HSPACE:
-  case OP_NOT_VSPACE:
-  case OP_VSPACE:
-  case OP_CHAR:
-  case OP_CHARI:
-  case OP_NOT:
-  case OP_NOTI:
-  case OP_CLASS:
-  case OP_NCLASS:
-  tmp_base = TMP3;
-  tmp_offset = 0;
-  break;
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+pcre_uchar opcode;
+pcre_uchar type;
+sljit_u32 max = 0, exact;
+BOOL fast_fail;
+sljit_s32 fast_str_ptr;
+BOOL charpos_enabled;
+pcre_uchar charpos_char;
+unsigned int charpos_othercasebit;
+pcre_uchar *end;
+jump_list *no_match = NULL;
+jump_list *no_char1_match = NULL;
+struct sljit_jump *jump = NULL;
+struct sljit_label *label;
+int private_data_ptr = PRIVATE_DATA(cc);
+int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP);
+int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;
+int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);
+int tmp_base, tmp_offset;
 
-  default:
-  SLJIT_ASSERT_STOP();
-  /* Fall through. */
+PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL);
 
-  case OP_EXTUNI:
-  case OP_XCLASS:
-  case OP_NOTPROP:
-  case OP_PROP:
+fast_str_ptr = PRIVATE_DATA(cc + 1);
+fast_fail = TRUE;
+
+SLJIT_ASSERT(common->fast_forward_bc_ptr == NULL || fast_str_ptr == 0 || cc == common->fast_forward_bc_ptr);
+
+if (cc == common->fast_forward_bc_ptr)
+  fast_fail = FALSE;
+else if (common->fast_fail_start_ptr == 0)
+  fast_str_ptr = 0;
+
+SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || fast_str_ptr == 0
+  || (fast_str_ptr >= common->fast_fail_start_ptr && fast_str_ptr <= common->fast_fail_end_ptr));
+
+cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end);
+
+if (type != OP_EXTUNI)
+  {
+  tmp_base = TMP3;
+  tmp_offset = 0;
+  }
+else
+  {
   tmp_base = SLJIT_MEM1(SLJIT_SP);
   tmp_offset = POSSESSIVE0;
-  break;
   }
 
+if (fast_fail && fast_str_ptr != 0)
+  add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), fast_str_ptr));
+
+/* Handle fixed part first. */
+if (exact > 1)
+  {
+  SLJIT_ASSERT(fast_str_ptr == 0);
+  if (common->mode == JIT_COMPILE
+#ifdef SUPPORT_UTF
+      && !common->utf
+#endif
+      )
+    {
+    OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact));
+    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0));
+    OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);
+    label = LABEL();
+    compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+    JUMPTO(SLJIT_NOT_ZERO, label);
+    }
+  else
+    {
+    OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);
+    label = LABEL();
+    compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+    JUMPTO(SLJIT_NOT_ZERO, label);
+    }
+  }
+else if (exact == 1)
+  compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE);
+
 switch(opcode)
   {
   case OP_STAR:
-  case OP_PLUS:
   case OP_UPTO:
-  case OP_CRRANGE:
+  SLJIT_ASSERT(fast_str_ptr == 0 || opcode == OP_STAR);
+
   if (type == OP_ANYNL || type == OP_EXTUNI)
     {
     SLJIT_ASSERT(private_data_ptr == 0);
-    if (opcode == OP_STAR || opcode == OP_UPTO)
-      {
-      allocate_stack(common, 2);
-      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
-      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
-      }
-    else
-      {
-      allocate_stack(common, 1);
-      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
-      }
+    SLJIT_ASSERT(fast_str_ptr == 0);
+
+    allocate_stack(common, 2);
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
 
-    if (opcode == OP_UPTO || opcode == OP_CRRANGE)
-      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, 0);
+    if (opcode == OP_UPTO)
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, max);
 
     label = LABEL();
-    compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
-    if (opcode == OP_UPTO || opcode == OP_CRRANGE)
+    compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE);
+    if (opcode == OP_UPTO)
       {
       OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0);
-      OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
-      if (opcode == OP_CRRANGE && min > 0)
-        CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, label);
-      if (opcode == OP_UPTO || (opcode == OP_CRRANGE && max > 0))
-        jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
+      OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+      jump = JUMP(SLJIT_ZERO);
       OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0);
       }
 
@@ -8006,139 +8894,273 @@ switch(opcode)
     }
   else
     {
-    if (opcode == OP_PLUS)
-      compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
-    if (private_data_ptr == 0)
-      allocate_stack(common, 2);
-    OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
-    if (opcode <= OP_PLUS)
+    charpos_enabled = FALSE;
+    charpos_char = 0;
+    charpos_othercasebit = 0;
+
+    if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))
+      {
+      charpos_enabled = TRUE;
+#ifdef SUPPORT_UTF
+      charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);
+#endif
+      if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1))
+        {
+        charpos_othercasebit = char_get_othercase_bit(common, end + 1);
+        if (charpos_othercasebit == 0)
+          charpos_enabled = FALSE;
+        }
+
+      if (charpos_enabled)
+        {
+        charpos_char = end[1];
+        /* Consumpe the OP_CHAR opcode. */
+        end += 2;
+#if defined COMPILE_PCRE8
+        SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);
+#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+        SLJIT_ASSERT((charpos_othercasebit >> 9) == 0);
+        if ((charpos_othercasebit & 0x100) != 0)
+          charpos_othercasebit = (charpos_othercasebit & 0xff) << 8;
+#endif
+        if (charpos_othercasebit != 0)
+          charpos_char |= charpos_othercasebit;
+
+        BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE;
+        BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char;
+        BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit;
+        }
+      }
+
+    if (charpos_enabled)
+      {
+      if (opcode == OP_UPTO)
+        OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1);
+
+      /* Search the first instance of charpos_char. */
+      jump = JUMP(SLJIT_JUMP);
+      label = LABEL();
+      if (opcode == OP_UPTO)
+        {
+        OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+        add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO));
+        }
+      compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
+      if (fast_str_ptr != 0)
+        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+      JUMPHERE(jump);
+
+      detect_partial_match(common, &backtrack->topbacktracks);
+      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+      if (charpos_othercasebit != 0)
+        OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
+      CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
+
+      if (private_data_ptr == 0)
+        allocate_stack(common, 2);
+      OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
       OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
-    else
-      OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1);
-    label = LABEL();
-    compile_char1_matchingpath(common, type, cc, &nomatch);
-    OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
-    if (opcode <= OP_PLUS)
-      JUMPTO(SLJIT_JUMP, label);
-    else if (opcode == OP_CRRANGE && max == 0)
+      if (opcode == OP_UPTO)
+        {
+        OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+        add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
+        }
+
+      /* Search the last instance of charpos_char. */
+      label = LABEL();
+      compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
+      if (fast_str_ptr != 0)
+        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+      detect_partial_match(common, &no_match);
+      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+      if (charpos_othercasebit != 0)
+        OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
+      if (opcode == OP_STAR)
+        {
+        CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
+        OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+        }
+      else
+        {
+        jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char);
+        OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+        JUMPHERE(jump);
+        }
+
+      if (opcode == OP_UPTO)
+        {
+        OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+        JUMPTO(SLJIT_NOT_ZERO, label);
+        }
+      else
+        JUMPTO(SLJIT_JUMP, label);
+
+      set_jumps(no_match, LABEL());
+      OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+      OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+      OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+      }
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+    else if (common->utf)
       {
-      OP2(SLJIT_ADD, base, offset1, base, offset1, SLJIT_IMM, 1);
-      JUMPTO(SLJIT_JUMP, label);
+      if (private_data_ptr == 0)
+        allocate_stack(common, 2);
+
+      OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+      OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+
+      if (opcode == OP_UPTO)
+        OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+
+      label = LABEL();
+      compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
+      OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+
+      if (opcode == OP_UPTO)
+        {
+        OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+        JUMPTO(SLJIT_NOT_ZERO, label);
+        }
+      else
+        JUMPTO(SLJIT_JUMP, label);
+
+      set_jumps(no_match, LABEL());
+      OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+      if (fast_str_ptr != 0)
+        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
       }
+#endif
     else
       {
-      OP1(SLJIT_MOV, TMP1, 0, base, offset1);
-      OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
-      OP1(SLJIT_MOV, base, offset1, TMP1, 0);
-      CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, max + 1, label);
+      if (private_data_ptr == 0)
+        allocate_stack(common, 2);
+
+      OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+      if (opcode == OP_UPTO)
+        OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+
+      label = LABEL();
+      detect_partial_match(common, &no_match);
+      compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
+      if (opcode == OP_UPTO)
+        {
+        OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+        JUMPTO(SLJIT_NOT_ZERO, label);
+        OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+        }
+      else
+        JUMPTO(SLJIT_JUMP, label);
+
+      set_jumps(no_char1_match, LABEL());
+      OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+      set_jumps(no_match, LABEL());
+      OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+      if (fast_str_ptr != 0)
+        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
       }
-    set_jumps(nomatch, LABEL());
-    if (opcode == OP_CRRANGE)
-      add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS, base, offset1, SLJIT_IMM, min + 1));
-    OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
     }
-  BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+  BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
   break;
 
   case OP_MINSTAR:
-  case OP_MINPLUS:
-  if (opcode == OP_MINPLUS)
-    compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
   if (private_data_ptr == 0)
     allocate_stack(common, 1);
   OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
-  BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+  BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
+  if (fast_str_ptr != 0)
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
   break;
 
   case OP_MINUPTO:
-  case OP_CRMINRANGE:
+  SLJIT_ASSERT(fast_str_ptr == 0);
   if (private_data_ptr == 0)
     allocate_stack(common, 2);
   OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
-  OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1);
-  if (opcode == OP_CRMINRANGE)
-    add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
-  BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+  OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, max + 1);
+  BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
   break;
 
   case OP_QUERY:
   case OP_MINQUERY:
+  SLJIT_ASSERT(fast_str_ptr == 0);
   if (private_data_ptr == 0)
     allocate_stack(common, 1);
   OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
   if (opcode == OP_QUERY)
-    compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
-  BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+    compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE);
+  BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
   break;
 
   case OP_EXACT:
-  OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
-  label = LABEL();
-  compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
-  OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
-  JUMPTO(SLJIT_NOT_ZERO, label);
   break;
 
   case OP_POSSTAR:
-  case OP_POSPLUS:
-  case OP_POSUPTO:
-  if (opcode == OP_POSPLUS)
-    compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
-  if (opcode == OP_POSUPTO)
-    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, SLJIT_IMM, max);
-  OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
-  label = LABEL();
-  compile_char1_matchingpath(common, type, cc, &nomatch);
-  OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
-  if (opcode != OP_POSUPTO)
-    JUMPTO(SLJIT_JUMP, label);
-  else
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+  if (common->utf)
     {
-    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, SLJIT_IMM, 1);
-    JUMPTO(SLJIT_NOT_ZERO, label);
+    OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+    label = LABEL();
+    compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
+    OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+    JUMPTO(SLJIT_JUMP, label);
+    set_jumps(no_match, LABEL());
+    OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
+    if (fast_str_ptr != 0)
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+    break;
     }
-  set_jumps(nomatch, LABEL());
-  OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
-  break;
-
-  case OP_POSQUERY:
-  OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
-  compile_char1_matchingpath(common, type, cc, &nomatch);
-  OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
-  set_jumps(nomatch, LABEL());
-  OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
+#endif
+  label = LABEL();
+  detect_partial_match(common, &no_match);
+  compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
+  JUMPTO(SLJIT_JUMP, label);
+  set_jumps(no_char1_match, LABEL());
+  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+  set_jumps(no_match, LABEL());
+  if (fast_str_ptr != 0)
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
   break;
 
-  case OP_CRPOSRANGE:
-  /* Combination of OP_EXACT and OP_POSSTAR or OP_POSUPTO */
-  OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, min);
+  case OP_POSUPTO:
+  SLJIT_ASSERT(fast_str_ptr == 0);
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+  if (common->utf)
+    {
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
+    OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+    label = LABEL();
+    compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
+    OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+    JUMPTO(SLJIT_NOT_ZERO, label);
+    set_jumps(no_match, LABEL());
+    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);
+    break;
+    }
+#endif
+  OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
   label = LABEL();
-  compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
-  OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+  detect_partial_match(common, &no_match);
+  compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
   JUMPTO(SLJIT_NOT_ZERO, label);
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+  set_jumps(no_char1_match, LABEL());
+  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+  set_jumps(no_match, LABEL());
+  break;
 
-  if (max != 0)
-    {
-    SLJIT_ASSERT(max - min > 0);
-    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, SLJIT_IMM, max - min);
-    }
+  case OP_POSQUERY:
+  SLJIT_ASSERT(fast_str_ptr == 0);
   OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
-  label = LABEL();
-  compile_char1_matchingpath(common, type, cc, &nomatch);
+  compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
   OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
-  if (max == 0)
-    JUMPTO(SLJIT_JUMP, label);
-  else
-    {
-    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, SLJIT_IMM, 1);
-    JUMPTO(SLJIT_NOT_ZERO, label);
-    }
-  set_jumps(nomatch, LABEL());
+  set_jumps(no_match, LABEL());
   OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
   break;
 
   default:
-  SLJIT_ASSERT_STOP();
+  SLJIT_UNREACHABLE();
   break;
   }
 
@@ -8174,9 +9196,9 @@ if (common->accept_label == NULL)
 else
   CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label);
 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
+OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
 add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
-OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
+OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
 if (common->accept_label == NULL)
   add_jump(compiler, &common->accept, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
 else
@@ -8260,7 +9282,7 @@ size = 3 + (size < 0 ? 0 : size);
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
 allocate_stack(common, size);
 if (size > 3)
-  OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw));
+  OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw));
 else
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0);
 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start);
@@ -8298,6 +9320,16 @@ while (cc < ccend)
     case OP_SOM:
     case OP_NOT_WORD_BOUNDARY:
     case OP_WORD_BOUNDARY:
+    case OP_EODN:
+    case OP_EOD:
+    case OP_DOLL:
+    case OP_DOLLM:
+    case OP_CIRC:
+    case OP_CIRCM:
+    case OP_REVERSE:
+    cc = compile_simple_assertion_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+    break;
+
     case OP_NOT_DIGIT:
     case OP_DIGIT:
     case OP_NOT_WHITESPACE:
@@ -8315,16 +9347,9 @@ while (cc < ccend)
     case OP_NOT_VSPACE:
     case OP_VSPACE:
     case OP_EXTUNI:
-    case OP_EODN:
-    case OP_EOD:
-    case OP_CIRC:
-    case OP_CIRCM:
-    case OP_DOLL:
-    case OP_DOLLM:
     case OP_NOT:
     case OP_NOTI:
-    case OP_REVERSE:
-    cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+    cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
     break;
 
     case OP_SET_SOM:
@@ -8341,7 +9366,7 @@ while (cc < ccend)
     if (common->mode == JIT_COMPILE)
       cc = compile_charn_matchingpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
     else
-      cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+      cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
     break;
 
     case OP_STAR:
@@ -8417,7 +9442,7 @@ while (cc < ccend)
     if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRPOSRANGE)
       cc = compile_iterator_matchingpath(common, cc, parent);
     else
-      cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+      cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
     break;
 
 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
@@ -8425,7 +9450,7 @@ while (cc < ccend)
     if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRPOSRANGE)
       cc = compile_iterator_matchingpath(common, cc, parent);
     else
-      cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+      cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
     break;
 #endif
 
@@ -8562,7 +9587,7 @@ while (cc < ccend)
     break;
 
     default:
-    SLJIT_ASSERT_STOP();
+    SLJIT_UNREACHABLE();
     return;
     }
   if (cc == NULL)
@@ -8601,95 +9626,82 @@ DEFINE_COMPILER;
 pcre_uchar *cc = current->cc;
 pcre_uchar opcode;
 pcre_uchar type;
-int max = -1, min = -1;
+sljit_u32 max = 0, exact;
 struct sljit_label *label = NULL;
 struct sljit_jump *jump = NULL;
 jump_list *jumplist = NULL;
+pcre_uchar *end;
 int private_data_ptr = PRIVATE_DATA(cc);
 int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP);
 int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;
 int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);
 
-cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &min, NULL);
+cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end);
 
 switch(opcode)
   {
   case OP_STAR:
-  case OP_PLUS:
   case OP_UPTO:
-  case OP_CRRANGE:
   if (type == OP_ANYNL || type == OP_EXTUNI)
     {
     SLJIT_ASSERT(private_data_ptr == 0);
-    set_jumps(current->topbacktracks, LABEL());
+    set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL());
     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
     free_stack(common, 1);
-    CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);
+    CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath);
     }
   else
     {
-    if (opcode == OP_UPTO)
-      min = 0;
-    if (opcode <= OP_PLUS)
+    if (CURRENT_AS(char_iterator_backtrack)->u.charpos.enabled)
       {
       OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
-      jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1);
+      OP1(SLJIT_MOV, TMP2, 0, base, offset1);
+      OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+      jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
+      label = LABEL();
+      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
+      OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+      if (CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit != 0)
+        OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit);
+      CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.chr, CURRENT_AS(char_iterator_backtrack)->matchingpath);
+      skip_char_back(common);
+      CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP2, 0, label);
       }
     else
       {
-      OP1(SLJIT_MOV, TMP1, 0, base, offset1);
       OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
-      jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, SLJIT_IMM, min + 1);
-      OP2(SLJIT_SUB, base, offset1, TMP1, 0, SLJIT_IMM, 1);
+      jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1);
+      skip_char_back(common);
+      OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+      JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
       }
-    skip_char_back(common);
-    OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
-    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
-    if (opcode == OP_CRRANGE)
-      set_jumps(current->topbacktracks, LABEL());
     JUMPHERE(jump);
     if (private_data_ptr == 0)
       free_stack(common, 2);
-    if (opcode == OP_PLUS)
-      set_jumps(current->topbacktracks, LABEL());
     }
   break;
 
   case OP_MINSTAR:
-  case OP_MINPLUS:
   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
-  compile_char1_matchingpath(common, type, cc, &jumplist);
+  compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);
   OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
-  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
+  JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
   set_jumps(jumplist, LABEL());
   if (private_data_ptr == 0)
     free_stack(common, 1);
-  if (opcode == OP_MINPLUS)
-    set_jumps(current->topbacktracks, LABEL());
   break;
 
   case OP_MINUPTO:
-  case OP_CRMINRANGE:
-  if (opcode == OP_CRMINRANGE)
-    {
-    label = LABEL();
-    set_jumps(current->topbacktracks, label);
-    }
+  OP1(SLJIT_MOV, TMP1, 0, base, offset1);
   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
-  compile_char1_matchingpath(common, type, cc, &jumplist);
+  OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+  add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO));
 
-  OP1(SLJIT_MOV, TMP1, 0, base, offset1);
-  OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
-  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
   OP1(SLJIT_MOV, base, offset1, TMP1, 0);
-
-  if (opcode == OP_CRMINRANGE)
-    CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min + 1, label);
-
-  if (opcode == OP_CRMINRANGE && max == 0)
-    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
-  else
-    CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, max + 2, CURRENT_AS(iterator_backtrack)->matchingpath);
+  compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);
+  OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+  JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
 
   set_jumps(jumplist, LABEL());
   if (private_data_ptr == 0)
@@ -8699,12 +9711,12 @@ switch(opcode)
   case OP_QUERY:
   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
   OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
-  CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);
+  CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath);
   jump = JUMP(SLJIT_JUMP);
-  set_jumps(current->topbacktracks, LABEL());
+  set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL());
   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
   OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
-  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
+  JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
   JUMPHERE(jump);
   if (private_data_ptr == 0)
     free_stack(common, 1);
@@ -8714,8 +9726,8 @@ switch(opcode)
   OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
   OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
   jump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
-  compile_char1_matchingpath(common, type, cc, &jumplist);
-  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
+  compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);
+  JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
   set_jumps(jumplist, LABEL());
   JUMPHERE(jump);
   if (private_data_ptr == 0)
@@ -8723,20 +9735,17 @@ switch(opcode)
   break;
 
   case OP_EXACT:
-  case OP_POSPLUS:
-  case OP_CRPOSRANGE:
-  set_jumps(current->topbacktracks, LABEL());
-  break;
-
   case OP_POSSTAR:
   case OP_POSQUERY:
   case OP_POSUPTO:
   break;
 
   default:
-  SLJIT_ASSERT_STOP();
+  SLJIT_UNREACHABLE();
   break;
   }
+
+set_jumps(current->topbacktracks, LABEL());
 }
 
 static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)
@@ -8754,12 +9763,12 @@ if ((type & 0x1) == 0)
   set_jumps(current->topbacktracks, LABEL());
   OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
   free_stack(common, 1);
-  CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);
+  CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath);
   return;
   }
 
 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
-CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);
+CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath);
 set_jumps(current->topbacktracks, LABEL());
 free_stack(common, ref ? 2 : 3);
 }
@@ -8840,7 +9849,7 @@ if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)
   {
   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr);
   add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
-  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_sw));
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(assert_backtrack)->framesize - 1));
 
   set_jumps(current->topbacktracks, LABEL());
   }
@@ -8850,7 +9859,7 @@ else
 if (bra == OP_BRAZERO)
   {
   /* We know there is enough place on the stack. */
-  OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+  OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
   OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
   JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->matchingpath);
   JUMPHERE(brajump);
@@ -8963,7 +9972,7 @@ else if (ket == OP_KETRMIN)
       else
         {
         OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
-        CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
+        CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 2), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
         }
       /* Drop STR_PTR for non-greedy plus quantifier. */
       if (opcode != OP_ONCE)
@@ -9069,7 +10078,7 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
       {
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr);
       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
-      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw));
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-assert->framesize - 1));
       }
     cond = JUMP(SLJIT_JUMP);
     set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());
@@ -9210,7 +10219,7 @@ if (has_alternatives)
       {
       OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr);
       add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
-      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw));
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-assert->framesize - 1));
       }
     JUMPHERE(cond);
     }
@@ -9258,12 +10267,14 @@ else if (opcode == OP_ONCE)
     /* The STR_PTR must be released. */
     stacksize++;
     }
-  free_stack(common, stacksize);
+
+  if (stacksize > 0)
+    free_stack(common, stacksize);
 
   JUMPHERE(once);
   /* Restore previous private_data_ptr */
   if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
-    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_sw));
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 1));
   else if (ket == OP_KETRMIN)
     {
     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
@@ -9353,7 +10364,7 @@ if (current->topbacktracks)
   free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
   JUMPHERE(jump);
   }
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_sw));
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracketpos_backtrack)->framesize - 1));
 }
 
 static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current)
@@ -9399,10 +10410,10 @@ if (opcode == OP_THEN || opcode == OP_THEN_ARG)
     jump = JUMP(SLJIT_JUMP);
 
     loop = LABEL();
-    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw));
+    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
     JUMPHERE(jump);
-    CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop);
-    CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop);
+    CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0, loop);
+    CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0, loop);
     add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));
     return;
     }
@@ -9652,7 +10663,7 @@ while (current)
     break;
 
     default:
-    SLJIT_ASSERT_STOP();
+    SLJIT_UNREACHABLE();
     break;
     }
   current = current->prev;
@@ -9688,10 +10699,10 @@ common->currententry->entry = LABEL();
 set_jumps(common->currententry->calls, common->currententry->entry);
 
 sljit_emit_fast_enter(compiler, TMP2, 0);
-allocate_stack(common, private_data_size + framesize + alternativesize);
 count_match(common);
+allocate_stack(common, private_data_size + framesize + alternativesize);
 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0);
-copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head);
+copy_private_data(common, ccbegin, ccend, TRUE, framesize + alternativesize, private_data_size + framesize + alternativesize, needs_control_head);
 if (needs_control_head)
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0);
@@ -9744,9 +10755,9 @@ if (common->quit != NULL)
   OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
   if (needs_frame)
     {
-    OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
-    add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
+    add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+    OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
     }
   OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
   common->quit = NULL;
@@ -9757,32 +10768,32 @@ set_jumps(common->accept, LABEL());
 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
 if (needs_frame)
   {
-  OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
-  add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
   OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
+  add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+  OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
   }
 OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);
 
 JUMPHERE(jump);
 if (common->quit != NULL)
   set_jumps(common->quit, LABEL());
-copy_private_data(common, ccbegin, ccend, FALSE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head);
+copy_private_data(common, ccbegin, ccend, FALSE, framesize + alternativesize, private_data_size + framesize + alternativesize, needs_control_head);
 free_stack(common, private_data_size + framesize + alternativesize);
 if (needs_control_head)
   {
-  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 2 * sizeof(sljit_sw));
-  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw));
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-3));
+  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP1, 0);
   OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0);
   }
 else
   {
-  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw));
+  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));
   OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP2, 0);
   }
-sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);
+sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), STACK(-1));
 }
 
 #undef COMPILE_BACKTRACKINGPATH
@@ -9795,7 +10806,7 @@ struct sljit_compiler *compiler;
 backtrack_common rootbacktrack;
 compiler_common common_data;
 compiler_common *common = &common_data;
-const pcre_uint8 *tables = re->tables;
+const sljit_u8 *tables = re->tables;
 pcre_study_data *study;
 int private_data_size;
 pcre_uchar *ccend;
@@ -9907,7 +10918,7 @@ ccend = bracketend(common->start);
 
 /* Calculate the local space size on the stack. */
 common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw);
-common->optimized_cbracket = (pcre_uint8 *)SLJIT_MALLOC(re->top_bracket + 1, compiler->allocator_data);
+common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, compiler->allocator_data);
 if (!common->optimized_cbracket)
   return;
 #if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1
@@ -9942,15 +10953,10 @@ if (mode != JIT_COMPILE)
     common->hit_start = common->ovector_start;
     common->ovector_start += 2 * sizeof(sljit_sw);
     }
-  else
-    {
-    SLJIT_ASSERT(mode == JIT_PARTIAL_HARD_COMPILE);
-    common->needs_start_ptr = TRUE;
-    }
   }
 if ((re->options & PCRE_FIRSTLINE) != 0)
   {
-  common->first_line_end = common->ovector_start;
+  common->match_end_ptr = common->ovector_start;
   common->ovector_start += sizeof(sljit_sw);
   }
 #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
@@ -9961,14 +10967,12 @@ if (common->control_head_ptr != 0)
   common->control_head_ptr = common->ovector_start;
   common->ovector_start += sizeof(sljit_sw);
   }
-if (common->needs_start_ptr && common->has_set_som)
+if (common->has_set_som)
   {
   /* Saving the real start pointer is necessary. */
   common->start_ptr = common->ovector_start;
   common->ovector_start += sizeof(sljit_sw);
   }
-else
-  common->needs_start_ptr = FALSE;
 
 /* Aligning ovector to even number of sljit words. */
 if ((common->ovector_start & sizeof(sljit_sw)) != 0)
@@ -9985,16 +10989,24 @@ SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
 common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);
 
 total_length = ccend - common->start;
-common->private_data_ptrs = (sljit_si *)SLJIT_MALLOC(total_length * (sizeof(sljit_si) + (common->has_then ? 1 : 0)), compiler->allocator_data);
+common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), compiler->allocator_data);
 if (!common->private_data_ptrs)
   {
   SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
   return;
   }
-memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_si));
+memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32));
 
 private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);
 set_private_data_ptrs(common, &private_data_size, ccend);
+if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
+  {
+  if (!detect_fast_forward_skip(common, &private_data_size) && !common->has_skip_in_assert_back)
+    detect_fast_fail(common, common->start, &private_data_size, 4);
+  }
+
+SLJIT_ASSERT(common->fast_fail_start_ptr <= common->fast_fail_end_ptr);
+
 if (private_data_size > SLJIT_MAX_LOCAL_SIZE)
   {
   SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
@@ -10004,7 +11016,7 @@ if (private_data_size > SLJIT_MAX_LOCAL_SIZE)
 
 if (common->has_then)
   {
-  common->then_offsets = (pcre_uint8 *)(common->private_data_ptrs + total_length);
+  common->then_offsets = (sljit_u8 *)(common->private_data_ptrs + total_length);
   memset(common->then_offsets, 0, total_length);
   set_then_offsets(common, common->start, NULL);
   }
@@ -10031,12 +11043,15 @@ OP1(SLJIT_MOV, TMP1, 0, SLJIT_S0, 0);
 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
-OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));
+OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));
 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
 OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);
 
+if (common->fast_fail_start_ptr < common->fast_fail_end_ptr)
+  reset_fast_fail(common);
+
 if (mode == JIT_PARTIAL_SOFT_COMPILE)
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);
 if (common->mark_ptr != 0)
@@ -10047,19 +11062,19 @@ if (common->control_head_ptr != 0)
 /* Main part of the matching */
 if ((re->options & PCRE_ANCHORED) == 0)
   {
-  mainloop_label = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0);
+  mainloop_label = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0);
   continue_match_label = LABEL();
   /* Forward search if possible. */
   if ((re->options & PCRE_NO_START_OPTIMIZE) == 0)
     {
-    if (mode == JIT_COMPILE && fast_forward_first_n_chars(common, (re->options & PCRE_FIRSTLINE) != 0))
+    if (mode == JIT_COMPILE && fast_forward_first_n_chars(common))
       ;
     else if ((re->flags & PCRE_FIRSTSET) != 0)
-      fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0);
+      fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0);
     else if ((re->flags & PCRE_STARTLINE) != 0)
-      fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);
+      fast_forward_newline(common);
     else if (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
-      fast_forward_start_bits(common, study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
+      fast_forward_start_bits(common, study->start_bits);
     }
   }
 else
@@ -10080,14 +11095,11 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);
 OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH);
 if (common->capture_last_ptr != 0)
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, -1);
+if (common->fast_forward_bc_ptr != NULL)
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1), STR_PTR, 0);
 
-if (common->needs_start_ptr)
-  {
-  SLJIT_ASSERT(common->start_ptr != OVECTOR(0));
+if (common->start_ptr != OVECTOR(0))
   OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0);
-  }
-else
-  SLJIT_ASSERT(common->start_ptr == OVECTOR(0));
 
 /* Copy the beginning of the string. */
 if (mode == JIT_PARTIAL_SOFT_COMPILE)
@@ -10166,11 +11178,12 @@ if (mode == JIT_PARTIAL_SOFT_COMPILE)
 /* Check we have remaining characters. */
 if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_FIRSTLINE) != 0)
   {
-  SLJIT_ASSERT(common->first_line_end != 0);
-  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->first_line_end);
+  SLJIT_ASSERT(common->match_end_ptr != 0);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
   }
 
-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP),
+    (common->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1)) : common->start_ptr);
 
 if ((re->options & PCRE_ANCHORED) == 0)
   {
@@ -10181,12 +11194,7 @@ if ((re->options & PCRE_ANCHORED) == 0)
     /* There cannot be more newlines here. */
     }
   else
-    {
-    if ((re->options & PCRE_FIRSTLINE) == 0)
-      CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, mainloop_label);
-    else
-      CMPTO(SLJIT_LESS, STR_PTR, 0, TMP1, 0, mainloop_label);
-    }
+    CMPTO(SLJIT_LESS, STR_PTR, 0, ((re->options & PCRE_FIRSTLINE) == 0) ? STR_END : TMP1, 0, mainloop_label);
   }
 
 /* No more remaining characters. */
@@ -10205,15 +11213,18 @@ if (common->might_be_empty)
   {
   JUMPHERE(empty_match);
   OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
   CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label);
-  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
+  OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
   CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label);
   OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
   CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label);
   JUMPTO(SLJIT_JUMP, empty_match_backtrack_label);
   }
 
+common->fast_forward_bc_ptr = NULL;
+common->fast_fail_start_ptr = 0;
+common->fast_fail_end_ptr = 0;
 common->currententry = common->entries;
 common->local_exit = TRUE;
 quit_label = common->quit_label;
@@ -10244,7 +11255,7 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0);
 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
 OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0);
-OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
+OP2(SLJIT_SUB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
 
 sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
 jump = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
@@ -10395,13 +11406,13 @@ union {
    void *executable_func;
    jit_function call_executable_func;
 } convert_executable_func;
-pcre_uint8 local_space[MACHINE_STACK_SIZE];
+sljit_u8 local_space[MACHINE_STACK_SIZE];
 struct sljit_stack local_stack;
 
-local_stack.top = (sljit_sw)&local_space;
-local_stack.base = local_stack.top;
-local_stack.limit = local_stack.base + MACHINE_STACK_SIZE;
-local_stack.max_limit = local_stack.limit;
+local_stack.max_limit = local_space;
+local_stack.limit = local_space;
+local_stack.base = local_space + MACHINE_STACK_SIZE;
+local_stack.top = local_space + MACHINE_STACK_SIZE;
 arguments->stack = &local_stack;
 convert_executable_func.executable_func = executable_func;
 return convert_executable_func.call_executable_func(arguments);
@@ -10435,7 +11446,7 @@ arguments.begin = subject;
 arguments.end = subject + length;
 arguments.mark_ptr = NULL;
 /* JIT decreases this value less frequently than the interpreter. */
-arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (pcre_uint32)(extra_data->match_limit);
+arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit);
 if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
   arguments.limit_match = functions->limit_match;
 arguments.notbol = (options & PCRE_NOTBOL) != 0;
@@ -10528,7 +11539,7 @@ arguments.begin = subject_ptr;
 arguments.end = subject_ptr + length;
 arguments.mark_ptr = NULL;
 /* JIT decreases this value less frequently than the interpreter. */
-arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (pcre_uint32)(extra_data->match_limit);
+arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit);
 if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
   arguments.limit_match = functions->limit_match;
 arguments.notbol = (options & PCRE_NOTBOL) != 0;
index 209cae9024115cdee36808e44450ed7823f2b709..a44a6eaa905b71567c8845c85185165d7e165907 100644 (file)
@@ -45,7 +45,9 @@ compilation of dftables.c, in which case the macro DFTABLES is defined. */
 
 
 #ifndef DFTABLES
+#  ifdef HAVE_CONFIG_H
 #  include "config.h"
+#  endif
 #  include "pcre_internal.h"
 #endif
 
index 405b91337592c0b3366308396b9effe3e92d9362..b8f5a4de19c8663f2cf40f39e1eb71de9eb1e2f3 100644 (file)
@@ -47,7 +47,9 @@ and NLTYPE_ANY. The full list of Unicode newline characters is taken from
 http://unicode.org/unicode/reports/tr18/. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
index ba3718612fb0e32c7de8b0053e00dd324deb4e56..95f1beb963e46b65ab6118144aded7339df70963 100644 (file)
@@ -41,7 +41,9 @@ POSSIBILITY OF SUCH DAMAGE.
 /* This file contains a private PCRE function that converts an ordinal
 character value into a UTF8 string. */
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #define COMPILE_PCRE8
 
index 8cbb1613958140a4a0fd4d96063e3aa25714bc91..60dcb55efbfe262235ba65067c7404b23c365466 100644 (file)
@@ -51,7 +51,9 @@ asked to print out a compiled regex for debugging purposes. */
 
 #ifndef PCRE_INCLUDED
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 /* For pcretest program. */
 #define PRIV(name) name
index d5e0b61c417c6286b317af8c222d6817251b806b..79efa90f216c5d86475f68687bb0141e75893a97 100644 (file)
@@ -44,7 +44,9 @@ pattern data block. This might be helpful in applications where the block is
 shared by different users. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
index 38ab820853f9c24bdeb6cc319dac31c190a046c0..d9d4960d84ecbac0ad16228cf56bf6d40a4b6cbc 100644 (file)
@@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
 supporting functions. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
@@ -1369,7 +1371,7 @@ do
             for (c = 0; c < 16; c++) start_bits[c] |= map[c];
             for (c = 128; c < 256; c++)
               {
-              if ((map[c/8] && (1 << (c&7))) != 0)
+              if ((map[c/8] & (1 << (c&7))) != 0)
                 {
                 int d = (c >> 6) | 0xc0;            /* Set bit for this starter */
                 start_bits[d/8] |= (1 << (d&7));    /* and then skip on to the */
index 93ea6ad160ed00a82e4f66dd913d5913e8010d63..5e18e8cf904b388a64e231bddcdc14efc2aa4a2a 100644 (file)
@@ -6,7 +6,7 @@
 and semantics are as close as possible to those of the Perl 5 language.
 
                        Written by Philip Hazel
-           Copyright (c) 1997-2012 University of Cambridge
+           Copyright (c) 1997-2017 University of Cambridge
 
 -----------------------------------------------------------------------------
 Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,9 @@ uses macros to change their names from _pcre_xxx to xxxx, thereby avoiding name
 clashes with the library. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
@@ -159,7 +161,7 @@ const pcre_uint32 PRIV(ucp_gbtable[]) = {
 
    (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark),                /*  5 SpacingMark */
    (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbL)|   /*  6 L */
-     (1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbLV)|(1<<ucp_gbLVT),
+     (1<<ucp_gbV)|(1<<ucp_gbLV)|(1<<ucp_gbLVT),
 
    (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)|   /*  7 V */
      (1<<ucp_gbT),
index d6449076750609d281b06ba6c26e39f1e8271145..f22f826c4c245106b13114f81277cc4324fdb62a 100644 (file)
@@ -10,7 +10,9 @@ needed. */
 
 #ifndef PCRE_INCLUDED
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
@@ -36,6 +38,20 @@ const pcre_uint16 PRIV(ucd_stage2)[] = {0};
 const pcre_uint32 PRIV(ucd_caseless_sets)[] = {0};
 #else
 
+/* If the 32-bit library is run in non-32-bit mode, character values
+greater than 0x10ffff may be encountered. For these we set up a
+special record. */
+
+#ifdef COMPILE_PCRE32
+const ucd_record PRIV(dummy_ucd_record)[] = {{
+  ucp_Common,    /* script */
+  ucp_Cn,        /* type unassigned */
+  ucp_gbOther,   /* grapheme break property */
+  0,             /* case set */
+  0,             /* other case */
+  }};
+#endif
+
 /* When recompiling tables with a new Unicode version, please check the
 types in this structure definition from pcre_internal.h (the actual
 field names will be different):
index 3a9fba785c7ed232827a967478539ea5009a0040..3b0f6464a359a64db422ef7bff5ed74051bcbda5 100644 (file)
@@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
 strings. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
index 00b8dd680c2f7b452279f3debb540aa75d9da03d..ae86ff28bc8f5859540a212c695a244c5f0e7f65 100644 (file)
@@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
 string that identifies the PCRE version that is in use. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
index 782748f2411c7af541b30d1a36b62c52b50f39d1..ef759a589a621de89aeef30a09c10b94452bbac1 100644 (file)
@@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
 class. It is used by both pcre_exec() and pcre_def_exec(). */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "pcre_internal.h"
 
index 8e0d8bb609050733cbf0d4f1ba756bcc8eb48ad4..7b404a711001a0f69060da86ca5915385d76023c 100644 (file)
@@ -6,7 +6,7 @@
 and semantics are as close as possible to those of the Perl 5 language.
 
                        Written by Philip Hazel
-           Copyright (c) 1997-2014 University of Cambridge
+           Copyright (c) 1997-2017 University of Cambridge
 
 -----------------------------------------------------------------------------
 Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
 functions. */
 
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 
 /* Ensure that the PCREPOSIX_EXP_xxx macros are set appropriately for
@@ -171,7 +173,8 @@ static const int eint[] = {
   REG_BADPAT,  /* group name must start with a non-digit */
   /* 85 */
   REG_BADPAT,  /* parentheses too deeply nested (stack check) */
-  REG_BADPAT   /* missing digits in \x{} or \o{} */
+  REG_BADPAT,  /* missing digits in \x{} or \o{} */
+  REG_BADPAT   /* pattern too complicated */
 };
 
 /* Table of texts corresponding to POSIX error codes */
@@ -362,6 +365,7 @@ start location rather than being passed as a PCRE "starting offset". */
 
 if ((eflags & REG_STARTEND) != 0)
   {
+  if (pmatch == NULL) return REG_INVARG;
   so = pmatch[0].rm_so;
   eo = pmatch[0].rm_eo;
   }
@@ -385,8 +389,8 @@ if (rc >= 0)
     {
     for (i = 0; i < (size_t)rc; i++)
       {
-      pmatch[i].rm_so = ovector[i*2];
-      pmatch[i].rm_eo = ovector[i*2+1];
+      pmatch[i].rm_so = ovector[i*2] + so;
+      pmatch[i].rm_eo = ovector[i*2+1] + so;
       }
     if (allocated_ovector) free(ovector);
     for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1;
index 1c8a521aa890d2ddb360df81ee87c69e913b5d57..b65584a4afdf9265dff1ac2060b69d2e9122fb94 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -82,7 +82,7 @@
 /* --------------------------------------------------------------------- */
 
 /* If SLJIT_STD_MACROS_DEFINED is not defined, the application should
-   define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMMOVE, and NULL. */
+   define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */
 #ifndef SLJIT_STD_MACROS_DEFINED
 /* Disabled by default. */
 #define SLJIT_STD_MACROS_DEFINED 0
 
 /* Executable code allocation:
    If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
-   define both SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC. */
+   define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_EXEC_OFFSET. */
 #ifndef SLJIT_EXECUTABLE_ALLOCATOR
 /* Enabled by default. */
 #define SLJIT_EXECUTABLE_ALLOCATOR 1
+
+/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses
+   an allocator which does not set writable and executable
+   permission flags at the same time. The trade-of is increased
+   memory consumption and disabled dynamic code modifications. */
+#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR
+/* Disabled by default. */
+#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0
+#endif
+
 #endif
 
 /* Force cdecl calling convention even if a better calling
index 16e3547c938f046455116a469d6ab7a6fcfb80c1..cc0810fbd7a560a1b50534c285ab37f32cc0c7f4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
    SLJIT defines the following architecture dependent types and macros:
 
    Types:
-     sljit_sb, sljit_ub : signed and unsigned 8 bit byte
-     sljit_sh, sljit_uh : signed and unsigned 16 bit half-word (short) type
-     sljit_si, sljit_ui : signed and unsigned 32 bit integer type
-     sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
-     sljit_p : unsgined pointer value (usually the same as sljit_uw, but
-               some 64 bit ABIs may use 32 bit pointers)
-     sljit_s : single precision floating point value
-     sljit_d : double precision floating point value
+     sljit_s8, sljit_u8   : signed and unsigned 8 bit integer type
+     sljit_s16, sljit_u16 : signed and unsigned 16 bit integer type
+     sljit_s32, sljit_u32 : signed and unsigned 32 bit integer type
+     sljit_sw, sljit_uw   : signed and unsigned machine word, enough to store a pointer
+     sljit_p              : unsgined pointer value (usually the same as sljit_uw, but
+                            some 64 bit ABIs may use 32 bit pointers)
+     sljit_f32            : 32 bit single precision floating point value
+     sljit_f64            : 64 bit double precision floating point value
 
    Macros for feature detection (boolean):
      SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
      SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available floating point scratch registers
      SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available floating point saved registers
      SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
-     SLJIT_DOUBLE_SHIFT : the shift required to apply when accessing
-                          a double precision floating point array by index
-     SLJIT_SINGLE_SHIFT : the shift required to apply when accessing
-                          a single precision floating point array by index
+     SLJIT_F32_SHIFT : the shift required to apply when accessing
+                       a single precision floating point array by index
+     SLJIT_F64_SHIFT : the shift required to apply when accessing
+                       a double precision floating point array by index
      SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET)
      SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
 
 /* External function definitions. */
 /**********************************/
 
-#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
-
-/* These libraries are needed for the macros below. */
-#include <stdlib.h>
-#include <string.h>
-
-#endif /* SLJIT_STD_MACROS_DEFINED */
-
 /* General macros:
    Note: SLJIT is designed to be independent from them as possible.
 
 #define SLJIT_FREE(ptr, allocator_data) free(ptr)
 #endif
 
-#ifndef SLJIT_MEMMOVE
-#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)
+#ifndef SLJIT_MEMCPY
+#define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len)
 #endif
 
 #ifndef SLJIT_ZEROMEM
 #endif
 #endif /* !SLJIT_INLINE */
 
-#ifndef SLJIT_CONST
-/* Const variables. */
-#define SLJIT_CONST const
-#endif
-
 #ifndef SLJIT_UNUSED_ARG
 /* Unused arguments. */
 #define SLJIT_UNUSED_ARG(arg) (void)arg
 /* Instruction cache flush. */
 /****************************/
 
+#if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin)
+#if __has_builtin(__builtin___clear_cache)
+
+#define SLJIT_CACHE_FLUSH(from, to) \
+       __builtin___clear_cache((char*)from, (char*)to)
+
+#endif /* __has_builtin(__builtin___clear_cache) */
+#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */
+
 #ifndef SLJIT_CACHE_FLUSH
 
 #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
 #define SLJIT_CACHE_FLUSH(from, to) \
        sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from))
 
-#elif defined __ANDROID__
+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
 
-/* Android lacks __clear_cache; instead, cacheflush should be used. */
+/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
+#define SLJIT_CACHE_FLUSH(from, to) \
+       ppc_cache_flush((from), (to))
+#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
+
+#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
 
 #define SLJIT_CACHE_FLUSH(from, to) \
-    cacheflush((long)(from), (long)(to), 0)
+       __builtin___clear_cache((char*)from, (char*)to)
 
-#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+#elif defined __ANDROID__
+
+/* Android lacks __clear_cache; instead, cacheflush should be used. */
 
-/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
 #define SLJIT_CACHE_FLUSH(from, to) \
-       ppc_cache_flush((from), (to))
+    cacheflush((long)(from), (long)(to), 0)
 
 #elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
 
 /* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
 #define SLJIT_CACHE_FLUSH(from, to) \
        sparc_cache_flush((from), (to))
+#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
 
 #else
 
 #endif /* !SLJIT_CACHE_FLUSH */
 
 /******************************************************/
-/* Byte/half/int/word/single/double type definitions. */
+/*    Integer and floating point type definitions.    */
 /******************************************************/
 
 /* 8 bit byte type. */
-typedef unsigned char sljit_ub;
-typedef signed char sljit_sb;
+typedef unsigned char sljit_u8;
+typedef signed char sljit_s8;
 
 /* 16 bit half-word type. */
-typedef unsigned short int sljit_uh;
-typedef signed short int sljit_sh;
+typedef unsigned short int sljit_u16;
+typedef signed short int sljit_s16;
 
 /* 32 bit integer type. */
-typedef unsigned int sljit_ui;
-typedef signed int sljit_si;
+typedef unsigned int sljit_u32;
+typedef signed int sljit_s32;
 
 /* Machine word type. Enough for storing a pointer.
      32 bit for 32 bit machines.
@@ -377,20 +380,22 @@ typedef long int sljit_sw;
 typedef sljit_uw sljit_p;
 
 /* Floating point types. */
-typedef float sljit_s;
-typedef double sljit_d;
+typedef float sljit_f32;
+typedef double sljit_f64;
 
 /* Shift for pointer sized data. */
 #define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT
 
 /* Shift for double precision sized data. */
-#define SLJIT_DOUBLE_SHIFT 3
-#define SLJIT_SINGLE_SHIFT 2
+#define SLJIT_F32_SHIFT 2
+#define SLJIT_F64_SHIFT 3
 
 #ifndef SLJIT_W
 
 /* Defining long constants. */
-#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+#define SLJIT_W(w)     (w##l)
+#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
 #define SLJIT_W(w)     (w##ll)
 #else
 #define SLJIT_W(w)     (w)
@@ -534,6 +539,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
 #define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size)
 #define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
+
+#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
+#define SLJIT_EXEC_OFFSET(ptr) sljit_exec_offset(ptr)
+#else
+#define SLJIT_EXEC_OFFSET(ptr) 0
+#endif
+
 #endif
 
 /**********************************************/
@@ -542,37 +555,37 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
 
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
 
-#define SLJIT_NUMBER_OF_REGISTERS 10
-#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
+#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9
 #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
-#define SLJIT_LOCALS_OFFSET_BASE ((2 + 4) * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
 #else
 /* Maximum 3 arguments are passed on the stack, +1 for double alignment. */
-#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1 + 4) * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
 #endif /* SLJIT_X86_32_FASTCALL */
 
 #elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
 
 #ifndef _WIN64
-#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_REGISTERS 13
 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
-#define SLJIT_LOCALS_OFFSET_BASE (sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE 0
 #else
-#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_REGISTERS 13
 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
-#define SLJIT_LOCALS_OFFSET_BASE ((4 + 2) * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
 #endif /* _WIN64 */
 
 #elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
 
-#define SLJIT_NUMBER_OF_REGISTERS 11
+#define SLJIT_NUMBER_OF_REGISTERS 12
 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
 #define SLJIT_LOCALS_OFFSET_BASE 0
 
 #elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
 
-#define SLJIT_NUMBER_OF_REGISTERS 11
-#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
+#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
 #define SLJIT_LOCALS_OFFSET_BASE 0
 
 #elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
@@ -596,7 +609,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
 
 #elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
 
-#define SLJIT_NUMBER_OF_REGISTERS 17
+#define SLJIT_NUMBER_OF_REGISTERS 21
 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
 #define SLJIT_LOCALS_OFFSET_BASE (4 * sizeof(sljit_sw))
@@ -652,7 +665,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
 
 #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
 
-#if !defined(SLJIT_ASSERT) || !defined(SLJIT_ASSERT_STOP)
+#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)
 
 /* SLJIT_HALT_PROCESS must halt the process. */
 #ifndef SLJIT_HALT_PROCESS
@@ -664,7 +677,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
 
 #include <stdio.h>
 
-#endif /* !SLJIT_ASSERT || !SLJIT_ASSERT_STOP */
+#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */
 
 /* Feel free to redefine these two macros. */
 #ifndef SLJIT_ASSERT
@@ -679,34 +692,33 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
 
 #endif /* !SLJIT_ASSERT */
 
-#ifndef SLJIT_ASSERT_STOP
+#ifndef SLJIT_UNREACHABLE
 
-#define SLJIT_ASSERT_STOP() \
+#define SLJIT_UNREACHABLE() \
        do { \
                printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \
                SLJIT_HALT_PROCESS(); \
        } while (0)
 
-#endif /* !SLJIT_ASSERT_STOP */
+#endif /* !SLJIT_UNREACHABLE */
 
 #else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
 
 /* Forcing empty, but valid statements. */
 #undef SLJIT_ASSERT
-#undef SLJIT_ASSERT_STOP
+#undef SLJIT_UNREACHABLE
 
 #define SLJIT_ASSERT(x) \
        do { } while (0)
-#define SLJIT_ASSERT_STOP() \
+#define SLJIT_UNREACHABLE() \
        do { } while (0)
 
 #endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
 
 #ifndef SLJIT_COMPILE_ASSERT
 
-/* Should be improved eventually. */
 #define SLJIT_COMPILE_ASSERT(x, description) \
-       SLJIT_ASSERT(x)
+       switch(0) { case 0: case ((x) ? 1 : 0): break; }
 
 #endif /* !SLJIT_COMPILE_ASSERT */
 
index f24ed337973e7f07510f6bf81664ae8c79c8c463..f5009788f6222da61ea81605f767393f5054e1db 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -86,7 +86,7 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
        return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
 }
 
-static SLJIT_INLINE void free_chunk(voidchunk, sljit_uw size)
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
 {
        SLJIT_UNUSED_ARG(size);
        VirtualFree(chunk, 0, MEM_RELEASE);
@@ -96,7 +96,7 @@ static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
 
 static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
 {
-       voidretval;
+       void *retval;
 
 #ifdef MAP_ANON
        retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
@@ -111,7 +111,7 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
        return (retval != MAP_FAILED) ? retval : NULL;
 }
 
-static SLJIT_INLINE void free_chunk(voidchunk, sljit_uw size)
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
 {
        munmap(chunk, size);
 }
@@ -137,10 +137,10 @@ struct free_block {
 };
 
 #define AS_BLOCK_HEADER(base, offset) \
-       ((struct block_header*)(((sljit_ub*)base) + offset))
+       ((struct block_header*)(((sljit_u8*)base) + offset))
 #define AS_FREE_BLOCK(base, offset) \
-       ((struct free_block*)(((sljit_ub*)base) + offset))
-#define MEM_START(base)                ((void*)(((sljit_ub*)base) + sizeof(struct block_header)))
+       ((struct free_block*)(((sljit_u8*)base) + offset))
+#define MEM_START(base)                ((void*)(((sljit_u8*)base) + sizeof(struct block_header)))
 #define ALIGN_SIZE(size)       (((size) + sizeof(struct block_header) + 7) & ~7)
 
 static struct free_block* free_blocks;
@@ -153,7 +153,7 @@ static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block,
        free_block->size = size;
 
        free_block->next = free_blocks;
-       free_block->prev = 0;
+       free_block->prev = NULL;
        if (free_blocks)
                free_blocks->prev = free_block;
        free_blocks = free_block;
@@ -180,8 +180,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
        sljit_uw chunk_size;
 
        allocator_grab_lock();
-       if (size < sizeof(struct free_block))
-               size = sizeof(struct free_block);
+       if (size < (64 - sizeof(struct block_header)))
+               size = (64 - sizeof(struct block_header));
        size = ALIGN_SIZE(size);
 
        free_block = free_blocks;
index 0f1b1c9ccee1e11213a40a7d4027c1912531d34d..66cdda3db42e1360144a03681c030e0bdc987621 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
 
 #include "sljitLir.h"
 
+#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
+
+/* These libraries are needed for the macros below. */
+#include <stdlib.h>
+#include <string.h>
+
+#endif /* SLJIT_STD_MACROS_DEFINED */
+
 #define CHECK_ERROR() \
        do { \
                if (SLJIT_UNLIKELY(compiler->error)) \
 
 #if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
 
+#define VARIABLE_FLAG_SHIFT (10)
+#define VARIABLE_FLAG_MASK (0x3f << VARIABLE_FLAG_SHIFT)
+#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT)
+
 #define GET_OPCODE(op) \
-       ((op) & ~(SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+       ((op) & ~(SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
 
-#define GET_FLAGS(op) \
-       ((op) & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C))
+#define HAS_FLAGS(op) \
+       ((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))
 
 #define GET_ALL_FLAGS(op) \
-       ((op) & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+       ((op) & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
 
 #define TYPE_CAST_NEEDED(op) \
-       (((op) >= SLJIT_MOV_UB && (op) <= SLJIT_MOV_SH) || ((op) >= SLJIT_MOVU_UB && (op) <= SLJIT_MOVU_SH))
+       (((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16) || ((op) >= SLJIT_MOVU_U8 && (op) <= SLJIT_MOVU_S16))
 
 #define BUF_SIZE       4096
 
 #if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
 
 #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+
+#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+#include "sljitProtExecAllocator.c"
+#else
 #include "sljitExecAllocator.c"
 #endif
 
+#endif
+
+#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr) + (exec_offset))
+#else
+#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr))
+#endif
+
 /* Argument checking features. */
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
                        return 1; \
        } while (0)
 
-#define CHECK_RETURN_TYPE sljit_si
+#define CHECK_RETURN_TYPE sljit_s32
 #define CHECK_RETURN_OK return 0
 
 #define CHECK(x) \
 /*  Public functions                                                     */
 /* --------------------------------------------------------------------- */
 
-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
 #define SLJIT_NEEDS_COMPILER_INIT 1
-static sljit_si compiler_initialized = 0;
+static sljit_s32 compiler_initialized = 0;
 /* A thread safe initialization. */
 static void init_compiler(void);
 #endif
@@ -333,18 +357,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
        SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler));
 
        SLJIT_COMPILE_ASSERT(
-               sizeof(sljit_sb) == 1 && sizeof(sljit_ub) == 1
-               && sizeof(sljit_sh) == 2 && sizeof(sljit_uh) == 2
-               && sizeof(sljit_si) == 4 && sizeof(sljit_ui) == 4
+               sizeof(sljit_s8) == 1 && sizeof(sljit_u8) == 1
+               && sizeof(sljit_s16) == 2 && sizeof(sljit_u16) == 2
+               && sizeof(sljit_s32) == 4 && sizeof(sljit_u32) == 4
                && (sizeof(sljit_p) == 4 || sizeof(sljit_p) == 8)
                && sizeof(sljit_p) <= sizeof(sljit_sw)
                && (sizeof(sljit_sw) == 4 || sizeof(sljit_sw) == 8)
                && (sizeof(sljit_uw) == 4 || sizeof(sljit_uw) == 8),
                invalid_integer_types);
-       SLJIT_COMPILE_ASSERT(SLJIT_INT_OP == SLJIT_SINGLE_OP,
+       SLJIT_COMPILE_ASSERT(SLJIT_I32_OP == SLJIT_F32_OP,
                int_op_and_single_op_must_be_the_same);
-       SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_SINGLE_OP,
+       SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_F32_OP,
                rewritable_jump_and_single_op_must_not_be_the_same);
+       SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_EQUAL_F64 & 0x1) && !(SLJIT_JUMP & 0x1),
+               conditional_flags_must_be_even_numbers);
 
        /* Only the non-zero members must be set. */
        compiler->error = SLJIT_SUCCESS;
@@ -379,14 +405,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
 
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
        compiler->cpool = (sljit_uw*)SLJIT_MALLOC(CPOOL_SIZE * sizeof(sljit_uw)
-               + CPOOL_SIZE * sizeof(sljit_ub), allocator_data);
+               + CPOOL_SIZE * sizeof(sljit_u8), allocator_data);
        if (!compiler->cpool) {
                SLJIT_FREE(compiler->buf, allocator_data);
                SLJIT_FREE(compiler->abuf, allocator_data);
                SLJIT_FREE(compiler, allocator_data);
                return NULL;
        }
-       compiler->cpool_unique = (sljit_ub*)(compiler->cpool + CPOOL_SIZE);
+       compiler->cpool_unique = (sljit_u8*)(compiler->cpool + CPOOL_SIZE);
        compiler->cpool_diff = 0xffffffff;
 #endif
 
@@ -479,13 +505,25 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
        }
 }
 
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(current_flags);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+       if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_I32_OP | SLJIT_SET_Z)) == 0) {
+               compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_I32_OP | SLJIT_SET_Z));
+       }
+#endif
+}
+
 /* --------------------------------------------------------------------- */
 /*  Private functions                                                    */
 /* --------------------------------------------------------------------- */
 
 static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size)
 {
-       sljit_ub *ret;
+       sljit_u8 *ret;
        struct sljit_memory_fragment *new_frag;
 
        SLJIT_ASSERT(size <= 256);
@@ -504,7 +542,7 @@ static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size)
 
 static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size)
 {
-       sljit_ub *ret;
+       sljit_u8 *ret;
        struct sljit_memory_fragment *new_frag;
 
        SLJIT_ASSERT(size <= 256);
@@ -521,7 +559,7 @@ static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size)
        return new_frag->memory;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)
 {
        CHECK_ERROR_PTR();
 
@@ -554,8 +592,8 @@ static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)
 }
 
 static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+       sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
+       sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
 {
        SLJIT_UNUSED_ARG(args);
        SLJIT_UNUSED_ARG(local_size);
@@ -571,8 +609,8 @@ static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,
 }
 
 static SLJIT_INLINE void set_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+       sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
+       sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
 {
        SLJIT_UNUSED_ARG(args);
        SLJIT_UNUSED_ARG(local_size);
@@ -598,7 +636,7 @@ static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compi
        compiler->last_label = label;
 }
 
-static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_si flags)
+static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_s32 flags)
 {
        jump->next = NULL;
        jump->flags = flags;
@@ -624,65 +662,6 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
        (((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-#define FUNCTION_CHECK_OP() \
-       CHECK_ARGUMENT(!GET_FLAGS(op) || !(op & SLJIT_KEEP_FLAGS)); \
-       switch (GET_OPCODE(op)) { \
-       case SLJIT_NOT: \
-       case SLJIT_CLZ: \
-       case SLJIT_AND: \
-       case SLJIT_OR: \
-       case SLJIT_XOR: \
-       case SLJIT_SHL: \
-       case SLJIT_LSHR: \
-       case SLJIT_ASHR: \
-               CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C))); \
-               break; \
-       case SLJIT_NEG: \
-               CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \
-               break; \
-       case SLJIT_MUL: \
-               CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \
-               break; \
-       case SLJIT_ADD: \
-               CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_S))); \
-               break; \
-       case SLJIT_SUB: \
-               break; \
-       case SLJIT_ADDC: \
-       case SLJIT_SUBC: \
-               CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))); \
-               break; \
-       case SLJIT_BREAKPOINT: \
-       case SLJIT_NOP: \
-       case SLJIT_LUMUL: \
-       case SLJIT_LSMUL: \
-       case SLJIT_MOV: \
-       case SLJIT_MOV_UI: \
-       case SLJIT_MOV_P: \
-       case SLJIT_MOVU: \
-       case SLJIT_MOVU_UI: \
-       case SLJIT_MOVU_P: \
-               /* Nothing allowed */ \
-               CHECK_ARGUMENT(!(op & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
-               break; \
-       default: \
-               /* Only SLJIT_INT_OP or SLJIT_SINGLE_OP is allowed. */ \
-               CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
-               break; \
-       }
-
-#define FUNCTION_CHECK_FOP() \
-       CHECK_ARGUMENT(!GET_FLAGS(op) || !(op & SLJIT_KEEP_FLAGS)); \
-       switch (GET_OPCODE(op)) { \
-       case SLJIT_DCMP: \
-               CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
-               CHECK_ARGUMENT((op & (SLJIT_SET_E | SLJIT_SET_S))); \
-               break; \
-       default: \
-               /* Only SLJIT_INT_OP or SLJIT_SINGLE_OP is allowed. */ \
-               CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
-               break; \
-       }
 
 #define FUNCTION_CHECK_IS_REG(r) \
        (((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) || \
@@ -718,12 +697,12 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
                        CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
                        CHECK_ARGUMENT(!((i) & ~0x3)); \
                } \
-               CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
+               CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
        }
 
-#define FUNCTION_CHECK_DST(p, i) \
+#define FUNCTION_CHECK_DST(p, i, unused) \
        CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); \
-       if (FUNCTION_CHECK_IS_REG_OR_UNUSED(p)) \
+       if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED)) \
                CHECK_ARGUMENT((i) == 0); \
        else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
                CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \
@@ -737,7 +716,7 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
                        CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
                        CHECK_ARGUMENT(!((i) & ~0x3)); \
                } \
-               CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
+               CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
        }
 
 #define FUNCTION_FCHECK(p, i) \
@@ -757,15 +736,7 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
                        CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
                        CHECK_ARGUMENT(((p) & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SP) && !(i & ~0x3)); \
                } \
-               CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
-       }
-
-#define FUNCTION_CHECK_OP1() \
-       if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_P) { \
-               CHECK_ARGUMENT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_SP); \
-               CHECK_ARGUMENT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_SP); \
-               if ((src & SLJIT_MEM) && (src & REG_MASK)) \
-                       CHECK_ARGUMENT((dst & REG_MASK) != (src & REG_MASK) && OFFS_REG(dst) != (src & REG_MASK)); \
+               CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
        }
 
 #endif /* SLJIT_ARGUMENT_CHECKS */
@@ -791,8 +762,10 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
        do { \
                if ((r) < (SLJIT_R0 + compiler->scratches)) \
                        fprintf(compiler->verbose, "r%d", (r) - SLJIT_R0); \
-               else \
+               else if ((r) != SLJIT_SP) \
                        fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - (r)); \
+               else \
+                       fprintf(compiler->verbose, "sp"); \
        } while (0)
 
 #define sljit_verbose_param(compiler, p, i) \
@@ -844,38 +817,38 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
                        fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - (p)); \
        }
 
-static SLJIT_CONST char* op0_names[] = {
-       (char*)"breakpoint", (char*)"nop", (char*)"lumul", (char*)"lsmul",
-       (char*)"udivmod", (char*)"sdivmod", (char*)"udivi", (char*)"sdivi"
+static const char* op0_names[] = {
+       (char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw",
+       (char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s"
 };
 
-static SLJIT_CONST char* op1_names[] = {
-       (char*)"mov", (char*)"mov_ub", (char*)"mov_sb", (char*)"mov_uh",
-       (char*)"mov_sh", (char*)"mov_ui", (char*)"mov_si", (char*)"mov_p",
-       (char*)"movu", (char*)"movu_ub", (char*)"movu_sb", (char*)"movu_uh",
-       (char*)"movu_sh", (char*)"movu_ui", (char*)"movu_si", (char*)"movu_p",
+static const char* op1_names[] = {
+       (char*)"", (char*)".u8", (char*)".s8", (char*)".u16",
+       (char*)".s16", (char*)".u32", (char*)".s32", (char*)".p",
+       (char*)"", (char*)".u8", (char*)".s8", (char*)".u16",
+       (char*)".s16", (char*)".u32", (char*)".s32", (char*)".p",
        (char*)"not", (char*)"neg", (char*)"clz",
 };
 
-static SLJIT_CONST char* op2_names[] = {
+static const char* op2_names[] = {
        (char*)"add", (char*)"addc", (char*)"sub", (char*)"subc",
        (char*)"mul", (char*)"and", (char*)"or", (char*)"xor",
        (char*)"shl", (char*)"lshr", (char*)"ashr",
 };
 
-static SLJIT_CONST char* fop1_names[] = {
+static const char* fop1_names[] = {
        (char*)"mov", (char*)"conv", (char*)"conv", (char*)"conv",
        (char*)"conv", (char*)"conv", (char*)"cmp", (char*)"neg",
        (char*)"abs",
 };
 
-static SLJIT_CONST char* fop2_names[] = {
+static const char* fop2_names[] = {
        (char*)"add", (char*)"sub", (char*)"mul", (char*)"div"
 };
 
-#define JUMP_PREFIX(type) \
-       ((type & 0xff) <= SLJIT_MUL_NOT_OVERFLOW ? ((type & SLJIT_INT_OP) ? "i_" : "") \
-       : ((type & 0xff) <= SLJIT_D_ORDERED ? ((type & SLJIT_SINGLE_OP) ? "s_" : "d_") : ""))
+#define JUMP_POSTFIX(type) \
+       ((type & 0xff) <= SLJIT_MUL_NOT_OVERFLOW ? ((type & SLJIT_I32_OP) ? "32" : "") \
+       : ((type & 0xff) <= SLJIT_ORDERED_F64 ? ((type & SLJIT_F32_OP) ? ".f32" : ".f64") : ""))
 
 static char* jump_names[] = {
        (char*)"equal", (char*)"not_equal",
@@ -885,6 +858,7 @@ static char* jump_names[] = {
        (char*)"sig_greater", (char*)"sig_less_equal",
        (char*)"overflow", (char*)"not_overflow",
        (char*)"mul_overflow", (char*)"mul_not_overflow",
+       (char*)"carry", (char*)"",
        (char*)"equal", (char*)"not_equal",
        (char*)"less", (char*)"greater_equal",
        (char*)"greater", (char*)"less_equal",
@@ -923,13 +897,13 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_com
 }
 
 static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+       sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
+       sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
 {
        SLJIT_UNUSED_ARG(compiler);
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(!(options & ~SLJIT_DOUBLE_ALIGNMENT));
+       CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));
        CHECK_ARGUMENT(args >= 0 && args <= 3);
        CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
        CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
@@ -939,6 +913,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
        CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
        CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
        CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
+       compiler->last_flags = 0;
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose))
@@ -949,16 +924,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
 }
 
 static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+       sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
+       sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
 {
-       if (SLJIT_UNLIKELY(compiler->skip_checks)) {
-               compiler->skip_checks = 0;
-               CHECK_RETURN_OK;
-       }
-
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(!(options & ~SLJIT_DOUBLE_ALIGNMENT));
+       CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));
        CHECK_ARGUMENT(args >= 0 && args <= 3);
        CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
        CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
@@ -968,6 +938,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
        CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
        CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
        CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
+       compiler->last_flags = 0;
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose))
@@ -977,7 +948,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        CHECK_ARGUMENT(compiler->scratches >= 0);
@@ -987,13 +958,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi
        }
        else
                CHECK_ARGUMENT(src == 0 && srcw == 0);
+       compiler->last_flags = 0;
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
                if (op == SLJIT_UNUSED)
                        fprintf(compiler->verbose, "  return\n");
                else {
-                       fprintf(compiler->verbose, "  return.%s ", op1_names[op - SLJIT_OP1_BASE]);
+                       fprintf(compiler->verbose, "  return%s ", op1_names[op - SLJIT_OP1_BASE]);
                        sljit_verbose_param(compiler, src, srcw);
                        fprintf(compiler->verbose, "\n");
                }
@@ -1002,10 +974,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       FUNCTION_CHECK_DST(dst, dstw);
+       FUNCTION_CHECK_DST(dst, dstw, 0);
+       compiler->last_flags = 0;
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1017,10 +990,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_c
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        FUNCTION_CHECK_SRC(src, srcw);
+       compiler->last_flags = 0;
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1032,23 +1006,31 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
 {
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LSMUL)
-               || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIVMOD && (op & ~SLJIT_INT_OP) <= SLJIT_SDIVI));
-       CHECK_ARGUMENT(op < SLJIT_LUMUL || compiler->scratches >= 2);
+       CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW)
+               || ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW));
+       CHECK_ARGUMENT(op < SLJIT_LMUL_UW || compiler->scratches >= 2);
+       if (op >= SLJIT_LMUL_UW)
+               compiler->last_flags = 0;
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose))
-               fprintf(compiler->verbose, "  %s%s\n", !(op & SLJIT_INT_OP) ? "" : "i", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);
+       {
+               fprintf(compiler->verbose, "  %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);
+               if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW) {
+                       fprintf(compiler->verbose, (op & SLJIT_I32_OP) ? "32" : "w");
+               }
+               fprintf(compiler->verbose, "\n");
+       }
 #endif
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
        if (SLJIT_UNLIKELY(compiler->skip_checks)) {
                compiler->skip_checks = 0;
@@ -1057,16 +1039,64 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ);
-       FUNCTION_CHECK_OP();
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_NOT:
+               /* Only SLJIT_I32_OP and SLJIT_SET_Z are allowed. */
+               CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
+               break;
+       case SLJIT_NEG:
+               CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+                       || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
+               break;
+       case SLJIT_MOV:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOV_P:
+       case SLJIT_MOVU:
+       case SLJIT_MOVU_U32:
+       case SLJIT_MOVU_P:
+               /* Nothing allowed */
+               CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+               break;
+       default:
+               /* Only SLJIT_I32_OP is allowed. */
+               CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+               break;
+       }
+
+       FUNCTION_CHECK_DST(dst, dstw, 1);
        FUNCTION_CHECK_SRC(src, srcw);
-       FUNCTION_CHECK_DST(dst, dstw);
-       FUNCTION_CHECK_OP1();
+
+       if (GET_OPCODE(op) >= SLJIT_NOT)
+               compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
+       else if (GET_OPCODE(op) >= SLJIT_MOVU) {
+               CHECK_ARGUMENT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_SP);
+               CHECK_ARGUMENT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_SP);
+               if ((src & REG_MASK) != SLJIT_UNUSED) {
+                       CHECK_ARGUMENT((src & REG_MASK) != (dst & REG_MASK) && (src & REG_MASK) != OFFS_REG(dst));
+                       CHECK_ARGUMENT((src & OFFS_REG_MASK) == SLJIT_UNUSED || srcw == 0);
+               }
+               if ((dst & REG_MASK) != SLJIT_UNUSED) {
+                       CHECK_ARGUMENT((dst & REG_MASK) != OFFS_REG(src));
+                       CHECK_ARGUMENT((dst & OFFS_REG_MASK) == SLJIT_UNUSED || dstw == 0);
+               }
+               compiler->last_flags = 0;
+       }
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
-               fprintf(compiler->verbose, "  %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE],
-                       !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
-                       !(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
+               if (GET_OPCODE(op) <= SLJIT_MOVU_P)
+               {
+                       fprintf(compiler->verbose, "  mov%s%s%s ", (GET_OPCODE(op) >= SLJIT_MOVU) ? "u" : "",
+                               !(op & SLJIT_I32_OP) ? "" : "32", (op != SLJIT_MOV32 && op != SLJIT_MOVU32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : "");
+               }
+               else
+               {
+                       fprintf(compiler->verbose, "  %s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_I32_OP) ? "" : "32",
+                               !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",
+                               !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);
+               }
+
                sljit_verbose_param(compiler, dst, dstw);
                fprintf(compiler->verbose, ", ");
                sljit_verbose_param(compiler, src, srcw);
@@ -1076,10 +1106,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        if (SLJIT_UNLIKELY(compiler->skip_checks)) {
                compiler->skip_checks = 0;
@@ -1088,16 +1118,53 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR);
-       FUNCTION_CHECK_OP();
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_AND:
+       case SLJIT_OR:
+       case SLJIT_XOR:
+       case SLJIT_SHL:
+       case SLJIT_LSHR:
+       case SLJIT_ASHR:
+               CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
+               break;
+       case SLJIT_MUL:
+               CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
+               CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+                       || GET_FLAG_TYPE(op) == SLJIT_MUL_OVERFLOW);
+               break;
+       case SLJIT_ADD:
+               CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+                       || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)
+                       || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
+               break;
+       case SLJIT_SUB:
+               CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+                       || (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_OVERFLOW)
+                       || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
+               break;
+       case SLJIT_ADDC:
+       case SLJIT_SUBC:
+               CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+                       || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
+               CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
+               CHECK_ARGUMENT((op & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP));
+               break;
+       default:
+               SLJIT_UNREACHABLE();
+               break;
+       }
+
+       FUNCTION_CHECK_DST(dst, dstw, 1);
        FUNCTION_CHECK_SRC(src1, src1w);
        FUNCTION_CHECK_SRC(src2, src2w);
-       FUNCTION_CHECK_DST(dst, dstw);
+       compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
-               fprintf(compiler->verbose, "  %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
-                       !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
-                       !(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
+               fprintf(compiler->verbose, "  %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_I32_OP) ? "" : "32",
+                       !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",
+                       !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);
                sljit_verbose_param(compiler, dst, dstw);
                fprintf(compiler->verbose, ", ");
                sljit_verbose_param(compiler, src1, src1w);
@@ -1109,7 +1176,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_si reg)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 reg)
 {
        SLJIT_UNUSED_ARG(reg);
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -1118,7 +1185,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_si re
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_float_register_index(sljit_si reg)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_float_register_index(sljit_s32 reg)
 {
        SLJIT_UNUSED_ARG(reg);
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -1128,7 +1195,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_float_register_index(sljit
 }
 
 static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+       void *instruction, sljit_s32 size)
 {
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        int i;
@@ -1138,6 +1205,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        CHECK_ARGUMENT(instruction);
+
 #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
        CHECK_ARGUMENT(size > 0 && size < 16);
 #elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
@@ -1147,21 +1215,22 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co
        CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0);
 #endif
 
+       compiler->last_flags = 0;
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
                fprintf(compiler->verbose, "  op_custom");
                for (i = 0; i < size; i++)
-                       fprintf(compiler->verbose, " 0x%x", ((sljit_ub*)instruction)[i]);
+                       fprintf(compiler->verbose, " 0x%x", ((sljit_u8*)instruction)[i]);
                fprintf(compiler->verbose, "\n");
        }
 #endif
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
        if (SLJIT_UNLIKELY(compiler->skip_checks)) {
                compiler->skip_checks = 0;
@@ -1169,20 +1238,20 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile
        }
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(sljit_is_fpu_available());
-       CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_DMOV && GET_OPCODE(op) <= SLJIT_DABS);
-       FUNCTION_CHECK_FOP();
+       CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+       CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64);
+       CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
        FUNCTION_FCHECK(src, srcw);
        FUNCTION_FCHECK(dst, dstw);
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
-               if (GET_OPCODE(op) == SLJIT_CONVD_FROMS)
-                       fprintf(compiler->verbose, "  %s%s ", fop1_names[SLJIT_CONVD_FROMS - SLJIT_FOP1_BASE],
-                               (op & SLJIT_SINGLE_OP) ? "s.fromd" : "d.froms");
+               if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
+                       fprintf(compiler->verbose, "  %s%s ", fop1_names[SLJIT_CONV_F64_FROM_F32 - SLJIT_FOP1_BASE],
+                               (op & SLJIT_F32_OP) ? ".f32.from.f64" : ".f64.from.f32");
                else
-                       fprintf(compiler->verbose, "  %s%s ", (op & SLJIT_SINGLE_OP) ? "s" : "d",
-                               fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE]);
+                       fprintf(compiler->verbose, "  %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
+                               (op & SLJIT_F32_OP) ? ".f32" : ".f64");
 
                sljit_verbose_fparam(compiler, dst, dstw);
                fprintf(compiler->verbose, ", ");
@@ -1193,26 +1262,35 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+       compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
+#endif
+
        if (SLJIT_UNLIKELY(compiler->skip_checks)) {
                compiler->skip_checks = 0;
                CHECK_RETURN_OK;
        }
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(sljit_is_fpu_available());
-       CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_DCMP);
-       FUNCTION_CHECK_FOP();
+       CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+       CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64);
+       CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
+       CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK)
+               || (GET_FLAG_TYPE(op) >= SLJIT_EQUAL_F64 && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_F64));
        FUNCTION_FCHECK(src1, src1w);
        FUNCTION_FCHECK(src2, src2w);
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
-               fprintf(compiler->verbose, "  %s%s%s%s ", (op & SLJIT_SINGLE_OP) ? "s" : "d", fop1_names[SLJIT_DCMP - SLJIT_FOP1_BASE],
-                       (op & SLJIT_SET_E) ? ".e" : "", (op & SLJIT_SET_S) ? ".s" : "");
+               fprintf(compiler->verbose, "  %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64");
+               if (op & VARIABLE_FLAG_MASK) {
+                       fprintf(compiler->verbose, ".%s_f", jump_names[GET_FLAG_TYPE(op)]);
+               }
+               fprintf(compiler->verbose, " ");
                sljit_verbose_fparam(compiler, src1, src1w);
                fprintf(compiler->verbose, ", ");
                sljit_verbose_fparam(compiler, src2, src2w);
@@ -1222,9 +1300,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
        if (SLJIT_UNLIKELY(compiler->skip_checks)) {
                compiler->skip_checks = 0;
@@ -1232,17 +1310,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_convw_fromd(struct s
        }
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(sljit_is_fpu_available());
-       CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONVW_FROMD && GET_OPCODE(op) <= SLJIT_CONVI_FROMD);
-       FUNCTION_CHECK_FOP();
+       CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+       CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CONV_S32_FROM_F64);
+       CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
        FUNCTION_FCHECK(src, srcw);
-       FUNCTION_CHECK_DST(dst, dstw);
+       FUNCTION_CHECK_DST(dst, dstw, 0);
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
                fprintf(compiler->verbose, "  %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
-                       (GET_OPCODE(op) == SLJIT_CONVI_FROMD) ? "i" : "w",
-                       (op & SLJIT_SINGLE_OP) ? "s" : "d");
+                       (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? ".s32" : ".sw",
+                       (op & SLJIT_F32_OP) ? ".f32" : ".f64");
                sljit_verbose_param(compiler, dst, dstw);
                fprintf(compiler->verbose, ", ");
                sljit_verbose_fparam(compiler, src, srcw);
@@ -1252,9 +1330,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_convw_fromd(struct s
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
        if (SLJIT_UNLIKELY(compiler->skip_checks)) {
                compiler->skip_checks = 0;
@@ -1262,17 +1340,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_convd_fromw(struct s
        }
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(sljit_is_fpu_available());
-       CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONVD_FROMW && GET_OPCODE(op) <= SLJIT_CONVD_FROMI);
-       FUNCTION_CHECK_FOP();
+       CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+       CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_SW && GET_OPCODE(op) <= SLJIT_CONV_F64_FROM_S32);
+       CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
        FUNCTION_CHECK_SRC(src, srcw);
        FUNCTION_FCHECK(dst, dstw);
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
                fprintf(compiler->verbose, "  %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
-                       (op & SLJIT_SINGLE_OP) ? "s" : "d",
-                       (GET_OPCODE(op) == SLJIT_CONVD_FROMI) ? "i" : "w");
+                       (op & SLJIT_F32_OP) ? ".f32" : ".f64",
+                       (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? ".s32" : ".sw");
                sljit_verbose_fparam(compiler, dst, dstw);
                fprintf(compiler->verbose, ", ");
                sljit_verbose_param(compiler, src, srcw);
@@ -1282,22 +1360,22 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_convd_fromw(struct s
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(sljit_is_fpu_available());
-       CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_DADD && GET_OPCODE(op) <= SLJIT_DDIV);
-       FUNCTION_CHECK_FOP();
+       CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+       CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64);
+       CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
        FUNCTION_FCHECK(src1, src1w);
        FUNCTION_FCHECK(src2, src2w);
        FUNCTION_FCHECK(dst, dstw);
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
-               fprintf(compiler->verbose, "  %s%s ", (op & SLJIT_SINGLE_OP) ? "s" : "d", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE]);
+               fprintf(compiler->verbose, "  %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64");
                sljit_verbose_fparam(compiler, dst, dstw);
                fprintf(compiler->verbose, ", ");
                sljit_verbose_fparam(compiler, src1, src1w);
@@ -1313,6 +1391,15 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil
 {
        SLJIT_UNUSED_ARG(compiler);
 
+       if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+               compiler->skip_checks = 0;
+               CHECK_RETURN_OK;
+       }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+       compiler->last_flags = 0;
+#endif
+
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose))
                fprintf(compiler->verbose, "label:\n");
@@ -1320,7 +1407,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
        if (SLJIT_UNLIKELY(compiler->skip_checks)) {
                compiler->skip_checks = 0;
@@ -1328,33 +1415,45 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile
        }
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_INT_OP)));
+       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));
+       CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1));
        CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_CALL3);
-       CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_INT_OP));
+       CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_I32_OP));
        CHECK_ARGUMENT((type & 0xff) <= SLJIT_CALL0 || ((type & 0xff) - SLJIT_CALL0) <= compiler->scratches);
+
+       if ((type & 0xff) < SLJIT_JUMP) {
+               if ((type & 0xff) <= SLJIT_NOT_ZERO)
+                       CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+               else
+                       CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
+                               || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)
+                               || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));
+               CHECK_ARGUMENT((type & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP));
+       }
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose))
-               fprintf(compiler->verbose, "  jump%s.%s%s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
-                       JUMP_PREFIX(type), jump_names[type & 0xff]);
+               fprintf(compiler->verbose, "  jump%s %s%s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
+                       jump_names[type & 0xff], JUMP_POSTFIX(type));
 #endif
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_INT_OP)));
+       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));
        CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL);
        FUNCTION_CHECK_SRC(src1, src1w);
        FUNCTION_CHECK_SRC(src2, src2w);
+       compiler->last_flags = 0;
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
-               fprintf(compiler->verbose, "  cmp%s.%s%s ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
-                       (type & SLJIT_INT_OP) ? "i_" : "", jump_names[type & 0xff]);
+               fprintf(compiler->verbose, "  cmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
+                       jump_names[type & 0xff], (type & SLJIT_I32_OP) ? "32" : "");
                sljit_verbose_param(compiler, src1, src1w);
                fprintf(compiler->verbose, ", ");
                sljit_verbose_param(compiler, src2, src2w);
@@ -1364,21 +1463,22 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(sljit_is_fpu_available());
-       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_SINGLE_OP)));
-       CHECK_ARGUMENT((type & 0xff) >= SLJIT_D_EQUAL && (type & 0xff) <= SLJIT_D_ORDERED);
+       CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_F32_OP)));
+       CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL_F64 && (type & 0xff) <= SLJIT_ORDERED_F64);
        FUNCTION_FCHECK(src1, src1w);
        FUNCTION_FCHECK(src2, src2w);
+       compiler->last_flags = 0;
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
-               fprintf(compiler->verbose, "  fcmp%s.%s%s ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
-                       (type & SLJIT_SINGLE_OP) ? "s_" : "d_", jump_names[type & 0xff]);
+               fprintf(compiler->verbose, "  fcmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
+                       jump_names[type & 0xff], (type & SLJIT_F32_OP) ? ".f32" : ".f64");
                sljit_verbose_fparam(compiler, src1, src1w);
                fprintf(compiler->verbose, ", ");
                sljit_verbose_fparam(compiler, src2, src2w);
@@ -1388,8 +1488,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+       compiler->last_flags = 0;
+#endif
+
        if (SLJIT_UNLIKELY(compiler->skip_checks)) {
                compiler->skip_checks = 0;
                CHECK_RETURN_OK;
@@ -1410,47 +1514,82 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compil
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type)
 {
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_INT_OP)));
-       CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_D_ORDERED);
-       CHECK_ARGUMENT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_MOV_UI || GET_OPCODE(op) == SLJIT_MOV_SI
+       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
+       CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
+       CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1));
+       CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32
                || (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));
-       CHECK_ARGUMENT((op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C)) == 0);
-       CHECK_ARGUMENT((op & (SLJIT_SET_E | SLJIT_KEEP_FLAGS)) != (SLJIT_SET_E | SLJIT_KEEP_FLAGS));
-       if (GET_OPCODE(op) < SLJIT_ADD) {
-               CHECK_ARGUMENT(src == SLJIT_UNUSED && srcw == 0);
-       } else {
-               CHECK_ARGUMENT(src == dst && srcw == dstw);
-       }
-       FUNCTION_CHECK_DST(dst, dstw);
+       CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
+
+       if ((type & 0xff) <= SLJIT_NOT_ZERO)
+               CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+       else
+               CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
+                       || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)
+                       || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));
+
+       FUNCTION_CHECK_DST(dst, dstw, 0);
+
+       if (GET_OPCODE(op) >= SLJIT_ADD)
+               compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
-               fprintf(compiler->verbose, "  flags.%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i",
-                       GET_OPCODE(op) >= SLJIT_OP2_BASE ? op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE] : op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE],
-                       !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
+               fprintf(compiler->verbose, "  flags%s %s%s, ",
+                       !(op & SLJIT_SET_Z) ? "" : ".z",
+                       GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
+                       GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_I32_OP) ? "32" : ""));
                sljit_verbose_param(compiler, dst, dstw);
-               if (src != SLJIT_UNUSED) {
-                       fprintf(compiler->verbose, ", ");
-                       sljit_verbose_param(compiler, src, srcw);
-               }
-               fprintf(compiler->verbose, ", %s%s\n", JUMP_PREFIX(type), jump_names[type & 0xff]);
+               fprintf(compiler->verbose, ", %s%s\n", jump_names[type & 0xff], JUMP_POSTFIX(type));
+       }
+#endif
+       CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
+       CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
+       CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP));
+       if (src != SLJIT_IMM) {
+               CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src));
+       }
+
+       if ((type & 0xff) <= SLJIT_NOT_ZERO)
+               CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+       else
+               CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
+                       || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)
+                       || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  cmov%s %s%s, ",
+                       !(dst_reg & SLJIT_I32_OP) ? "" : ".i",
+                       jump_names[type & 0xff], JUMP_POSTFIX(type));
+               sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP);
+               fprintf(compiler->verbose, ", ");
+               sljit_verbose_param(compiler, src, srcw);
+               fprintf(compiler->verbose, "\n");
        }
 #endif
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
 {
        SLJIT_UNUSED_ARG(offset);
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       FUNCTION_CHECK_DST(dst, dstw);
+       FUNCTION_CHECK_DST(dst, dstw, 0);
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1462,12 +1601,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_co
        CHECK_RETURN_OK;
 }
 
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 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);
+       FUNCTION_CHECK_DST(dst, dstw, 0);
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
        if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1482,31 +1621,31 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil
 #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
 
 #define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \
-       SLJIT_COMPILE_ASSERT(!(SLJIT_CONVW_FROMD & 0x1) && !(SLJIT_CONVD_FROMW & 0x1), \
+       SLJIT_COMPILE_ASSERT(!(SLJIT_CONV_SW_FROM_F64 & 0x1) && !(SLJIT_CONV_F64_FROM_SW & 0x1), \
                invalid_float_opcodes); \
-       if (GET_OPCODE(op) >= SLJIT_CONVW_FROMD && GET_OPCODE(op) <= SLJIT_DCMP) { \
-               if (GET_OPCODE(op) == SLJIT_DCMP) { \
+       if (GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CMP_F64) { \
+               if (GET_OPCODE(op) == SLJIT_CMP_F64) { \
                        CHECK(check_sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw)); \
                        ADJUST_LOCAL_OFFSET(dst, dstw); \
                        ADJUST_LOCAL_OFFSET(src, srcw); \
                        return sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw); \
                } \
-               if ((GET_OPCODE(op) | 0x1) == SLJIT_CONVI_FROMD) { \
-                       CHECK(check_sljit_emit_fop1_convw_fromd(compiler, op, dst, dstw, src, srcw)); \
+               if ((GET_OPCODE(op) | 0x1) == SLJIT_CONV_S32_FROM_F64) { \
+                       CHECK(check_sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw)); \
                        ADJUST_LOCAL_OFFSET(dst, dstw); \
                        ADJUST_LOCAL_OFFSET(src, srcw); \
-                       return sljit_emit_fop1_convw_fromd(compiler, op, dst, dstw, src, srcw); \
+                       return sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw); \
                } \
-               CHECK(check_sljit_emit_fop1_convd_fromw(compiler, op, dst, dstw, src, srcw)); \
+               CHECK(check_sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw)); \
                ADJUST_LOCAL_OFFSET(dst, dstw); \
                ADJUST_LOCAL_OFFSET(src, srcw); \
-               return sljit_emit_fop1_convd_fromw(compiler, op, dst, dstw, src, srcw); \
+               return sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw); \
        } \
        CHECK(check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw)); \
        ADJUST_LOCAL_OFFSET(dst, dstw); \
        ADJUST_LOCAL_OFFSET(src, srcw);
 
-static SLJIT_INLINE sljit_si emit_mov_before_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
        /* Return if don't need to do anything. */
        if (op == SLJIT_UNUSED)
@@ -1517,7 +1656,7 @@ static SLJIT_INLINE sljit_si emit_mov_before_return(struct sljit_compiler *compi
        if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P))
                return SLJIT_SUCCESS;
 #else
-       if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI || op == SLJIT_MOV_P))
+       if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P))
                return SLJIT_SUCCESS;
 #endif
 
@@ -1528,6 +1667,44 @@ static SLJIT_INLINE sljit_si emit_mov_before_return(struct sljit_compiler *compi
        return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
 }
 
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+               || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
+               || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
+               || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1))
+
+static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+       struct sljit_label *label;
+       struct sljit_jump *jump;
+       sljit_s32 op = (dst_reg & SLJIT_I32_OP) ? SLJIT_MOV32 : SLJIT_MOV;
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+               || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+       compiler->skip_checks = 1;
+#endif
+       jump = sljit_emit_jump(compiler, type ^ 0x1);
+       FAIL_IF(!jump);
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+               || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+       compiler->skip_checks = 1;
+#endif
+       FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_I32_OP, 0, src, srcw));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+               || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+       compiler->skip_checks = 1;
+#endif
+       label = sljit_emit_label(compiler);
+       FAIL_IF(!label);
+       sljit_set_label(jump, label);
+       return SLJIT_SUCCESS;
+}
+
+#endif
+
 /* CPU description section */
 
 #if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
@@ -1576,12 +1753,12 @@ static SLJIT_INLINE sljit_si emit_mov_before_return(struct sljit_compiler *compi
 
 #if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        /* Default compare for most architectures. */
-       sljit_si flags, tmp_src, condition;
+       sljit_s32 flags, tmp_src, condition;
        sljit_sw tmp_srcw;
 
        CHECK_ERROR_PTR();
@@ -1629,7 +1806,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
                        condition = SLJIT_SIG_GREATER_EQUAL;
                        break;
                }
-               type = condition | (type & (SLJIT_INT_OP | SLJIT_REWRITABLE_JUMP));
+
+               type = condition | (type & (SLJIT_I32_OP | SLJIT_REWRITABLE_JUMP));
                tmp_src = src1;
                src1 = src2;
                src2 = tmp_src;
@@ -1639,57 +1817,48 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
        }
 
        if (condition <= SLJIT_NOT_ZERO)
-               flags = SLJIT_SET_E;
-       else if (condition <= SLJIT_LESS_EQUAL)
-               flags = SLJIT_SET_U;
+               flags = SLJIT_SET_Z;
        else
-               flags = SLJIT_SET_S;
+               flags = condition << VARIABLE_FLAG_SHIFT;
 
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
                || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        compiler->skip_checks = 1;
 #endif
-       PTR_FAIL_IF(sljit_emit_op2(compiler, SLJIT_SUB | flags | (type & SLJIT_INT_OP),
+       PTR_FAIL_IF(sljit_emit_op2(compiler, SLJIT_SUB | flags | (type & SLJIT_I32_OP),
                SLJIT_UNUSED, 0, src1, src1w, src2, src2w));
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
                || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        compiler->skip_checks = 1;
 #endif
-       return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
+       return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
-{
-       sljit_si flags, condition;
+#endif
 
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
+{
        CHECK_ERROR_PTR();
        CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));
 
-       condition = type & 0xff;
-       flags = (condition <= SLJIT_D_NOT_EQUAL) ? SLJIT_SET_E : SLJIT_SET_S;
-       if (type & SLJIT_SINGLE_OP)
-               flags |= SLJIT_SINGLE_OP;
-
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
                || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        compiler->skip_checks = 1;
 #endif
-       sljit_emit_fop1(compiler, SLJIT_DCMP | flags, src1, src1w, src2, src2w);
+       sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_I32_OP), src1, src1w, src2, src2w);
 
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
                || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        compiler->skip_checks = 1;
 #endif
-       return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
+       return sljit_emit_jump(compiler, type);
 }
 
-#endif
-
 #if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
 {
        CHECK_ERROR();
        CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
@@ -1700,7 +1869,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *co
        compiler->skip_checks = 1;
 #endif
        if (offset != 0)
-               return sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
+               return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
        return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0);
 }
 
@@ -1710,28 +1879,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *co
 
 /* Empty function bodies for those machines, which are not (yet) supported. */
 
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
 {
        return "unsupported";
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data)
 {
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNUSED_ARG(allocator_data);
+       SLJIT_UNREACHABLE();
        return NULL;
 }
 
 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)
 {
        SLJIT_UNUSED_ARG(compiler);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNREACHABLE();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(size);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return NULL;
 }
 
@@ -1740,26 +1916,33 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(verbose);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
 }
 #endif
 
 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
 {
        SLJIT_UNUSED_ARG(compiler);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return NULL;
 }
 
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+       SLJIT_UNUSED_ARG(feature_type);
+       SLJIT_UNREACHABLE();
+       return 0;
+}
+
 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
 {
        SLJIT_UNUSED_ARG(code);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(options);
@@ -1769,13 +1952,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        SLJIT_UNUSED_ARG(fscratches);
        SLJIT_UNUSED_ARG(fsaveds);
        SLJIT_UNUSED_ARG(local_size);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(options);
@@ -1785,49 +1968,49 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
        SLJIT_UNUSED_ARG(fscratches);
        SLJIT_UNUSED_ARG(fsaveds);
        SLJIT_UNUSED_ARG(local_size);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(op);
        SLJIT_UNUSED_ARG(src);
        SLJIT_UNUSED_ARG(srcw);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(dst);
        SLJIT_UNUSED_ARG(dstw);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(src);
        SLJIT_UNUSED_ARG(srcw);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(op);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(op);
@@ -1835,14 +2018,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        SLJIT_UNUSED_ARG(dstw);
        SLJIT_UNUSED_ARG(src);
        SLJIT_UNUSED_ARG(srcw);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(op);
@@ -1852,35 +2035,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        SLJIT_UNUSED_ARG(src1w);
        SLJIT_UNUSED_ARG(src2);
        SLJIT_UNUSED_ARG(src2w);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
 {
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return reg;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(instruction);
        SLJIT_UNUSED_ARG(size);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
 {
-       SLJIT_ASSERT_STOP();
-       return 0;
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(current_flags);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(op);
@@ -1888,14 +2071,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
        SLJIT_UNUSED_ARG(dstw);
        SLJIT_UNUSED_ARG(src);
        SLJIT_UNUSED_ARG(srcw);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(op);
@@ -1905,28 +2088,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
        SLJIT_UNUSED_ARG(src1w);
        SLJIT_UNUSED_ARG(src2);
        SLJIT_UNUSED_ARG(src2w);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
 {
        SLJIT_UNUSED_ARG(compiler);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return NULL;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(type);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return NULL;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(type);
@@ -1934,13 +2117,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
        SLJIT_UNUSED_ARG(src1w);
        SLJIT_UNUSED_ARG(src2);
        SLJIT_UNUSED_ARG(src2w);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return NULL;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(type);
@@ -1948,7 +2131,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
        SLJIT_UNUSED_ARG(src1w);
        SLJIT_UNUSED_ARG(src2);
        SLJIT_UNUSED_ARG(src2w);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return NULL;
 }
 
@@ -1956,74 +2139,86 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl
 {
        SLJIT_UNUSED_ARG(jump);
        SLJIT_UNUSED_ARG(label);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
 }
 
 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)
 {
        SLJIT_UNUSED_ARG(jump);
        SLJIT_UNUSED_ARG(target);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(type);
        SLJIT_UNUSED_ARG(src);
        SLJIT_UNUSED_ARG(srcw);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(op);
        SLJIT_UNUSED_ARG(dst);
        SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_UNREACHABLE();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_UNUSED_ARG(dst_reg);
        SLJIT_UNUSED_ARG(src);
        SLJIT_UNUSED_ARG(srcw);
-       SLJIT_UNUSED_ARG(type);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(dst);
        SLJIT_UNUSED_ARG(dstw);
        SLJIT_UNUSED_ARG(offset);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw initval)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw initval)
 {
        SLJIT_UNUSED_ARG(compiler);
        SLJIT_UNUSED_ARG(dst);
        SLJIT_UNUSED_ARG(dstw);
        SLJIT_UNUSED_ARG(initval);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return NULL;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
 {
        SLJIT_UNUSED_ARG(addr);
-       SLJIT_UNUSED_ARG(new_addr);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNUSED_ARG(new_target);
+       SLJIT_UNUSED_ARG(executable_offset);
+       SLJIT_UNREACHABLE();
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
        SLJIT_UNUSED_ARG(addr);
        SLJIT_UNUSED_ARG(new_constant);
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNUSED_ARG(executable_offset);
+       SLJIT_UNREACHABLE();
 }
 
 #endif
index 2e2e9ac09cd660883f7c362b2260c7730a6060ca..a58ad6e63872603f1ef6e705ef33b7b93a10749b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -99,6 +99,8 @@ of sljitConfigInternal.h */
 #define SLJIT_ERR_UNSUPPORTED          4
 /* An ivalid argument is passed to any SLJIT function. */
 #define SLJIT_ERR_BAD_ARGUMENT         5
+/* Dynamic code modification is not enabled. */
+#define SLJIT_ERR_DYN_CODE_MOD         6
 
 /* --------------------------------------------------------------------- */
 /*  Registers                                                            */
@@ -118,8 +120,8 @@ of sljitConfigInternal.h */
   If an architecture provides two scratch and three saved registers,
   its scratch and saved register sets are the following:
 
-     R0   |  [S4]  |   R0 and S4 represent the same physical register
-     R1   |  [S3]  |   R1 and S3 represent the same physical register
+     R0   |        |   R0 is always a scratch register
+     R1   |        |   R1 is always a scratch register
     [R2]  |   S2   |   R2 and S2 represent the same physical register
     [R3]  |   S1   |   R3 and S1 represent the same physical register
     [R4]  |   S0   |   R4 and S0 represent the same physical register
@@ -127,38 +129,35 @@ of sljitConfigInternal.h */
   Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS would be 2 and
         SLJIT_NUMBER_OF_SAVED_REGISTERS would be 3 for this architecture.
 
-  Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 10
-        and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 5. However, 4 registers
+  Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 12
+        and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 6. However, 6 registers
         are virtual on x86-32. See below.
 
-  The purpose of this definition is convenience. Although a register
-  is either scratch register or saved register, SLJIT allows accessing
-  them from the other set. For example, four registers can be used as
-  scratch registers and the fifth one as saved register on the architecture
-  above. Of course the last two scratch registers (R2 and R3) from this
-  four will be saved on the stack, because they are defined as saved
-  registers in the application binary interface. Still R2 and R3 can be
-  used for referencing to these registers instead of S2 and S1, which
-  makes easier to write platform independent code. Scratch registers
-  can be saved registers in a similar way, but these extra saved
-  registers will not be preserved across function calls! Hence the
-  application must save them on those platforms, where the number of
-  saved registers is too low. This can be done by copy them onto
-  the stack and restore them after a function call.
+  The purpose of this definition is convenience: saved registers can
+  be used as extra scratch registers. For example four registers can
+  be specified as scratch registers and the fifth one as saved register
+  on the CPU above and any user code which requires four scratch
+  registers can run unmodified. The SLJIT compiler automatically saves
+  the content of the two extra scrath register on the stack. Scratch
+  registers can also be preserved by saving their value on the stack
+  but this needs to be done manually.
 
   Note: To emphasize that registers assigned to R2-R4 are saved
-        registers, they are enclosed by square brackets. S3-S4
-        are marked in a similar way.
+        registers, they are enclosed by square brackets.
 
   Note: sljit_emit_enter and sljit_set_context defines whether a register
         is S or R register. E.g: when 3 scratches and 1 saved is mapped
         by sljit_emit_enter, the allowed register set will be: R0-R2 and
         S0. Although S2 is mapped to the same position as R2, it does not
-        available in the current configuration. Furthermore the R3 (S1)
-        register does not available as well.
+        available in the current configuration. Furthermore the S1 register
+        is not available at all.
 */
 
-/* When SLJIT_UNUSED is specified as destination, the result is discarded. */
+/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1 and
+   and sljit_emit_op2 operations the result is discarded. If no status
+   flags are set, no instructions are emitted for these operations. Data
+   prefetch is a special exception, see SLJIT_MOV operation. Other SLJIT
+   operations do not support SLJIT_UNUSED as a destination operand. */
 #define SLJIT_UNUSED           0
 
 /* Scratch registers. */
@@ -226,7 +225,7 @@ of sljitConfigInternal.h */
 /*  Floating point registers                                             */
 /* --------------------------------------------------------------------- */
 
-/* Each floating point register can store a double or single precision
+/* Each floating point register can store a 32 or a 64 bit precision
    value. The FR and FS register sets are overlap in the same way as R
    and S register sets. See above. */
 
@@ -271,7 +270,7 @@ struct sljit_memory_fragment {
        struct sljit_memory_fragment *next;
        sljit_uw used_size;
        /* Must be aligned to sljit_sw. */
-       sljit_ub memory[1];
+       sljit_u8 memory[1];
 };
 
 struct sljit_label {
@@ -297,8 +296,8 @@ struct sljit_const {
 };
 
 struct sljit_compiler {
-       sljit_si error;
-       sljit_si options;
+       sljit_s32 error;
+       sljit_s32 options;
 
        struct sljit_label *labels;
        struct sljit_jump *jumps;
@@ -312,36 +311,39 @@ struct sljit_compiler {
        struct sljit_memory_fragment *abuf;
 
        /* Used scratch registers. */
-       sljit_si scratches;
+       sljit_s32 scratches;
        /* Used saved registers. */
-       sljit_si saveds;
+       sljit_s32 saveds;
        /* Used float scratch registers. */
-       sljit_si fscratches;
+       sljit_s32 fscratches;
        /* Used float saved registers. */
-       sljit_si fsaveds;
+       sljit_s32 fsaveds;
        /* Local stack size. */
-       sljit_si local_size;
+       sljit_s32 local_size;
        /* Code size. */
        sljit_uw size;
-       /* For statistical purposes. */
+       /* Relative offset of the executable mapping from the writable mapping. */
+       sljit_uw executable_offset;
+       /* Executable size for statistical purposes. */
        sljit_uw executable_size;
 
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       sljit_si args;
+       sljit_s32 args;
+       sljit_s32 locals_offset;
+       sljit_s32 saveds_offset;
 #endif
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       sljit_si mode32;
+       sljit_s32 mode32;
+#ifdef _WIN64
+       sljit_s32 locals_offset;
 #endif
-
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
-       sljit_si flags_saved;
 #endif
 
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
        /* Constant pool handling. */
        sljit_uw *cpool;
-       sljit_ub *cpool_unique;
+       sljit_u8 *cpool_unique;
        sljit_uw cpool_diff;
        sljit_uw cpool_fill;
        /* Other members. */
@@ -352,40 +354,33 @@ struct sljit_compiler {
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
        /* Temporary fields. */
        sljit_uw shift_imm;
-       sljit_si cache_arg;
-       sljit_sw cache_argw;
-#endif
-
-#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
-       sljit_si cache_arg;
-       sljit_sw cache_argw;
 #endif
 
 #if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
-       sljit_si cache_arg;
+       sljit_s32 cache_arg;
        sljit_sw cache_argw;
 #endif
 
 #if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
        sljit_sw imm;
-       sljit_si cache_arg;
+       sljit_s32 cache_arg;
        sljit_sw cache_argw;
 #endif
 
 #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
-       sljit_si delay_slot;
-       sljit_si cache_arg;
+       sljit_s32 delay_slot;
+       sljit_s32 cache_arg;
        sljit_sw cache_argw;
 #endif
 
 #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
-       sljit_si delay_slot;
-       sljit_si cache_arg;
+       sljit_s32 delay_slot;
+       sljit_s32 cache_arg;
        sljit_sw cache_argw;
 #endif
 
 #if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
-       sljit_si cache_arg;
+       sljit_s32 cache_arg;
        sljit_sw cache_argw;
 #endif
 
@@ -395,14 +390,18 @@ struct sljit_compiler {
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
                || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       /* Flags specified by the last arithmetic instruction.
+          It contains the type of the variable flag. */
+       sljit_s32 last_flags;
        /* Local size passed to the functions. */
-       sljit_si logical_local_size;
+       sljit_s32 logical_local_size;
 #endif
 
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
                || (defined SLJIT_DEBUG && SLJIT_DEBUG) \
                || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
-       sljit_si skip_checks;
+       /* Trust arguments when the API function is called. */
+       sljit_s32 skip_checks;
 #endif
 };
 
@@ -427,7 +426,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compile
    error code. Thus there is no need for checking the error after every
    call, it is enough to do it before the code is compiled. Removing
    these checks increases the performance of the compiling process. */
-static SLJIT_INLINE sljit_si sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
+static SLJIT_INLINE sljit_s32 sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
 
 /* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED except
    if an error was detected before. After the error code is set
@@ -448,26 +447,74 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compi
    indicate that there is no more memory (does not set the current error code
    of the compiler to out-of-memory status).
 */
-SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_si size);
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size);
 
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
 /* Passing NULL disables verbose. */
 SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose);
 #endif
 
+/*
+   Create executable code from the sljit instruction stream. This is the final step
+   of the code generation so no more instructions can be added after this call.
+*/
+
 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler);
+
+/* Free executable code. */
+
 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code);
 
 /*
-   After the machine code generation is finished we can retrieve the allocated
-   executable memory size, although this area may not be fully filled with
-   instructions depending on some optimizations. This function is useful only
-   for statistical purposes.
+   When the protected executable allocator is used the JIT code is mapped
+   twice. The first mapping has read/write and the second mapping has read/exec
+   permissions. This function returns with the relative offset of the executable
+   mapping using the writable mapping as the base after the machine code is
+   successfully generated. The returned value is always 0 for the normal executable
+   allocator, since it uses only one mapping with read/write/exec permissions.
+   Dynamic code modifications requires this value.
+
+   Before a successful code generation, this function returns with 0.
+*/
+static SLJIT_INLINE sljit_sw sljit_get_executable_offset(struct sljit_compiler *compiler) { return compiler->executable_offset; }
+
+/*
+   The executable memory consumption of the generated code can be retrieved by
+   this function. The returned value can be used for statistical purposes.
 
    Before a successful code generation, this function returns with 0.
 */
 static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }
 
+/* Returns with non-zero if the feature or limitation type passed as its
+   argument is present on the current CPU.
+
+   Some features (e.g. floating point operations) require hardware (CPU)
+   support while others (e.g. move with update) are emulated if not available.
+   However even if a feature is emulated, specialized code paths can be faster
+   than the emulation. Some limitations are emulated as well so their general
+   case is supported but it has extra performance costs. */
+
+/* [Not emulated] Floating-point support is available. */
+#define SLJIT_HAS_FPU                  0
+/* [Limitation] Some registers are virtual registers. */
+#define SLJIT_HAS_VIRTUAL_REGISTERS    1
+/* [Emulated] Some forms of move with pre update is supported. */
+#define SLJIT_HAS_PRE_UPDATE           2
+/* [Emulated] Count leading zero is supported. */
+#define SLJIT_HAS_CLZ                  3
+/* [Emulated] Conditional move is supported. */
+#define SLJIT_HAS_CMOV                 4
+/* [Limitation] [Emulated] Shifting with register is limited to SLJIT_PREF_SHIFT_REG. */
+#define SLJIT_HAS_PREF_SHIFT_REG       5
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+/* [Not emulated] SSE2 support is available on x86. */
+#define SLJIT_HAS_SSE2                 100
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type);
+
 /* Instruction generation. Returns with any error code. If there is no
    error, they return with SLJIT_SUCCESS. */
 
@@ -512,15 +559,15 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
 */
 
 /* The absolute address returned by sljit_get_local_base with
-offset 0 is aligned to sljit_d. Otherwise it is aligned to sljit_uw. */
-#define SLJIT_DOUBLE_ALIGNMENT 0x00000001
+offset 0 is aligned to sljit_f64. Otherwise it is aligned to sljit_sw. */
+#define SLJIT_F64_ALIGNMENT 0x00000001
 
 /* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */
 #define SLJIT_MAX_LOCAL_SIZE   65536
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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);
 
 /* The machine code has a context (which contains the local stack space size,
    number of used registers, etc.) which initialized by sljit_emit_enter. Several
@@ -532,9 +579,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
    Note: every call of sljit_emit_enter and sljit_set_context overwrites
          the previous context. */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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);
 
 /* Return from machine code.  The op argument can be SLJIT_UNUSED which means the
    function does not return with anything or any opcode between SLJIT_MOV and
@@ -542,8 +589,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
    is SLJIT_UNUSED, otherwise see below the description about source and
    destination arguments. */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si src, sljit_sw srcw);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src, sljit_sw srcw);
 
 /* Fast calling mechanism for utility functions (see SLJIT_FAST_CALL). All registers and
    even the stack frame is passed to the callee. The return address is preserved in
@@ -555,13 +602,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
    and setting up a new stack frame would cost too much performance. However, it is still
    possible to return to the address of the caller (or anywhere else). */
 
-/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */
+/* Note: may destroy flags. */
 
 /* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested,
    since many architectures do clever branch prediction on call / return instruction pairs. */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw);
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw);
 
 /*
    Source and destination values for arithmetical instructions
@@ -624,59 +671,97 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
 #define SLJIT_MEM2(r1, r2)     (SLJIT_MEM | (r1) | ((r2) << 8))
 #define SLJIT_IMM              0x40
 
-/* Set 32 bit operation mode (I) on 64 bit CPUs. The flag is totally ignored on
-   32 bit CPUs. If this flag is set for an arithmetic operation, it uses only the
-   lower 32 bit of the input register(s), and set the CPU status flags according
-   to the 32 bit result. The higher 32 bits are undefined for both the input and
-   output. However, the CPU might not ignore those higher 32 bits, like MIPS, which
-   expects it to be the sign extension of the lower 32 bit. All 32 bit operations
-   are undefined, if this condition is not fulfilled. Therefore, when SLJIT_INT_OP
-   is specified, all register arguments must be the result of other operations with
-   the same SLJIT_INT_OP flag. In other words, although a register can hold either
-   a 64 or 32 bit value, these values cannot be mixed. The only exceptions are
-   SLJIT_IMOV and SLJIT_IMOVU (SLJIT_MOV_SI/SLJIT_MOVU_SI with SLJIT_INT_OP flag)
-   which can convert any source argument to SLJIT_INT_OP compatible result. This
-   conversion might be unnecessary on some CPUs like x86-64, since the upper 32
-   bit is always ignored. In this case SLJIT is clever enough to not generate any
-   instructions if the source and destination operands are the same registers.
-   Affects sljit_emit_op0, sljit_emit_op1 and sljit_emit_op2. */
-#define SLJIT_INT_OP           0x100
-
-/* Single precision mode (SP). This flag is similar to SLJIT_INT_OP, just
-   it applies to floating point registers (it is even the same bit). When
-   this flag is passed, the CPU performs single precision floating point
-   operations. Similar to SLJIT_INT_OP, all register arguments must be the
-   result of other floating point operations with this flag. Affects
-   sljit_emit_fop1, sljit_emit_fop2 and sljit_emit_fcmp. */
-#define SLJIT_SINGLE_OP                0x100
-
-/* Common CPU status flags for all architectures (x86, ARM, PPC)
-    - carry flag
-    - overflow flag
-    - zero flag
-    - negative/positive flag (depends on arc)
-   On mips, these flags are emulated by software. */
-
-/* By default, the instructions may, or may not set the CPU status flags.
-   Forcing to set or keep status flags can be done with the following flags: */
-
-/* Note: sljit tries to emit the minimum number of instructions. Using these
-   flags can increase them, so use them wisely to avoid unnecessary code generation. */
-
-/* Set Equal (Zero) status flag (E). */
-#define SLJIT_SET_E                    0x0200
-/* Set unsigned status flag (U). */
-#define SLJIT_SET_U                    0x0400
-/* Set signed status flag (S). */
-#define SLJIT_SET_S                    0x0800
-/* Set signed overflow flag (O). */
-#define SLJIT_SET_O                    0x1000
-/* Set carry flag (C).
-   Note: Kinda unsigned overflow, but behaves differently on various cpus. */
-#define SLJIT_SET_C                    0x2000
-/* Do not modify the flags (K).
-   Note: This flag cannot be combined with any other SLJIT_SET_* flag. */
-#define SLJIT_KEEP_FLAGS               0x4000
+/* Set 32 bit operation mode (I) on 64 bit CPUs. This option is ignored on
+   32 bit CPUs. When this option is set for an arithmetic operation, only
+   the lower 32 bit of the input registers are used, and the CPU status
+   flags are set according to the 32 bit result. Although the higher 32 bit
+   of the input and the result registers are not defined by SLJIT, it might
+   be defined by the CPU architecture (e.g. MIPS). To satisfy these CPU
+   requirements all source registers must be the result of those operations
+   where this option was also set. Memory loads read 32 bit values rather
+   than 64 bit ones. In other words 32 bit and 64 bit operations cannot
+   be mixed. The only exception is SLJIT_MOV32 and SLJIT_MOVU32 whose source
+   register can hold any 32 or 64 bit value, and it is converted to a 32 bit
+   compatible format first. This conversion is free (no instructions are
+   emitted) on most CPUs. A 32 bit value can also be coverted to a 64 bit
+   value by SLJIT_MOV_S32 (sign extension) or SLJIT_MOV_U32 (zero extension).
+
+   Note: memory addressing always uses 64 bit values on 64 bit systems so
+         the result of a 32 bit operation must not be used with SLJIT_MEMx
+         macros.
+
+   This option is part of the instruction name, so there is no need to
+   manually set it. E.g:
+
+     SLJIT_ADD32 == (SLJIT_ADD | SLJIT_I32_OP) */
+#define SLJIT_I32_OP           0x100
+
+/* Set F32 (single) precision mode for floating-point computation. This
+   option is similar to SLJIT_I32_OP, it just applies to floating point
+   registers. When this option is passed, the CPU performs 32 bit floating
+   point operations, rather than 64 bit one. Similar to SLJIT_I32_OP, all
+   register arguments must be the result of those operations where this
+   option was also set.
+
+   This option is part of the instruction name, so there is no need to
+   manually set it. E.g:
+
+     SLJIT_MOV_F32 = (SLJIT_MOV_F64 | SLJIT_F32_OP)
+ */
+#define SLJIT_F32_OP           SLJIT_I32_OP
+
+/* Many CPUs (x86, ARM, PPC) has status flags which can be set according
+   to the result of an operation. Other CPUs (MIPS) does not have status
+   flags, and results must be stored in registers. To cover both architecture
+   types efficiently only two flags are defined by SLJIT:
+
+    * Zero (equal) flag: it is set if the result is zero
+    * Variable flag: its value is defined by the last arithmetic operation
+
+   SLJIT instructions can set any or both of these flags. The value of
+   these flags is undefined if the instruction does not specify their value.
+   The description of each instruction contains the list of allowed flag
+   types.
+
+   Example: SLJIT_ADD can set the Z, OVERFLOW, CARRY flags hence
+
+     sljit_op2(..., SLJIT_ADD, ...)
+       Both the zero and variable flags are undefined so they can
+       have any value after the operation is completed.
+
+     sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z, ...)
+       Sets the zero flag if the result is zero, clears it otherwise.
+       The variable flag is undefined.
+
+     sljit_op2(..., SLJIT_ADD | SLJIT_SET_OVERFLOW, ...)
+       Sets the variable flag if an integer overflow occurs, clears
+       it otherwise. The zero flag is undefined.
+
+     sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z | SLJIT_SET_CARRY, ...)
+       Sets the zero flag if the result is zero, clears it otherwise.
+       Sets the variable flag if unsigned overflow (carry) occurs,
+       clears it otherwise.
+
+   If an instruction (e.g. SLJIT_MOV) does not modify flags the flags are
+   unchanged.
+
+   Using these flags can reduce the number of emitted instructions. E.g. a
+   fast loop can be implemented by decreasing a counter register and set the
+   zero flag to jump back if the counter register is not reached zero.
+
+   Motivation: although CPUs can set a large number of flags, usually their
+   values are ignored or only one of them is used. Emulating a large number
+   of flags on systems without flag register is complicated so SLJIT
+   instructions must specify the flag they want to use and only that flag
+   will be emulated. The last arithmetic instruction can be repeated if
+   multiple flags needs to be checked.
+*/
+
+/* Set Zero status flag. */
+#define SLJIT_SET_Z                    0x0200
+/* Set the variable status flag if condition is true.
+   See comparison types. */
+#define SLJIT_SET(condition)                   ((condition) << 10)
 
 /* Notes:
      - you cannot postpone conditional jump instructions except if noted that
@@ -686,254 +771,286 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
 /* Starting index of opcodes for sljit_emit_op0. */
 #define SLJIT_OP0_BASE                 0
 
-/* Flags: - (never set any flags)
+/* Flags: - (does not modify flags)
    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)
+/* Flags: - (does not modify flags)
    Note: may or may not cause an extra cycle wait
          it can even decrease the runtime in a few cases. */
 #define SLJIT_NOP                      (SLJIT_OP0_BASE + 1)
 /* Flags: - (may destroy flags)
    Unsigned multiplication of SLJIT_R0 and SLJIT_R1.
    Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
-#define SLJIT_LUMUL                    (SLJIT_OP0_BASE + 2)
+#define SLJIT_LMUL_UW                  (SLJIT_OP0_BASE + 2)
 /* Flags: - (may destroy flags)
    Signed multiplication of SLJIT_R0 and SLJIT_R1.
    Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
-#define SLJIT_LSMUL                    (SLJIT_OP0_BASE + 3)
-/* Flags: - (may destroy flags)
+#define SLJIT_LMUL_SW                  (SLJIT_OP0_BASE + 3)
+/* Flags: - (may destroy flags)
    Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
    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: - (may destroy flags)
+#define SLJIT_DIVMOD_UW                        (SLJIT_OP0_BASE + 4)
+#define SLJIT_DIVMOD_U32               (SLJIT_DIVMOD_UW | SLJIT_I32_OP)
+/* Flags: - (may destroy flags)
    Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
    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: - (may destroy flags)
+#define SLJIT_DIVMOD_SW                        (SLJIT_OP0_BASE + 5)
+#define SLJIT_DIVMOD_S32               (SLJIT_DIVMOD_SW | SLJIT_I32_OP)
+/* Flags: - (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)
+   Note: if SLJIT_R1 is 0, the behaviour is undefined. */
+#define SLJIT_DIV_UW                   (SLJIT_OP0_BASE + 6)
+#define SLJIT_DIV_U32                  (SLJIT_DIV_UW | SLJIT_I32_OP)
+/* Flags: - (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)
+         the behaviour is undefined. */
+#define SLJIT_DIV_SW                   (SLJIT_OP0_BASE + 7)
+#define SLJIT_DIV_S32                  (SLJIT_DIV_SW | SLJIT_I32_OP)
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op);
 
 /* Starting index of opcodes for sljit_emit_op1. */
 #define SLJIT_OP1_BASE                 32
 
-/* Notes for MOV instructions:
-   U = Mov with update (pre form). If source or destination defined as SLJIT_MEM1(r1)
-       or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument
-   UB = unsigned byte (8 bit)
-   SB = signed byte (8 bit)
-   UH = unsigned half (16 bit)
-   SH = signed half (16 bit)
-   UI = unsigned int (32 bit)
-   SI = signed int (32 bit)
-   P  = pointer (sljit_p) size */
-
-/* Flags: - (never set any flags) */
+/* The MOV instruction transfer data from source to destination.
+
+   MOV instruction suffixes:
+
+   U8  - unsigned 8 bit data transfer
+   S8  - signed 8 bit data transfer
+   U16 - unsigned 16 bit data transfer
+   S16 - signed 16 bit data transfer
+   U32 - unsigned int (32 bit) data transfer
+   S32 - signed int (32 bit) data transfer
+   P   - pointer (sljit_p) data transfer
+
+   U = move with update (pre form). If source or destination defined as
+       SLJIT_MEM1(r1) or SLJIT_MEM2(r1, r2), r1 is increased by the
+       offset part of the address.
+
+   Register arguments and base registers can only be used once for move
+   with update instructions. The shift value of SLJIT_MEM2 addressing
+   mode must also be 0. Reason: SLJIT_MOVU instructions are expected to
+   be in high-performance loops where complex instruction emulation
+   would be too costly.
+
+   Examples for invalid move with update instructions:
+
+   sljit_emit_op1(..., SLJIT_MOVU_U8,
+       SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 8);
+   sljit_emit_op1(..., SLJIT_MOVU_U8,
+       SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_R0, 0);
+   sljit_emit_op1(..., SLJIT_MOVU_U8,
+       SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 0, SLJIT_MEM1(SLJIT_R0), 8);
+   sljit_emit_op1(..., SLJIT_MOVU_U8,
+       SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0);
+   sljit_emit_op1(..., SLJIT_MOVU_U8,
+       SLJIT_R2, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1);
+
+   The following example is valid, since only the offset register is
+   used multiple times:
+
+   sljit_emit_op1(..., SLJIT_MOVU_U8,
+       SLJIT_MEM2(SLJIT_R0, SLJIT_R2), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);
+
+   If the destination of a MOV without update instruction is SLJIT_UNUSED
+   and the source operand is a memory address the compiler emits a prefetch
+   instruction if this instruction is supported by the current CPU.
+   Higher data sizes bring the data closer to the core: a MOV with word
+   size loads the data into a higher level cache than a byte size. Otherwise
+   the type does not affect the prefetch instruction. Furthermore a prefetch
+   instruction never fails, so it can be used to prefetch a data from an
+   address and check whether that address is NULL afterwards.
+*/
+
+/* Flags: - (does not modify flags) */
 #define SLJIT_MOV                      (SLJIT_OP1_BASE + 0)
-/* Flags: I - (never set any flags) */
-#define SLJIT_MOV_UB                   (SLJIT_OP1_BASE + 1)
-#define SLJIT_IMOV_UB                  (SLJIT_MOV_UB | SLJIT_INT_OP)
-/* Flags: I - (never set any flags) */
-#define SLJIT_MOV_SB                   (SLJIT_OP1_BASE + 2)
-#define SLJIT_IMOV_SB                  (SLJIT_MOV_SB | SLJIT_INT_OP)
-/* Flags: I - (never set any flags) */
-#define SLJIT_MOV_U                  (SLJIT_OP1_BASE + 3)
-#define SLJIT_IMOV_UH                  (SLJIT_MOV_UH | SLJIT_INT_OP)
-/* Flags: I - (never set any flags) */
-#define SLJIT_MOV_S                  (SLJIT_OP1_BASE + 4)
-#define SLJIT_IMOV_SH                  (SLJIT_MOV_SH | SLJIT_INT_OP)
-/* Flags: I - (never set any flags)
-   Note: see SLJIT_INT_OP for further details. */
-#define SLJIT_MOV_U                  (SLJIT_OP1_BASE + 5)
-/* No SLJIT_INT_OP form, since it is the same as SLJIT_IMOV. */
-/* Flags: I - (never set any flags)
-   Note: see SLJIT_INT_OP for further details. */
-#define SLJIT_MOV_SI                   (SLJIT_OP1_BASE + 6)
-#define SLJIT_IMOV                     (SLJIT_MOV_SI | SLJIT_INT_OP)
-/* Flags: - (never set any flags) */
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_U8                   (SLJIT_OP1_BASE + 1)
+#define SLJIT_MOV32_U8                 (SLJIT_MOV_U8 | SLJIT_I32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_S8                   (SLJIT_OP1_BASE + 2)
+#define SLJIT_MOV32_S8                 (SLJIT_MOV_S8 | SLJIT_I32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_U16                  (SLJIT_OP1_BASE + 3)
+#define SLJIT_MOV32_U16                        (SLJIT_MOV_U16 | SLJIT_I32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_S16                  (SLJIT_OP1_BASE + 4)
+#define SLJIT_MOV32_S16                        (SLJIT_MOV_S16 | SLJIT_I32_OP)
+/* Flags: - (does not modify flags)
+   Note: no SLJIT_MOV32_U32 form, since it is the same as SLJIT_MOV32 */
+#define SLJIT_MOV_U32                  (SLJIT_OP1_BASE + 5)
+/* Flags: - (does not modify flags)
+   Note: no SLJIT_MOV32_S32 form, since it is the same as SLJIT_MOV32 */
+#define SLJIT_MOV_S32                  (SLJIT_OP1_BASE + 6)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV32                    (SLJIT_MOV_S32 | SLJIT_I32_OP)
+/* Flags: - (does not modify flags) */
 #define SLJIT_MOV_P                    (SLJIT_OP1_BASE + 7)
-/* Flags: - (never set any flags) */
+/* Flags: - (may destroy flags) */
 #define SLJIT_MOVU                     (SLJIT_OP1_BASE + 8)
-/* Flags: I - (never set any flags) */
-#define SLJIT_MOVU_UB                  (SLJIT_OP1_BASE + 9)
-#define SLJIT_IMOVU_UB                 (SLJIT_MOVU_UB | SLJIT_INT_OP)
-/* Flags: I - (never set any flags) */
-#define SLJIT_MOVU_SB                  (SLJIT_OP1_BASE + 10)
-#define SLJIT_IMOVU_SB                 (SLJIT_MOVU_SB | SLJIT_INT_OP)
-/* Flags: I - (never set any flags) */
-#define SLJIT_MOVU_U                 (SLJIT_OP1_BASE + 11)
-#define SLJIT_IMOVU_UH                 (SLJIT_MOVU_UH | SLJIT_INT_OP)
-/* Flags: I - (never set any flags) */
-#define SLJIT_MOVU_S                 (SLJIT_OP1_BASE + 12)
-#define SLJIT_IMOVU_SH                 (SLJIT_MOVU_SH | SLJIT_INT_OP)
-/* Flags: I - (never set any flags)
-   Note: see SLJIT_INT_OP for further details. */
-#define SLJIT_MOVU_U                 (SLJIT_OP1_BASE + 13)
-/* No SLJIT_INT_OP form, since it is the same as SLJIT_IMOVU. */
-/* Flags: I - (never set any flags)
-   Note: see SLJIT_INT_OP for further details. */
-#define SLJIT_MOVU_SI                  (SLJIT_OP1_BASE + 14)
-#define SLJIT_IMOVU                    (SLJIT_MOVU_SI | SLJIT_INT_OP)
-/* Flags: - (never set any flags) */
+/* Flags: - (may destroy flags) */
+#define SLJIT_MOVU_U8                  (SLJIT_OP1_BASE + 9)
+#define SLJIT_MOVU32_U8                        (SLJIT_MOVU_U8 | SLJIT_I32_OP)
+/* Flags: - (may destroy flags) */
+#define SLJIT_MOVU_S8                  (SLJIT_OP1_BASE + 10)
+#define SLJIT_MOVU32_S8                        (SLJIT_MOVU_S8 | SLJIT_I32_OP)
+/* Flags: - (may destroy flags) */
+#define SLJIT_MOVU_U16                 (SLJIT_OP1_BASE + 11)
+#define SLJIT_MOVU32_U16                       (SLJIT_MOVU_U16 | SLJIT_I32_OP)
+/* Flags: - (may destroy flags) */
+#define SLJIT_MOVU_S16                 (SLJIT_OP1_BASE + 12)
+#define SLJIT_MOVU32_S16               (SLJIT_MOVU_S16 | SLJIT_I32_OP)
+/* Flags: - (may destroy flags)
+   Note: no SLJIT_MOVU32_U32 form, since it is the same as SLJIT_MOVU32 */
+#define SLJIT_MOVU_U32                 (SLJIT_OP1_BASE + 13)
+/* Flags: - (may destroy flags)
+   Note: no SLJIT_MOVU32_S32 form, since it is the same as SLJIT_MOVU32 */
+#define SLJIT_MOVU_S32                 (SLJIT_OP1_BASE + 14)
+/* Flags: - (may destroy flags) */
+#define SLJIT_MOVU32                   (SLJIT_MOVU_S32 | SLJIT_I32_OP)
+/* Flags: - (may destroy flags) */
 #define SLJIT_MOVU_P                   (SLJIT_OP1_BASE + 15)
-/* Flags: I | E | K */
+/* Flags: Z */
 #define SLJIT_NOT                      (SLJIT_OP1_BASE + 16)
-#define SLJIT_INOT                     (SLJIT_NOT | SLJIT_INT_OP)
-/* Flags: I | E | O | K */
+#define SLJIT_NOT32                    (SLJIT_NOT | SLJIT_I32_OP)
+/* Flags: Z | OVERFLOW */
 #define SLJIT_NEG                      (SLJIT_OP1_BASE + 17)
-#define SLJIT_INEG                     (SLJIT_NEG | SLJIT_INT_OP)
+#define SLJIT_NEG32                    (SLJIT_NEG | SLJIT_I32_OP)
 /* Count leading zeroes
-   Flags: I | E | K
-   Important note! Sparc 32 does not support K flag, since
-   the required popc instruction is introduced only in sparc 64. */
+   Flags: - (may destroy flags) */
 #define SLJIT_CLZ                      (SLJIT_OP1_BASE + 18)
-#define SLJIT_ICLZ                     (SLJIT_CLZ | SLJIT_INT_OP)
+#define SLJIT_CLZ32                    (SLJIT_CLZ | SLJIT_I32_OP)
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw);
 
 /* Starting index of opcodes for sljit_emit_op2. */
 #define SLJIT_OP2_BASE                 96
 
-/* Flags: I | E | O | C | K */
+/* Flags: Z | OVERFLOW | CARRY */
 #define SLJIT_ADD                      (SLJIT_OP2_BASE + 0)
-#define SLJIT_IADD                     (SLJIT_ADD | SLJIT_INT_OP)
-/* Flags: I | C | K */
+#define SLJIT_ADD32                    (SLJIT_ADD | SLJIT_I32_OP)
+/* Flags: CARRY */
 #define SLJIT_ADDC                     (SLJIT_OP2_BASE + 1)
-#define SLJIT_IADDC                    (SLJIT_ADDC | SLJIT_INT_OP)
-/* Flags: I | E | U | S | O | C | K */
+#define SLJIT_ADDC32                   (SLJIT_ADDC | SLJIT_I32_OP)
+/* Flags: Z | LESS | GREATER_EQUAL | GREATER | LESS_EQUAL
+          SIG_LESS | SIG_GREATER_EQUAL | SIG_GREATER
+          SIG_LESS_EQUAL | CARRY */
 #define SLJIT_SUB                      (SLJIT_OP2_BASE + 2)
-#define SLJIT_ISUB                     (SLJIT_SUB | SLJIT_INT_OP)
-/* Flags: I | C | K */
+#define SLJIT_SUB32                    (SLJIT_SUB | SLJIT_I32_OP)
+/* Flags: CARRY */
 #define SLJIT_SUBC                     (SLJIT_OP2_BASE + 3)
-#define SLJIT_ISUBC                    (SLJIT_SUBC | SLJIT_INT_OP)
+#define SLJIT_SUBC32                   (SLJIT_SUBC | SLJIT_I32_OP)
 /* Note: integer mul
-   Flags: I | O (see SLJIT_C_MUL_*) | K */
+   Flags: MUL_OVERFLOW */
 #define SLJIT_MUL                      (SLJIT_OP2_BASE + 4)
-#define SLJIT_IMUL                     (SLJIT_MUL | SLJIT_INT_OP)
-/* Flags: I | E | K */
+#define SLJIT_MUL32                    (SLJIT_MUL | SLJIT_I32_OP)
+/* Flags: Z */
 #define SLJIT_AND                      (SLJIT_OP2_BASE + 5)
-#define SLJIT_IAND                     (SLJIT_AND | SLJIT_INT_OP)
-/* Flags: I | E | K */
+#define SLJIT_AND32                    (SLJIT_AND | SLJIT_I32_OP)
+/* Flags: Z */
 #define SLJIT_OR                       (SLJIT_OP2_BASE + 6)
-#define SLJIT_IOR                      (SLJIT_OR | SLJIT_INT_OP)
-/* Flags: I | E | K */
+#define SLJIT_OR32                     (SLJIT_OR | SLJIT_I32_OP)
+/* Flags: Z */
 #define SLJIT_XOR                      (SLJIT_OP2_BASE + 7)
-#define SLJIT_IXOR                     (SLJIT_XOR | SLJIT_INT_OP)
-/* Flags: I | E | K
+#define SLJIT_XOR32                    (SLJIT_XOR | SLJIT_I32_OP)
+/* Flags: Z
    Let bit_length be the length of the shift operation: 32 or 64.
    If src2 is immediate, src2w is masked by (bit_length - 1).
    Otherwise, if the content of src2 is outside the range from 0
    to bit_length - 1, the result is undefined. */
 #define SLJIT_SHL                      (SLJIT_OP2_BASE + 8)
-#define SLJIT_ISHL                     (SLJIT_SHL | SLJIT_INT_OP)
-/* Flags: I | E | K
+#define SLJIT_SHL32                    (SLJIT_SHL | SLJIT_I32_OP)
+/* Flags: Z
    Let bit_length be the length of the shift operation: 32 or 64.
    If src2 is immediate, src2w is masked by (bit_length - 1).
    Otherwise, if the content of src2 is outside the range from 0
    to bit_length - 1, the result is undefined. */
 #define SLJIT_LSHR                     (SLJIT_OP2_BASE + 9)
-#define SLJIT_ILSHR                    (SLJIT_LSHR | SLJIT_INT_OP)
-/* Flags: I | E | K
+#define SLJIT_LSHR32                   (SLJIT_LSHR | SLJIT_I32_OP)
+/* Flags: Z
    Let bit_length be the length of the shift operation: 32 or 64.
    If src2 is immediate, src2w is masked by (bit_length - 1).
    Otherwise, if the content of src2 is outside the range from 0
    to bit_length - 1, the result is undefined. */
 #define SLJIT_ASHR                     (SLJIT_OP2_BASE + 10)
-#define SLJIT_IASHR                    (SLJIT_ASHR | SLJIT_INT_OP)
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w);
+#define SLJIT_ASHR32                   (SLJIT_ASHR | SLJIT_I32_OP)
 
-/* Returns with non-zero if fpu is available. */
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w);
 
 /* Starting index of opcodes for sljit_emit_fop1. */
 #define SLJIT_FOP1_BASE                        128
 
-/* Flags: SP - (never set any flags) */
-#define SLJIT_DMOV                     (SLJIT_FOP1_BASE + 0)
-#define SLJIT_SMOV                     (SLJIT_DMOV | SLJIT_SINGLE_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_F64                  (SLJIT_FOP1_BASE + 0)
+#define SLJIT_MOV_F32                  (SLJIT_MOV_F64 | SLJIT_F32_OP)
 /* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE]
    SRC/DST TYPE can be: D - double, S - single, W - signed word, I - signed int
    Rounding mode when the destination is W or I: round towards zero. */
-/* Flags: SP - (never set any flags) */
-#define SLJIT_CONVD_FROMS              (SLJIT_FOP1_BASE + 1)
-#define SLJIT_CONVS_FROMD              (SLJIT_CONVD_FROMS | SLJIT_SINGLE_OP)
-/* Flags: SP - (never set any flags) */
-#define SLJIT_CONVW_FROMD              (SLJIT_FOP1_BASE + 2)
-#define SLJIT_CONVW_FROMS              (SLJIT_CONVW_FROMD | SLJIT_SINGLE_OP)
-/* Flags: SP - (never set any flags) */
-#define SLJIT_CONVI_FROMD              (SLJIT_FOP1_BASE + 3)
-#define SLJIT_CONVI_FROMS              (SLJIT_CONVI_FROMD | SLJIT_SINGLE_OP)
-/* Flags: SP - (never set any flags) */
-#define SLJIT_CONVD_FROMW              (SLJIT_FOP1_BASE + 4)
-#define SLJIT_CONVS_FROMW              (SLJIT_CONVD_FROMW | SLJIT_SINGLE_OP)
-/* Flags: SP - (never set any flags) */
-#define SLJIT_CONVD_FROMI              (SLJIT_FOP1_BASE + 5)
-#define SLJIT_CONVS_FROMI              (SLJIT_CONVD_FROMI | SLJIT_SINGLE_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_CONV_F64_FROM_F32                (SLJIT_FOP1_BASE + 1)
+#define SLJIT_CONV_F32_FROM_F64                (SLJIT_CONV_F64_FROM_F32 | SLJIT_F32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_CONV_SW_FROM_F64         (SLJIT_FOP1_BASE + 2)
+#define SLJIT_CONV_SW_FROM_F32         (SLJIT_CONV_SW_FROM_F64 | SLJIT_F32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_CONV_S32_FROM_F64                (SLJIT_FOP1_BASE + 3)
+#define SLJIT_CONV_S32_FROM_F32                (SLJIT_CONV_S32_FROM_F64 | SLJIT_F32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_CONV_F64_FROM_SW         (SLJIT_FOP1_BASE + 4)
+#define SLJIT_CONV_F32_FROM_SW         (SLJIT_CONV_F64_FROM_SW | SLJIT_F32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_CONV_F64_FROM_S32                (SLJIT_FOP1_BASE + 5)
+#define SLJIT_CONV_F32_FROM_S32                (SLJIT_CONV_F64_FROM_S32 | SLJIT_F32_OP)
 /* Note: dst is the left and src is the right operand for SLJIT_CMPD.
-   Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED flag
-         is set, the comparison result is unpredictable.
-   Flags: SP | E | S (see SLJIT_C_FLOAT_*) */
-#define SLJIT_DCMP                     (SLJIT_FOP1_BASE + 6)
-#define SLJIT_SCMP                     (SLJIT_DCMP | SLJIT_SINGLE_OP)
-/* Flags: SP - (never set any flags) */
-#define SLJIT_DNEG                     (SLJIT_FOP1_BASE + 7)
-#define SLJIT_SNEG                     (SLJIT_DNEG | SLJIT_SINGLE_OP)
-/* Flags: SP - (never set any flags) */
-#define SLJIT_DABS                     (SLJIT_FOP1_BASE + 8)
-#define SLJIT_SABS                     (SLJIT_DABS | SLJIT_SINGLE_OP)
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw);
+   Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */
+#define SLJIT_CMP_F64                  (SLJIT_FOP1_BASE + 6)
+#define SLJIT_CMP_F32                  (SLJIT_CMP_F64 | SLJIT_F32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_NEG_F64                  (SLJIT_FOP1_BASE + 7)
+#define SLJIT_NEG_F32                  (SLJIT_NEG_F64 | SLJIT_F32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_ABS_F64                  (SLJIT_FOP1_BASE + 8)
+#define SLJIT_ABS_F32                  (SLJIT_ABS_F64 | SLJIT_F32_OP)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw);
 
 /* Starting index of opcodes for sljit_emit_fop2. */
 #define SLJIT_FOP2_BASE                        160
 
-/* Flags: SP - (never set any flags) */
-#define SLJIT_DADD                     (SLJIT_FOP2_BASE + 0)
-#define SLJIT_SADD                     (SLJIT_DADD | SLJIT_SINGLE_OP)
-/* Flags: SP - (never set any flags) */
-#define SLJIT_DSUB                     (SLJIT_FOP2_BASE + 1)
-#define SLJIT_SSUB                     (SLJIT_DSUB | SLJIT_SINGLE_OP)
-/* Flags: SP - (never set any flags) */
-#define SLJIT_DMUL                     (SLJIT_FOP2_BASE + 2)
-#define SLJIT_SMUL                     (SLJIT_DMUL | SLJIT_SINGLE_OP)
-/* Flags: SP - (never set any flags) */
-#define SLJIT_DDIV                     (SLJIT_FOP2_BASE + 3)
-#define SLJIT_SDIV                     (SLJIT_DDIV | SLJIT_SINGLE_OP)
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w);
+/* Flags: - (does not modify flags) */
+#define SLJIT_ADD_F64                  (SLJIT_FOP2_BASE + 0)
+#define SLJIT_ADD_F32                  (SLJIT_ADD_F64 | SLJIT_F32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_SUB_F64                  (SLJIT_FOP2_BASE + 1)
+#define SLJIT_SUB_F32                  (SLJIT_SUB_F64 | SLJIT_F32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MUL_F64                  (SLJIT_FOP2_BASE + 2)
+#define SLJIT_MUL_F32                  (SLJIT_MUL_F64 | SLJIT_F32_OP)
+/* Flags: - (does not modify flags) */
+#define SLJIT_DIV_F64                  (SLJIT_FOP2_BASE + 3)
+#define SLJIT_DIV_F32                  (SLJIT_DIV_F64 | SLJIT_F32_OP)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w);
 
 /* Label and jump instructions. */
 
@@ -943,66 +1060,87 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
 
 /* Integer comparison types. */
 #define SLJIT_EQUAL                    0
-#define SLJIT_I_EQUAL                  (SLJIT_EQUAL | SLJIT_INT_OP)
+#define SLJIT_EQUAL32                  (SLJIT_EQUAL | SLJIT_I32_OP)
 #define SLJIT_ZERO                     0
-#define SLJIT_I_ZERO                   (SLJIT_ZERO | SLJIT_INT_OP)
+#define SLJIT_ZERO32                   (SLJIT_ZERO | SLJIT_I32_OP)
 #define SLJIT_NOT_EQUAL                        1
-#define SLJIT_I_NOT_EQUAL              (SLJIT_NOT_EQUAL | SLJIT_INT_OP)
+#define SLJIT_NOT_EQUAL32              (SLJIT_NOT_EQUAL | SLJIT_I32_OP)
 #define SLJIT_NOT_ZERO                 1
-#define SLJIT_I_NOT_ZERO               (SLJIT_NOT_ZERO | SLJIT_INT_OP)
+#define SLJIT_NOT_ZERO32               (SLJIT_NOT_ZERO | SLJIT_I32_OP)
 
 #define SLJIT_LESS                     2
-#define SLJIT_I_LESS                   (SLJIT_LESS | SLJIT_INT_OP)
+#define SLJIT_LESS32                   (SLJIT_LESS | SLJIT_I32_OP)
+#define SLJIT_SET_LESS                 SLJIT_SET(SLJIT_LESS)
 #define SLJIT_GREATER_EQUAL            3
-#define SLJIT_I_GREATER_EQUAL          (SLJIT_GREATER_EQUAL | SLJIT_INT_OP)
+#define SLJIT_GREATER_EQUAL32          (SLJIT_GREATER_EQUAL | SLJIT_I32_OP)
+#define SLJIT_SET_GREATER_EQUAL                SLJIT_SET(SLJIT_GREATER_EQUAL)
 #define SLJIT_GREATER                  4
-#define SLJIT_I_GREATER                        (SLJIT_GREATER | SLJIT_INT_OP)
+#define SLJIT_GREATER32                        (SLJIT_GREATER | SLJIT_I32_OP)
+#define SLJIT_SET_GREATER              SLJIT_SET(SLJIT_GREATER)
 #define SLJIT_LESS_EQUAL               5
-#define SLJIT_I_LESS_EQUAL             (SLJIT_LESS_EQUAL | SLJIT_INT_OP)
+#define SLJIT_LESS_EQUAL32             (SLJIT_LESS_EQUAL | SLJIT_I32_OP)
+#define SLJIT_SET_LESS_EQUAL           SLJIT_SET(SLJIT_LESS_EQUAL)
 #define SLJIT_SIG_LESS                 6
-#define SLJIT_I_SIG_LESS               (SLJIT_SIG_LESS | SLJIT_INT_OP)
+#define SLJIT_SIG_LESS32               (SLJIT_SIG_LESS | SLJIT_I32_OP)
+#define SLJIT_SET_SIG_LESS             SLJIT_SET(SLJIT_SIG_LESS)
 #define SLJIT_SIG_GREATER_EQUAL                7
-#define SLJIT_I_SIG_GREATER_EQUAL      (SLJIT_SIG_GREATER_EQUAL | SLJIT_INT_OP)
+#define SLJIT_SIG_GREATER_EQUAL32      (SLJIT_SIG_GREATER_EQUAL | SLJIT_I32_OP)
+#define SLJIT_SET_SIG_GREATER_EQUAL    SLJIT_SET(SLJIT_SIG_GREATER_EQUAL)
 #define SLJIT_SIG_GREATER              8
-#define SLJIT_I_SIG_GREATER            (SLJIT_SIG_GREATER | SLJIT_INT_OP)
+#define SLJIT_SIG_GREATER32            (SLJIT_SIG_GREATER | SLJIT_I32_OP)
+#define SLJIT_SET_SIG_GREATER          SLJIT_SET(SLJIT_SIG_GREATER)
 #define SLJIT_SIG_LESS_EQUAL           9
-#define SLJIT_I_SIG_LESS_EQUAL         (SLJIT_SIG_LESS_EQUAL | SLJIT_INT_OP)
+#define SLJIT_SIG_LESS_EQUAL32         (SLJIT_SIG_LESS_EQUAL | SLJIT_I32_OP)
+#define SLJIT_SET_SIG_LESS_EQUAL       SLJIT_SET(SLJIT_SIG_LESS_EQUAL)
 
 #define SLJIT_OVERFLOW                 10
-#define SLJIT_I_OVERFLOW               (SLJIT_OVERFLOW | SLJIT_INT_OP)
+#define SLJIT_OVERFLOW32               (SLJIT_OVERFLOW | SLJIT_I32_OP)
+#define SLJIT_SET_OVERFLOW             SLJIT_SET(SLJIT_OVERFLOW)
 #define SLJIT_NOT_OVERFLOW             11
-#define SLJIT_I_NOT_OVERFLOW           (SLJIT_NOT_OVERFLOW | SLJIT_INT_OP)
+#define SLJIT_NOT_OVERFLOW32           (SLJIT_NOT_OVERFLOW | SLJIT_I32_OP)
 
 #define SLJIT_MUL_OVERFLOW             12
-#define SLJIT_I_MUL_OVERFLOW           (SLJIT_MUL_OVERFLOW | SLJIT_INT_OP)
+#define SLJIT_MUL_OVERFLOW32           (SLJIT_MUL_OVERFLOW | SLJIT_I32_OP)
+#define SLJIT_SET_MUL_OVERFLOW         SLJIT_SET(SLJIT_MUL_OVERFLOW)
 #define SLJIT_MUL_NOT_OVERFLOW         13
-#define SLJIT_I_MUL_NOT_OVERFLOW       (SLJIT_MUL_NOT_OVERFLOW | SLJIT_INT_OP)
+#define SLJIT_MUL_NOT_OVERFLOW32       (SLJIT_MUL_NOT_OVERFLOW | SLJIT_I32_OP)
+
+/* There is no SLJIT_CARRY or SLJIT_NOT_CARRY. */
+#define SLJIT_SET_CARRY                        SLJIT_SET(14)
 
 /* Floating point comparison types. */
-#define SLJIT_D_EQUAL                  14
-#define SLJIT_S_EQUAL                  (SLJIT_D_EQUAL | SLJIT_SINGLE_OP)
-#define SLJIT_D_NOT_EQUAL              15
-#define SLJIT_S_NOT_EQUAL              (SLJIT_D_NOT_EQUAL | SLJIT_SINGLE_OP)
-#define SLJIT_D_LESS                   16
-#define SLJIT_S_LESS                   (SLJIT_D_LESS | SLJIT_SINGLE_OP)
-#define SLJIT_D_GREATER_EQUAL          17
-#define SLJIT_S_GREATER_EQUAL          (SLJIT_D_GREATER_EQUAL | SLJIT_SINGLE_OP)
-#define SLJIT_D_GREATER                        18
-#define SLJIT_S_GREATER                        (SLJIT_D_GREATER | SLJIT_SINGLE_OP)
-#define SLJIT_D_LESS_EQUAL             19
-#define SLJIT_S_LESS_EQUAL             (SLJIT_D_LESS_EQUAL | SLJIT_SINGLE_OP)
-#define SLJIT_D_UNORDERED              20
-#define SLJIT_S_UNORDERED              (SLJIT_D_UNORDERED | SLJIT_SINGLE_OP)
-#define SLJIT_D_ORDERED                        21
-#define SLJIT_S_ORDERED                        (SLJIT_D_ORDERED | SLJIT_SINGLE_OP)
+#define SLJIT_EQUAL_F64                        16
+#define SLJIT_EQUAL_F32                        (SLJIT_EQUAL_F64 | SLJIT_F32_OP)
+#define SLJIT_SET_EQUAL_F              SLJIT_SET(SLJIT_EQUAL_F64)
+#define SLJIT_NOT_EQUAL_F64            17
+#define SLJIT_NOT_EQUAL_F32            (SLJIT_NOT_EQUAL_F64 | SLJIT_F32_OP)
+#define SLJIT_SET_NOT_EQUAL_F          SLJIT_SET(SLJIT_NOT_EQUAL_F64)
+#define SLJIT_LESS_F64                 18
+#define SLJIT_LESS_F32                 (SLJIT_LESS_F64 | SLJIT_F32_OP)
+#define SLJIT_SET_LESS_F               SLJIT_SET(SLJIT_LESS_F64)
+#define SLJIT_GREATER_EQUAL_F64                19
+#define SLJIT_GREATER_EQUAL_F32                (SLJIT_GREATER_EQUAL_F64 | SLJIT_F32_OP)
+#define SLJIT_SET_GREATER_EQUAL_F      SLJIT_SET(SLJIT_GREATER_EQUAL_F64)
+#define SLJIT_GREATER_F64              20
+#define SLJIT_GREATER_F32              (SLJIT_GREATER_F64 | SLJIT_F32_OP)
+#define SLJIT_SET_GREATER_F            SLJIT_SET(SLJIT_GREATER_F64)
+#define SLJIT_LESS_EQUAL_F64           21
+#define SLJIT_LESS_EQUAL_F32           (SLJIT_LESS_EQUAL_F64 | SLJIT_F32_OP)
+#define SLJIT_SET_LESS_EQUAL_F         SLJIT_SET(SLJIT_LESS_EQUAL_F64)
+#define SLJIT_UNORDERED_F64            22
+#define SLJIT_UNORDERED_F32            (SLJIT_UNORDERED_F64 | SLJIT_F32_OP)
+#define SLJIT_SET_UNORDERED_F          SLJIT_SET(SLJIT_UNORDERED_F64)
+#define SLJIT_ORDERED_F64              23
+#define SLJIT_ORDERED_F32              (SLJIT_ORDERED_F64 | SLJIT_F32_OP)
+#define SLJIT_SET_ORDERED_F            SLJIT_SET(SLJIT_ORDERED_F64)
 
 /* Unconditional jump types. */
-#define SLJIT_JUMP                     22
-#define SLJIT_FAST_CALL                        23
-#define SLJIT_CALL0                    24
-#define SLJIT_CALL1                    25
-#define SLJIT_CALL2                    26
-#define SLJIT_CALL3                    27
+#define SLJIT_JUMP                     24
+#define SLJIT_FAST_CALL                        25
+#define SLJIT_CALL0                    26
+#define SLJIT_CALL1                    27
+#define SLJIT_CALL2                    28
+#define SLJIT_CALL3                    29
 
 /* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */
 
@@ -1012,9 +1150,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
 /* Emit a jump instruction. The destination is not set, only the type of the jump.
     type must be between SLJIT_EQUAL and SLJIT_CALL3
     type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
-   Flags: - (never set any flags) for both conditional and unconditional jumps.
-   Flags: destroy all flags for calls. */
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type);
+
+   Flags: does not modify flags for conditional and unconditional
+          jumps but destroy all flags for calls. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type);
 
 /* Basic arithmetic comparison. In most architectures it is implemented as
    an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting
@@ -1023,24 +1162,24 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
    It is suggested to use this comparison form when appropriate.
     type must be between SLJIT_EQUAL and SLJIT_I_SIG_LESS_EQUAL
     type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
-   Flags: destroy flags. */
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w);
+   Flags: may destroy flags. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w);
 
 /* Basic floating point comparison. In most architectures it is implemented as
    an SLJIT_FCMP operation (setting appropriate flags) followed by a
    sljit_emit_jump. However some architectures (i.e: MIPS) may employ
    special optimizations here. It is suggested to use this comparison form
    when appropriate.
-    type must be between SLJIT_D_EQUAL and SLJIT_S_ORDERED
+    type must be between SLJIT_EQUAL_F64 and SLJIT_ORDERED_F32
     type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
    Flags: destroy flags.
    Note: if either operand is NaN, the behaviour is undefined for
          types up to SLJIT_S_LESS_EQUAL. */
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w);
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w);
 
 /* Set the destination of the jump to this label. */
 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);
@@ -1051,37 +1190,48 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
     type must be between SLJIT_JUMP and SLJIT_CALL3
     Direct form: set src to SLJIT_IMM() and srcw to the address
     Indirect form: any other valid addressing mode
-   Flags: - (never set any flags) for unconditional jumps.
-   Flags: destroy all flags for calls. */
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw);
+
+   Flags: does not modify flags for unconditional jumps but
+          destroy all flags for calls. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw);
 
 /* Perform the operation using the conditional flags as the second argument.
-   Type must always be between SLJIT_EQUAL and SLJIT_S_ORDERED. The value
+   Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_F64. The value
    represented by the type is 1, if the condition represented by the type
    is fulfilled, and 0 otherwise.
 
-   If op == SLJIT_MOV, SLJIT_MOV_SI, SLJIT_MOV_UI:
+   If op == SLJIT_MOV, SLJIT_MOV32:
      Set dst to the value represented by the type (0 or 1).
-     Src must be SLJIT_UNUSED, and srcw must be 0
-     Flags: - (never set any flags)
+     Flags: - (does not modify flags)
    If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR
-     Performs the binary operation using src as the first, and the value
-     represented by type as the second argument.
-     Important note: only dst=src and dstw=srcw is supported at the moment!
-     Flags: I | E | K
-   Note: sljit_emit_op_flags does nothing, if dst is SLJIT_UNUSED (regardless of op). */
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type);
+     Performs the binary operation using dst as the first, and the value
+     represented by type as the second argument. Result is written into dst.
+     Flags: Z (may destroy flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type);
+
+/* Emit a conditional mov instruction which moves source to destination,
+   if the condition is satisfied. Unlike other arithmetic operations this
+   instruction does not support memory accesses.
+
+   type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64
+   dst_reg must be a valid register and it can be combined
+      with SLJIT_I32_OP to perform a 32 bit arithmetic operation
+   src must be register or immediate (SLJIT_IMM)
+
+   Flags: - (does not modify flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw);
 
 /* Copies the base address of SLJIT_SP + offset to dst.
-   Flags: - (never set any flags) */
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset);
+   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)
-   Flags: - (never set any flags) */
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value);
+   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);
 
 /* After the code generation the address for label, jump and const instructions
    are computed. Since these structures are freed by sljit_free_compiler, the
@@ -1090,21 +1240,22 @@ static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { r
 static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }
 static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; }
 
-/* Only the address is required to rewrite the code. */
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr);
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant);
+/* Only the address and executable offset are required to perform dynamic
+   code modifications. See sljit_get_executable_offset function. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset);
 
 /* --------------------------------------------------------------------- */
 /*  Miscellaneous utility functions                                      */
 /* --------------------------------------------------------------------- */
 
 #define SLJIT_MAJOR_VERSION    0
-#define SLJIT_MINOR_VERSION    93
+#define SLJIT_MINOR_VERSION    94
 
 /* Get the human readable name of the platform. Can be useful on platforms
    like ARM, where ARM and Thumb2 functions can be mixed, and
    it is useful to know the type of the code generator. */
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void);
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void);
 
 /* Portable helper function to get an offset of a member. */
 #define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10)
@@ -1117,19 +1268,23 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void);
 
 #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
 
-/* The sljit_stack is a utiliy feature of sljit, which allocates a
-   writable memory region between base (inclusive) and limit (exclusive).
-   Both base and limit is a pointer, and base is always <= than limit.
-   This feature uses the "address space reserve" feature
-   of modern operating systems. Basically we don't need to allocate a
-   huge memory block in one step for the worst case, we can start with
-   a smaller chunk and extend it later. Since the address space is
-   reserved, the data never copied to other regions, thus it is safe
-   to store pointers here. */
-
-/* Note: The base field is aligned to PAGE_SIZE bytes (usually 4k or more).
-   Note: stack growing should not happen in small steps: 4k, 16k or even
-     bigger growth is better.
+/* The sljit_stack is a utility extension of sljit, which provides
+   a top-down stack. The stack starts at base and goes down to
+   max_limit, so the memory region for this stack is between
+   max_limit (inclusive) and base (exclusive). However the
+   application can only use the region between limit (inclusive)
+   and base (exclusive). The sljit_stack_resize can be used to
+   extend this region up to max_limit.
+
+   This feature uses the "address space reserve" feature of modern
+   operating systems, so instead of allocating a huge memory block
+   applications can allocate a small region and extend it later
+   without moving the memory area. Hence pointers can be stored
+   in this area. */
+
+/* Note: base and max_limit fields are aligned to PAGE_SIZE bytes
+     (usually 4 Kbyte or more).
+   Note: stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more.
    Note: this structure may not be supported by all operating systems.
      Some kind of fallback mechanism is suggested when SLJIT_UTIL_STACK
      is not defined. */
@@ -1137,15 +1292,16 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void);
 struct sljit_stack {
        /* User data, anything can be stored here.
           Starting with the same value as base. */
-       sljit_utop;
+       sljit_u8 *top;
        /* These members are read only. */
-       sljit_ubase;
-       sljit_ulimit;
-       sljit_umax_limit;
+       sljit_u8 *base;
+       sljit_u8 *limit;
+       sljit_u8 *max_limit;
 };
 
 /* Returns NULL if unsuccessful.
-   Note: limit and max_limit contains the size for stack allocation.
+   Note: max_limit contains the maximum stack size in bytes.
+   Note: limit contains the starting stack size in bytes.
    Note: the top field is initialized to base.
    Note: see sljit_create_compiler for the explanation of allocator_data. */
 SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data);
@@ -1157,7 +1313,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *st
    since the growth ratio can be added to the current limit, and sljit_stack_resize
    will do all the necessary checks. The fields of the stack are not changed if
    sljit_stack_resize fails. */
-SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_unew_limit);
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_limit);
 
 #endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */
 
@@ -1186,6 +1342,15 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct
 
 #endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
 
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+/* Free unused executable memory. The allocator keeps some free memory
+   around to reduce the number of OS executable memory allocations.
+   This improves performance since these calls are costly. However
+   it is sometimes desired to free all unused memory regions, e.g.
+   before the application terminates. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
+#endif
+
 /* --------------------------------------------------------------------- */
 /*  CPU specific functions                                               */
 /* --------------------------------------------------------------------- */
@@ -1196,14 +1361,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct
 
    Note: it returns with -1 for virtual registers (only on x86-32). */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg);
 
 /* The following function is a helper function for sljit_emit_op_custom.
    It returns with the real machine register index of any SLJIT_FLOAT register.
 
    Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg);
 
 /* Any instruction can be inserted into the instruction stream by
    sljit_emit_op_custom. It has a similar purpose as inline assembly.
@@ -1215,35 +1380,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg);
               if size == 4, the instruction argument must be 4 byte aligned.
    Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size);
-
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size);
 
-/* Returns with non-zero if sse2 is available. */
+/* Define the currently available CPU status flags. It is usually used after an
+   sljit_emit_op_custom call to define which flags are set. */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_sse2_available(void);
-
-/* Returns with non-zero if cmov instruction is available. */
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_cmov_available(void);
-
-/* Emit a conditional mov instruction on x86 CPUs. This instruction
-   moves src to destination, if the condition is satisfied. Unlike
-   other arithmetic instructions, destination must be a register.
-   Before such instructions are emitted, cmov support should be
-   checked by sljit_x86_is_cmov_available function.
-    type must be between SLJIT_EQUAL and SLJIT_S_ORDERED
-    dst_reg must be a valid register and it can be combined
-      with SLJIT_INT_OP to perform 32 bit arithmetic
-   Flags: I - (never set any flags)
- */
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_emit_cmov(struct sljit_compiler *compiler,
-       sljit_si type,
-       sljit_si dst_reg,
-       sljit_si src, sljit_sw srcw);
-
-#endif
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,
+       sljit_s32 current_flags);
 
 #endif /* _SLJIT_LIR_H_ */
index 5cd4c71a298f6f1891fb05291b1c8ada65cebc00..745da99f614efff42c287ba3cb8b9c2256fb3c3b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -24,7 +24,7 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
 {
 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
        return "ARMv7" SLJIT_CPUINFO;
@@ -38,8 +38,7 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
 /* Last register + 1. */
 #define TMP_REG1       (SLJIT_NUMBER_OF_REGISTERS + 2)
 #define TMP_REG2       (SLJIT_NUMBER_OF_REGISTERS + 3)
-#define TMP_REG3       (SLJIT_NUMBER_OF_REGISTERS + 4)
-#define TMP_PC         (SLJIT_NUMBER_OF_REGISTERS + 5)
+#define TMP_PC         (SLJIT_NUMBER_OF_REGISTERS + 4)
 
 #define TMP_FREG1      (0)
 #define TMP_FREG2      (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
@@ -52,11 +51,11 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
 #define ALIGN_INSTRUCTION(ptr) \
        (sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1))
 #define MAX_DIFFERENCE(max_diff) \
-       (((max_diff) / (sljit_si)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
+       (((max_diff) / (sljit_s32)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
 
 /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
-       0, 0, 1, 2, 11, 10, 9, 8, 7, 6, 5, 4, 13, 3, 12, 14, 15
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
+       0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 14, 12, 15
 };
 
 #define RM(rm) (reg_map[rm])
@@ -83,6 +82,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
 #define BLX            0xe12fff30
 #define BX             0xe12fff10
 #define CLZ            0xe16f0f10
+#define CMN_DP         0xb
 #define CMP_DP         0xa
 #define BKPT           0xe1200070
 #define EOR_DP         0x1
@@ -126,13 +126,13 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
 
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
 
-static sljit_si push_cpool(struct sljit_compiler *compiler)
+static sljit_s32 push_cpool(struct sljit_compiler *compiler)
 {
        /* Pushing the constant pool into the instruction stream. */
        sljit_uw* inst;
        sljit_uw* cpool_ptr;
        sljit_uw* cpool_end;
-       sljit_si i;
+       sljit_s32 i;
 
        /* The label could point the address after the constant pool. */
        if (compiler->last_label && compiler->last_label->size == compiler->size)
@@ -164,7 +164,7 @@ static sljit_si push_cpool(struct sljit_compiler *compiler)
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_inst(struct sljit_compiler *compiler, sljit_uw inst)
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst)
 {
        sljit_uw* ptr;
 
@@ -178,13 +178,13 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_uw inst)
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
+static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
 {
        sljit_uw* ptr;
        sljit_uw cpool_index = CPOOL_SIZE;
        sljit_uw* cpool_ptr;
        sljit_uw* cpool_end;
-       sljit_ub* cpool_unique_ptr;
+       sljit_u8* cpool_unique_ptr;
 
        if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
                FAIL_IF(push_cpool(compiler));
@@ -228,7 +228,7 @@ static sljit_si push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
+static sljit_s32 push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
 {
        sljit_uw* ptr;
        if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE))
@@ -248,7 +248,7 @@ static sljit_si push_inst_with_unique_literal(struct sljit_compiler *compiler, s
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si prepare_blx(struct sljit_compiler *compiler)
+static SLJIT_INLINE sljit_s32 prepare_blx(struct sljit_compiler *compiler)
 {
        /* Place for at least two instruction (doesn't matter whether the first has a literal). */
        if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088)))
@@ -256,11 +256,11 @@ static SLJIT_INLINE sljit_si prepare_blx(struct sljit_compiler *compiler)
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_blx(struct sljit_compiler *compiler)
+static SLJIT_INLINE sljit_s32 emit_blx(struct sljit_compiler *compiler)
 {
        /* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */
        SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092));
-       return push_inst(compiler, BLX | RM(TMP_REG1));
+       return push_inst(compiler, BLX | RM(TMP_REG2));
 }
 
 static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)
@@ -286,7 +286,7 @@ static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_
 
                        /* Must be a load instruction with immediate offset. */
                        SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20)));
-                       if ((sljit_si)const_pool[ind] < 0) {
+                       if ((sljit_s32)const_pool[ind] < 0) {
                                const_pool[ind] = counter;
                                ind = counter;
                                counter++;
@@ -311,26 +311,26 @@ static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_
 /* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */
 struct future_patch {
        struct future_patch* next;
-       sljit_si index;
-       sljit_si value;
+       sljit_s32 index;
+       sljit_s32 value;
 };
 
-static sljit_si resolve_const_pool_index(struct sljit_compiler *compiler, struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)
+static sljit_s32 resolve_const_pool_index(struct sljit_compiler *compiler, struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)
 {
-       sljit_si value;
+       sljit_s32 value;
        struct future_patch *curr_patch, *prev_patch;
 
        SLJIT_UNUSED_ARG(compiler);
 
        /* Using the values generated by patch_pc_relative_loads. */
        if (!*first_patch)
-               value = (sljit_si)cpool_start_address[cpool_current_index];
+               value = (sljit_s32)cpool_start_address[cpool_current_index];
        else {
                curr_patch = *first_patch;
-               prev_patch = 0;
+               prev_patch = NULL;
                while (1) {
                        if (!curr_patch) {
-                               value = (sljit_si)cpool_start_address[cpool_current_index];
+                               value = (sljit_s32)cpool_start_address[cpool_current_index];
                                break;
                        }
                        if ((sljit_uw)curr_patch->index == cpool_current_index) {
@@ -370,7 +370,7 @@ static sljit_si resolve_const_pool_index(struct sljit_compiler *compiler, struct
 
 #else
 
-static sljit_si push_inst(struct sljit_compiler *compiler, sljit_uw inst)
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst)
 {
        sljit_uw* ptr;
 
@@ -381,7 +381,7 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_uw inst)
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_imm(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
+static SLJIT_INLINE sljit_s32 emit_imm(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
 {
        FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
        return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
@@ -389,7 +389,7 @@ static SLJIT_INLINE sljit_si emit_imm(struct sljit_compiler *compiler, sljit_si
 
 #endif
 
-static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code)
+static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code, sljit_sw executable_offset)
 {
        sljit_sw diff;
 
@@ -401,7 +401,7 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uw
                code_ptr--;
 
        if (jump->flags & JUMP_ADDR)
-               diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2));
+               diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset);
        else {
                SLJIT_ASSERT(jump->flags & JUMP_LABEL);
                diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2));
@@ -426,7 +426,7 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uw
        }
 #else
        if (jump->flags & JUMP_ADDR)
-               diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr);
+               diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr - executable_offset);
        else {
                SLJIT_ASSERT(jump->flags & JUMP_LABEL);
                diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)code_ptr);
@@ -446,26 +446,28 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uw
        return 0;
 }
 
-static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, sljit_si flush)
+static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache)
 {
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-       sljit_uw *ptr = (sljit_uw*)addr;
-       sljit_uw *inst = (sljit_uw*)ptr[0];
+       sljit_uw *ptr = (sljit_uw *)jump_ptr;
+       sljit_uw *inst = (sljit_uw *)ptr[0];
        sljit_uw mov_pc = ptr[1];
-       sljit_si bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
-       sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2)) >> 2);
+       sljit_s32 bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
+       sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2) - executable_offset) >> 2);
 
        if (diff <= 0x7fffff && diff >= -0x800000) {
                /* Turn to branch. */
                if (!bl) {
                        inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);
-                       if (flush) {
+                       if (flush_cache) {
+                               inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
                                SLJIT_CACHE_FLUSH(inst, inst + 1);
                        }
                } else {
                        inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);
                        inst[1] = NOP;
-                       if (flush) {
+                       if (flush_cache) {
+                               inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
                                SLJIT_CACHE_FLUSH(inst, inst + 2);
                        }
                }
@@ -479,12 +481,14 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr,
                if (*inst != mov_pc) {
                        inst[0] = mov_pc;
                        if (!bl) {
-                               if (flush) {
+                               if (flush_cache) {
+                                       inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
                                        SLJIT_CACHE_FLUSH(inst, inst + 1);
                                }
                        } else {
                                inst[1] = BLX | RM(TMP_REG1);
-                               if (flush) {
+                               if (flush_cache) {
+                                       inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
                                        SLJIT_CACHE_FLUSH(inst, inst + 2);
                                }
                        }
@@ -492,11 +496,12 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr,
                *ptr = new_addr;
        }
 #else
-       sljit_uw *inst = (sljit_uw*)addr;
+       sljit_uw *inst = (sljit_uw*)jump_ptr;
        SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
        inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff);
        inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff);
-       if (flush) {
+       if (flush_cache) {
+               inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
                SLJIT_CACHE_FLUSH(inst, inst + 2);
        }
 #endif
@@ -504,7 +509,7 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr,
 
 static sljit_uw get_imm(sljit_uw imm);
 
-static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant, sljit_si flush)
+static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_sw new_constant, sljit_s32 flush_cache)
 {
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
        sljit_uw *ptr = (sljit_uw*)addr;
@@ -515,7 +520,8 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant,
        src2 = get_imm(new_constant);
        if (src2) {
                *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;
-               if (flush) {
+               if (flush_cache) {
+                       inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
                        SLJIT_CACHE_FLUSH(inst, inst + 1);
                }
                return;
@@ -524,7 +530,8 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant,
        src2 = get_imm(~new_constant);
        if (src2) {
                *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;
-               if (flush) {
+               if (flush_cache) {
+                       inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
                        SLJIT_CACHE_FLUSH(inst, inst + 1);
                }
                return;
@@ -537,7 +544,8 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant,
 
        if (*inst != ldr_literal) {
                *inst = ldr_literal;
-               if (flush) {
+               if (flush_cache) {
+                       inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
                        SLJIT_CACHE_FLUSH(inst, inst + 1);
                }
        }
@@ -547,7 +555,8 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw new_constant,
        SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
        inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff);
        inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff);
-       if (flush) {
+       if (flush_cache) {
+               inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
                SLJIT_CACHE_FLUSH(inst, inst + 2);
        }
 #endif
@@ -562,6 +571,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        sljit_uw *buf_end;
        sljit_uw size;
        sljit_uw word_count;
+       sljit_sw executable_offset;
+       sljit_sw jump_addr;
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
        sljit_uw cpool_size;
        sljit_uw cpool_skip_alignment;
@@ -602,14 +613,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
        code_ptr = code;
        word_count = 0;
+       executable_offset = SLJIT_EXEC_OFFSET(code);
 
        label = compiler->labels;
        jump = compiler->jumps;
        const_ = compiler->consts;
 
        if (label && label->size == 0) {
-               label->addr = (sljit_uw)code;
-               label->size = 0;
+               label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
                label = label->next;
        }
 
@@ -636,7 +647,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                                                cpool_size = 0;
                                                if (label && label->size == word_count) {
                                                        /* Points after the current instruction. */
-                                                       label->addr = (sljit_uw)code_ptr;
+                                                       label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
                                                        label->size = code_ptr - code;
                                                        label = label->next;
                                                }
@@ -652,19 +663,19 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                                SLJIT_ASSERT(!const_ || const_->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))
+                                       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))
+                                       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)(code_ptr + 1);
+                                       label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
                                        label->size = (code_ptr + 1) - code;
                                        label = label->next;
                                }
@@ -729,17 +740,18 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
        jump = compiler->jumps;
        while (jump) {
-               buf_ptr = (sljit_uw*)jump->addr;
+               buf_ptr = (sljit_uw *)jump->addr;
 
                if (jump->flags & PATCH_B) {
+                       jump_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 - (sljit_sw)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) >= -0x02000000);
-                               *buf_ptr |= (((sljit_sw)jump->u.label->addr - (sljit_sw)(buf_ptr + 2)) >> 2) & 0x00ffffff;
+                               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;
                        }
                        else {
-                               SLJIT_ASSERT(((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) >= -0x02000000);
-                               *buf_ptr |= (((sljit_sw)jump->u.target - (sljit_sw)(buf_ptr + 2)) >> 2) & 0x00ffffff;
+                               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;
                        }
                }
                else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
@@ -747,10 +759,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                        jump->addr = (sljit_uw)code_ptr;
                        code_ptr[0] = (sljit_uw)buf_ptr;
                        code_ptr[1] = *buf_ptr;
-                       inline_set_jump_addr((sljit_uw)code_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+                       inline_set_jump_addr((sljit_uw)code_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
                        code_ptr += 2;
 #else
-                       inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+                       inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
 #endif
                }
                else {
@@ -763,7 +775,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                                buf_ptr += 1;
                        *buf_ptr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
 #else
-                       inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+                       inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
 #endif
                }
                jump = jump->next;
@@ -782,54 +794,115 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                else
                        buf_ptr += 1;
                /* Set the value again (can be a simple constant). */
-               inline_set_const((sljit_uw)code_ptr, *buf_ptr, 0);
+               inline_set_const((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);
                code_ptr += 2;
 
                const_ = const_->next;
        }
 #endif
 
-       SLJIT_ASSERT(code_ptr - code <= (sljit_si)size);
+       SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size);
 
        compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_offset = executable_offset;
        compiler->executable_size = (code_ptr - code) * sizeof(sljit_uw);
+
+       code = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+       code_ptr = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
        SLJIT_CACHE_FLUSH(code, code_ptr);
        return code;
 }
 
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+       switch (feature_type) {
+       case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+               return SLJIT_IS_FPU_AVAILABLE;
+#else
+               /* Available by default. */
+               return 1;
+#endif
+
+       case SLJIT_HAS_PRE_UPDATE:
+       case SLJIT_HAS_CLZ:
+       case SLJIT_HAS_CMOV:
+               return 1;
+
+       default:
+               return 0;
+       }
+}
+
 /* --------------------------------------------------------------------- */
 /*  Entry, exit                                                          */
 /* --------------------------------------------------------------------- */
 
+/* Creates an index in data_transfer_insts array. */
+#define WORD_DATA      0x00
+#define BYTE_DATA      0x01
+#define HALF_DATA      0x02
+#define PRELOAD_DATA   0x03
+#define SIGNED_DATA    0x04
+#define LOAD_DATA      0x08
+
 /* emit_op inp_flags.
    WRITE_BACK must be the first, since it is a flag. */
-#define WRITE_BACK     0x01
-#define ALLOW_IMM      0x02
-#define ALLOW_INV_IMM  0x04
+#define WRITE_BACK     0x10
+#define ALLOW_IMM      0x20
+#define ALLOW_INV_IMM  0x40
 #define ALLOW_ANY_IMM  (ALLOW_IMM | ALLOW_INV_IMM)
-#define ARG_TEST       0x08
 
-/* Creates an index in data_transfer_insts array. */
-#define WORD_DATA      0x00
-#define BYTE_DATA      0x10
-#define HALF_DATA      0x20
-#define SIGNED_DATA    0x40
-#define LOAD_DATA      0x80
+/* s/l - store/load (1 bit)
+   u/s - signed/unsigned (1 bit)
+   w/b/h/N - word/byte/half/NOT allowed (2 bit)
+   Storing signed and unsigned values are the same operations. */
+
+static const sljit_uw data_transfer_insts[16] = {
+/* s u w */ 0xe5000000 /* str */,
+/* s u b */ 0xe5400000 /* strb */,
+/* s u h */ 0xe10000b0 /* strh */,
+/* s u N */ 0x00000000 /* not allowed */,
+/* s s w */ 0xe5000000 /* str */,
+/* s s b */ 0xe5400000 /* strb */,
+/* s s h */ 0xe10000b0 /* strh */,
+/* s s N */ 0x00000000 /* not allowed */,
+
+/* l u w */ 0xe5100000 /* ldr */,
+/* l u b */ 0xe5500000 /* ldrb */,
+/* l u h */ 0xe11000b0 /* ldrh */,
+/* l u p */ 0xf5500000 /* preload data */,
+/* l s w */ 0xe5100000 /* ldr */,
+/* l s b */ 0xe11000d0 /* ldrsb */,
+/* l s h */ 0xe11000f0 /* ldrsh */,
+/* l s N */ 0x00000000 /* not allowed */,
+};
+
+#define EMIT_DATA_TRANSFER(type, add, wb, target_reg, base_reg, arg) \
+       (data_transfer_insts[(type) & 0xf] | ((add) << 23) | ((wb) << (21 - 4)) | RD(target_reg) | RN(base_reg) | (arg))
+
+/* Normal ldr/str instruction.
+   Type2: ldrsb, ldrh, ldrsh */
+#define IS_TYPE1_TRANSFER(type) \
+       (data_transfer_insts[(type) & 0xf] & 0x04000000)
+#define TYPE2_TRANSFER_IMM(imm) \
+       (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
 
 /* Condition: AL. */
 #define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \
        (0xe0000000 | ((opcode) << 21) | (set_flags) | RD(dst) | RN(src1) | (src2))
 
-static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si inp_flags,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w);
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w);
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
-       sljit_si size, i, tmp;
+       sljit_s32 size, i, tmp;
        sljit_uw push;
 
        CHECK_ERROR();
@@ -866,11 +939,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
-       sljit_si size;
+       sljit_s32 size;
 
        CHECK_ERROR();
        CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -881,9 +954,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si i, tmp;
+       sljit_s32 i, tmp;
        sljit_uw pop;
 
        CHECK_ERROR();
@@ -912,52 +985,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
 /*  Operators                                                            */
 /* --------------------------------------------------------------------- */
 
-/* s/l - store/load (1 bit)
-   u/s - signed/unsigned (1 bit)
-   w/b/h/N - word/byte/half/NOT allowed (2 bit)
-   It contans 16 items, but not all are different. */
-
-static sljit_sw data_transfer_insts[16] = {
-/* s u w */ 0xe5000000 /* str */,
-/* s u b */ 0xe5400000 /* strb */,
-/* s u h */ 0xe10000b0 /* strh */,
-/* s u N */ 0x00000000 /* not allowed */,
-/* s s w */ 0xe5000000 /* str */,
-/* s s b */ 0xe5400000 /* strb */,
-/* s s h */ 0xe10000b0 /* strh */,
-/* s s N */ 0x00000000 /* not allowed */,
-
-/* l u w */ 0xe5100000 /* ldr */,
-/* l u b */ 0xe5500000 /* ldrb */,
-/* l u h */ 0xe11000b0 /* ldrh */,
-/* l u N */ 0x00000000 /* not allowed */,
-/* l s w */ 0xe5100000 /* ldr */,
-/* l s b */ 0xe11000d0 /* ldrsb */,
-/* l s h */ 0xe11000f0 /* ldrsh */,
-/* l s N */ 0x00000000 /* not allowed */,
-};
-
-#define EMIT_DATA_TRANSFER(type, add, wb, target, base1, base2) \
-       (data_transfer_insts[(type) >> 4] | ((add) << 23) | ((wb) << 21) | (reg_map[target] << 12) | (reg_map[base1] << 16) | (base2))
-/* Normal ldr/str instruction.
-   Type2: ldrsb, ldrh, ldrsh */
-#define IS_TYPE1_TRANSFER(type) \
-       (data_transfer_insts[(type) >> 4] & 0x04000000)
-#define TYPE2_TRANSFER_IMM(imm) \
-       (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
-
 /* flags: */
   /* Arguments are swapped. */
 #define ARGS_SWAPPED   0x01
   /* Inverted immediate. */
 #define INV_IMM                0x02
   /* Source and destination is register. */
-#define REG_DEST       0x04
-#define REG_SOURCE     0x08
-  /* One instruction is enough. */
-#define FAST_DEST      0x10
-  /* Multiple instructions are required. */
-#define SLOW_DEST      0x20
+#define MOVE_REG_CONV  0x04
+  /* Unused return value. */
+#define UNUSED_RETURN  0x08
 /* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
 #define SET_FLAGS      (1 << 20)
 /* dst: reg
@@ -966,157 +1002,135 @@ static sljit_sw data_transfer_insts[16] = {
    SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */
 #define SRC2_IMM       (1 << 25)
 
-#define EMIT_DATA_PROCESS_INS_AND_RETURN(opcode) \
-       return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)))
-
-#define EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(opcode, dst, src1, src2) \
-       return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, src2))
-
 #define EMIT_SHIFT_INS_AND_RETURN(opcode) \
        SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \
        if (compiler->shift_imm != 0x20) { \
                SLJIT_ASSERT(src1 == TMP_REG1); \
                SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \
+               \
                if (compiler->shift_imm != 0) \
-                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \
-               return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, reg_map[src2])); \
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, \
+                               dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | RM(src2))); \
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, RM(src2))); \
        } \
-       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1])));
+       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, \
+               dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1)));
 
-static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
-       sljit_si dst, sljit_si src1, sljit_si src2)
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+       sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
 {
-       sljit_sw mul_inst;
-
        switch (GET_OPCODE(op)) {
        case SLJIT_MOV:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
                if (dst != src2) {
                        if (src2 & SRC2_IMM) {
-                               if (flags & INV_IMM)
-                                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
-                               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+                               return push_inst(compiler, EMIT_DATA_PROCESS_INS((flags & INV_IMM) ? MVN_DP : MOV_DP, 0,
+                                       dst, SLJIT_UNUSED, src2));
                        }
-                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]);
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(src2)));
                }
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UB:
-       case SLJIT_MOV_SB:
+       case SLJIT_MOV_U8:
+       case SLJIT_MOV_S8:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
-               if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
+               if (flags & MOVE_REG_CONV) {
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-                       if (op == SLJIT_MOV_UB)
+                       if (op == SLJIT_MOV_U8)
                                return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff));
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2])));
-                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_UB ? 0x20 : 0x40) | reg_map[dst]));
+                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | RM(src2))));
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | RM(dst)));
 #else
-                       return push_inst(compiler, (op == SLJIT_MOV_UB ? UXTB : SXTB) | RD(dst) | RM(src2));
+                       return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2));
 #endif
                }
                else if (dst != src2) {
                        SLJIT_ASSERT(src2 & SRC2_IMM);
-                       if (flags & INV_IMM)
-                               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
-                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS((flags & INV_IMM) ? MVN_DP : MOV_DP, 0,
+                               dst, SLJIT_UNUSED, src2));
                }
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UH:
-       case SLJIT_MOV_SH:
+       case SLJIT_MOV_U16:
+       case SLJIT_MOV_S16:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
-               if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
+               if (flags & MOVE_REG_CONV) {
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2])));
-                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_UH ? 0x20 : 0x40) | reg_map[dst]));
+                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | RM(src2))));
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | RM(dst)));
 #else
-                       return push_inst(compiler, (op == SLJIT_MOV_UH ? UXTH : SXTH) | RD(dst) | RM(src2));
+                       return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2));
 #endif
                }
                else if (dst != src2) {
                        SLJIT_ASSERT(src2 & SRC2_IMM);
-                       if (flags & INV_IMM)
-                               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
-                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS((flags & INV_IMM) ? MVN_DP : MOV_DP, 0,
+                               dst, SLJIT_UNUSED, src2));
                }
                return SLJIT_SUCCESS;
 
        case SLJIT_NOT:
                if (src2 & SRC2_IMM) {
-                       if (flags & INV_IMM)
-                               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
-                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS((flags & INV_IMM) ? MOV_DP : MVN_DP, flags & SET_FLAGS,
+                               dst, SLJIT_UNUSED, src2));
                }
-               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2));
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(MVN_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, RM(src2)));
 
        case SLJIT_CLZ:
                SLJIT_ASSERT(!(flags & INV_IMM));
                SLJIT_ASSERT(!(src2 & SRC2_IMM));
                FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
-               if (flags & SET_FLAGS)
-                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM);
                return SLJIT_SUCCESS;
 
        case SLJIT_ADD:
                SLJIT_ASSERT(!(flags & INV_IMM));
-               EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP);
+               if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMN_DP, SET_FLAGS,
+                               SLJIT_UNUSED, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, flags & SET_FLAGS,
+                       dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
 
        case SLJIT_ADDC:
                SLJIT_ASSERT(!(flags & INV_IMM));
-               EMIT_DATA_PROCESS_INS_AND_RETURN(ADC_DP);
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADC_DP, flags & SET_FLAGS,
+                       dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
 
        case SLJIT_SUB:
                SLJIT_ASSERT(!(flags & INV_IMM));
-               if (!(flags & ARGS_SWAPPED))
-                       EMIT_DATA_PROCESS_INS_AND_RETURN(SUB_DP);
-               EMIT_DATA_PROCESS_INS_AND_RETURN(RSB_DP);
+               if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS,
+                               SLJIT_UNUSED, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(!(flags & ARGS_SWAPPED) ? SUB_DP : RSB_DP, flags & SET_FLAGS,
+                       dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
 
        case SLJIT_SUBC:
                SLJIT_ASSERT(!(flags & INV_IMM));
-               if (!(flags & ARGS_SWAPPED))
-                       EMIT_DATA_PROCESS_INS_AND_RETURN(SBC_DP);
-               EMIT_DATA_PROCESS_INS_AND_RETURN(RSC_DP);
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(!(flags & ARGS_SWAPPED) ? SBC_DP : RSC_DP, flags & SET_FLAGS,
+                       dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
 
        case SLJIT_MUL:
                SLJIT_ASSERT(!(flags & INV_IMM));
                SLJIT_ASSERT(!(src2 & SRC2_IMM));
-               if (SLJIT_UNLIKELY(op & SLJIT_SET_O))
-                       mul_inst = SMULL | (reg_map[TMP_REG3] << 16) | (reg_map[dst] << 12);
-               else
-                       mul_inst = MUL | (reg_map[dst] << 16);
 
-               if (dst != src2)
-                       FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src1] << 8) | reg_map[src2]));
-               else if (dst != src1)
-                       FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[src1]));
-               else {
-                       /* Rm and Rd must not be the same register. */
-                       SLJIT_ASSERT(dst != TMP_REG1);
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, reg_map[src2])));
-                       FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[TMP_REG1]));
-               }
+               if (!HAS_FLAGS(op))
+                       return push_inst(compiler, MUL | (reg_map[dst] << 16) | (reg_map[src2] << 8) | reg_map[src1]);
 
-               if (!(op & SLJIT_SET_O))
-                       return SLJIT_SUCCESS;
+               FAIL_IF(push_inst(compiler, SMULL | (reg_map[TMP_REG1] << 16) | (reg_map[dst] << 12) | (reg_map[src2] << 8) | reg_map[src1]));
 
-               /* We need to use TMP_REG3. */
-               compiler->cache_arg = 0;
-               compiler->cache_argw = 0;
-               /* cmp TMP_REG2, dst asr #31. */
-               return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS, SLJIT_UNUSED, TMP_REG3, RM(dst) | 0xfc0));
+               /* cmp TMP_REG1, dst asr #31. */
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS, SLJIT_UNUSED, TMP_REG1, RM(dst) | 0xfc0));
 
        case SLJIT_AND:
-               if (!(flags & INV_IMM))
-                       EMIT_DATA_PROCESS_INS_AND_RETURN(AND_DP);
-               EMIT_DATA_PROCESS_INS_AND_RETURN(BIC_DP);
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(!(flags & INV_IMM) ? AND_DP : BIC_DP, flags & SET_FLAGS,
+                       dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
 
        case SLJIT_OR:
                SLJIT_ASSERT(!(flags & INV_IMM));
-               EMIT_DATA_PROCESS_INS_AND_RETURN(ORR_DP);
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(ORR_DP, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
 
        case SLJIT_XOR:
                SLJIT_ASSERT(!(flags & INV_IMM));
-               EMIT_DATA_PROCESS_INS_AND_RETURN(EOR_DP);
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(EOR_DP, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
 
        case SLJIT_SHL:
                EMIT_SHIFT_INS_AND_RETURN(0);
@@ -1127,19 +1141,18 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
        case SLJIT_ASHR:
                EMIT_SHIFT_INS_AND_RETURN(2);
        }
-       SLJIT_ASSERT_STOP();
+
+       SLJIT_UNREACHABLE();
        return SLJIT_SUCCESS;
 }
 
-#undef EMIT_DATA_PROCESS_INS_AND_RETURN
-#undef EMIT_FULL_DATA_PROCESS_INS_AND_RETURN
 #undef EMIT_SHIFT_INS_AND_RETURN
 
 /* Tests whether the immediate can be stored in the 12 bit imm field.
    Returns with 0 if not possible. */
 static sljit_uw get_imm(sljit_uw imm)
 {
-       sljit_si rol;
+       sljit_s32 rol;
 
        if (imm <= 0xff)
                return SRC2_IMM | imm;
@@ -1175,12 +1188,12 @@ static sljit_uw get_imm(sljit_uw imm)
 }
 
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-static sljit_si generate_int(struct sljit_compiler *compiler, sljit_si reg, sljit_uw imm, sljit_si positive)
+static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm, sljit_s32 positive)
 {
        sljit_uw mask;
        sljit_uw imm1;
        sljit_uw imm2;
-       sljit_si rol;
+       sljit_s32 rol;
 
        /* Step1: Search a zero byte (8 continous zero bit). */
        mask = 0xff000000;
@@ -1286,7 +1299,7 @@ static sljit_si generate_int(struct sljit_compiler *compiler, sljit_si reg, slji
 }
 #endif
 
-static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_uw imm)
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm)
 {
        sljit_uw tmp;
 
@@ -1312,360 +1325,183 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
        /* Load integer. */
        return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), imm);
 #else
-       return emit_imm(compiler, reg, imm);
+       FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
+       if (imm <= 0xffff)
+               return SLJIT_SUCCESS;
+       return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
 #endif
 }
 
-/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
-static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sljit_si reg, sljit_sw value)
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
+       sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
 {
-       if (value >= 0) {
-               value = get_imm(value);
-               if (value)
-                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, dst, reg, value));
-       }
-       else {
-               value = get_imm(-value);
-               if (value)
-                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, dst, reg, value));
-       }
-       return SLJIT_ERR_UNSUPPORTED;
-}
+       sljit_uw offset_reg, imm;
+       sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags);
 
-/* Can perform an operation using at most 1 instruction. */
-static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw)
-{
-       sljit_uw imm;
+       SLJIT_ASSERT (arg & SLJIT_MEM);
+       SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
 
-       if (arg & SLJIT_IMM) {
-               imm = get_imm(argw);
-               if (imm) {
-                       if (inp_flags & ARG_TEST)
-                               return 1;
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm)));
-                       return -1;
+       SLJIT_COMPILE_ASSERT(WRITE_BACK == 0x10, optimized_for_emit_data_transfer);
+
+       if ((arg & REG_MASK) == SLJIT_UNUSED) {
+               /* Write back is not used. */
+               if (is_type1_transfer) {
+                       FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xfff));
+                       argw &= 0xfff;
                }
-               imm = get_imm(~argw);
-               if (imm) {
-                       if (inp_flags & ARG_TEST)
-                               return 1;
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm)));
-                       return -1;
+               else {
+                       FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xff));
+                       argw &= 0xff;
                }
-               return 0;
+
+               return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, 0, reg, tmp_reg, is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw)));
        }
 
-       SLJIT_ASSERT(arg & SLJIT_MEM);
+       if (arg & OFFS_REG_MASK) {
+               offset_reg = OFFS_REG(arg);
+               arg &= REG_MASK;
+               argw &= 0x3;
 
-       /* Fast loads/stores. */
-       if (!(arg & REG_MASK))
-               return 0;
+               if (argw != 0 && !is_type1_transfer) {
+                       SLJIT_ASSERT(!(flags & WRITE_BACK));
 
-       if (arg & OFFS_REG_MASK) {
-               if ((argw & 0x3) != 0 && !IS_TYPE1_TRANSFER(inp_flags))
-                       return 0;
+                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_reg, arg, RM(offset_reg) | (argw << 7))));
+                       return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, 0, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
+               }
 
-               if (inp_flags & ARG_TEST)
-                       return 1;
-               FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK,
-                       RM(OFFS_REG(arg)) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7))));
-               return -1;
+               /* Bit 25: RM is offset. */
+               return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg,
+                       RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | (argw << 7)));
        }
 
-       if (IS_TYPE1_TRANSFER(inp_flags)) {
+       arg &= REG_MASK;
+
+       if (is_type1_transfer) {
+               if (argw > 0xfff) {
+                       imm = get_imm(argw & ~0xfff);
+                       if (imm) {
+                               offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
+                               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, offset_reg, arg, imm)));
+                               argw = argw & 0xfff;
+                               arg = offset_reg;
+                       }
+               }
+               else if (argw < -0xfff) {
+                       imm = get_imm(-argw & ~0xfff);
+                       if (imm) {
+                               offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
+                               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, offset_reg, arg, imm)));
+                               argw = -(-argw & 0xfff);
+                               arg = offset_reg;
+                       }
+               }
+
                if (argw >= 0 && argw <= 0xfff) {
-                       if (inp_flags & ARG_TEST)
-                               return 1;
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, argw)));
-                       return -1;
+                       return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg & REG_MASK, argw));
                }
                if (argw < 0 && argw >= -0xfff) {
-                       if (inp_flags & ARG_TEST)
-                               return 1;
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, -argw)));
-                       return -1;
+                       return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, flags & WRITE_BACK, reg, arg & REG_MASK, -argw));
                }
        }
        else {
+               if (argw > 0xff) {
+                       imm = get_imm(argw & ~0xff);
+                       if (imm) {
+                               offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
+                               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, offset_reg, arg, imm)));
+                               argw = argw & 0xff;
+                               arg = offset_reg;
+                       }
+               }
+               else if (argw < -0xff) {
+                       imm = get_imm(-argw & ~0xff);
+                       if (imm) {
+                               offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
+                               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, offset_reg, arg, imm)));
+                               argw = -(-argw & 0xff);
+                               arg = offset_reg;
+                       }
+               }
+
                if (argw >= 0 && argw <= 0xff) {
-                       if (inp_flags & ARG_TEST)
-                               return 1;
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw))));
-                       return -1;
+                       return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg, TYPE2_TRANSFER_IMM(argw)));
                }
                if (argw < 0 && argw >= -0xff) {
-                       if (inp_flags & ARG_TEST)
-                               return 1;
                        argw = -argw;
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw))));
-                       return -1;
+                       return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, flags & WRITE_BACK, reg, arg, TYPE2_TRANSFER_IMM(argw)));
                }
        }
 
-       return 0;
+       FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+       return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg,
+               RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0)));
 }
 
-/* See getput_arg below.
-   Note: can_cache is called only for binary operators. Those
-   operators always uses word arguments without write back. */
-static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       /* Immediate caching is not supported as it would be an operation on constant arguments. */
-       if (arg & SLJIT_IMM)
-               return 0;
-
-       /* Always a simple operation. */
-       if (arg & OFFS_REG_MASK)
-               return 0;
-
-       if (!(arg & REG_MASK)) {
-               /* Immediate access. */
-               if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
-                       return 1;
-               return 0;
-       }
-
-       if (argw <= 0xfffff && argw >= -0xfffff)
-               return 0;
-
-       if (argw == next_argw && (next_arg & SLJIT_MEM))
-               return 1;
+       /* src1 is reg or TMP_REG1
+          src2 is reg, TMP_REG2, or imm
+          result goes to TMP_REG2, so put result can use TMP_REG1. */
 
-       if (arg == next_arg && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
-               return 1;
-
-       return 0;
-}
+       /* We prefers register and simple consts. */
+       sljit_s32 dst_reg;
+       sljit_s32 src1_reg;
+       sljit_s32 src2_reg;
+       sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
 
-#define GETPUT_ARG_DATA_TRANSFER(add, wb, target, base, imm) \
-       if (max_delta & 0xf00) \
-               FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, imm))); \
-       else \
-               FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, TYPE2_TRANSFER_IMM(imm))));
-
-#define TEST_WRITE_BACK() \
-       if (inp_flags & WRITE_BACK) { \
-               tmp_r = arg & REG_MASK; \
-               if (reg == tmp_r) { \
-                       /* This can only happen for stores */ \
-                       /* since ldr reg, [reg, ...]! has no meaning */ \
-                       SLJIT_ASSERT(!(inp_flags & LOAD_DATA)); \
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(reg)))); \
-                       reg = TMP_REG3; \
-               } \
-       }
-
-/* Emit the necessary instructions. See can_cache above. */
-static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
-{
-       sljit_si tmp_r;
-       sljit_sw max_delta;
-       sljit_sw sign;
-       sljit_uw imm;
+       /* Destination check. */
+       if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))
+               flags |= UNUSED_RETURN;
 
-       if (arg & SLJIT_IMM) {
-               SLJIT_ASSERT(inp_flags & LOAD_DATA);
-               return load_immediate(compiler, reg, argw);
-       }
+       SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));
 
-       SLJIT_ASSERT(arg & SLJIT_MEM);
+       src2_reg = 0;
 
-       tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3;
-       max_delta = IS_TYPE1_TRANSFER(inp_flags) ? 0xfff : 0xff;
+       do {
+               if (!(inp_flags & ALLOW_IMM))
+                       break;
 
-       if ((arg & REG_MASK) == SLJIT_UNUSED) {
-               /* Write back is not used. */
-               imm = (sljit_uw)(argw - compiler->cache_argw);
-               if ((compiler->cache_arg & SLJIT_IMM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
-                       if (imm <= (sljit_uw)max_delta) {
-                               sign = 1;
-                               argw = argw - compiler->cache_argw;
+               if (src2 & SLJIT_IMM) {
+                       src2_reg = get_imm(src2w);
+                       if (src2_reg)
+                               break;
+                       if (inp_flags & ALLOW_INV_IMM) {
+                               src2_reg = get_imm(~src2w);
+                               if (src2_reg) {
+                                       flags |= INV_IMM;
+                                       break;
+                               }
                        }
-                       else {
-                               sign = 0;
-                               argw = compiler->cache_argw - argw;
+                       if (GET_OPCODE(op) == SLJIT_ADD) {
+                               src2_reg = get_imm(-src2w);
+                               if (src2_reg) {
+                                       op = SLJIT_SUB | GET_ALL_FLAGS(op);
+                                       break;
+                               }
+                       }
+                       if (GET_OPCODE(op) == SLJIT_SUB) {
+                               src2_reg = get_imm(-src2w);
+                               if (src2_reg) {
+                                       op = SLJIT_ADD | GET_ALL_FLAGS(op);
+                                       break;
+                               }
                        }
-
-                       GETPUT_ARG_DATA_TRANSFER(sign, 0, reg, TMP_REG3, argw);
-                       return SLJIT_SUCCESS;
-               }
-
-               /* With write back, we can create some sophisticated loads, but
-                  it is hard to decide whether we should convert downward (0s) or upward (1s). */
-               imm = (sljit_uw)(argw - next_argw);
-               if ((next_arg & SLJIT_MEM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
-                       SLJIT_ASSERT(inp_flags & LOAD_DATA);
-
-                       compiler->cache_arg = SLJIT_IMM;
-                       compiler->cache_argw = argw;
-                       tmp_r = TMP_REG3;
-               }
-
-               FAIL_IF(load_immediate(compiler, tmp_r, argw));
-               GETPUT_ARG_DATA_TRANSFER(1, 0, reg, tmp_r, 0);
-               return SLJIT_SUCCESS;
-       }
-
-       if (arg & OFFS_REG_MASK) {
-               SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00));
-               if (inp_flags & WRITE_BACK)
-                       tmp_r = arg & REG_MASK;
-               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))));
-               return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0)));
-       }
-
-       imm = (sljit_uw)(argw - compiler->cache_argw);
-       if (compiler->cache_arg == arg && imm <= (sljit_uw)max_delta) {
-               SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
-               GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, imm);
-               return SLJIT_SUCCESS;
-       }
-       if (compiler->cache_arg == arg && imm >= (sljit_uw)-max_delta) {
-               SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
-               imm = (sljit_uw)-(sljit_sw)imm;
-               GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, imm);
-               return SLJIT_SUCCESS;
-       }
-
-       imm = get_imm(argw & ~max_delta);
-       if (imm) {
-               TEST_WRITE_BACK();
-               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, imm)));
-               GETPUT_ARG_DATA_TRANSFER(1, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
-               return SLJIT_SUCCESS;
-       }
-
-       imm = get_imm(-argw & ~max_delta);
-       if (imm) {
-               argw = -argw;
-               TEST_WRITE_BACK();
-               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & REG_MASK, imm)));
-               GETPUT_ARG_DATA_TRANSFER(0, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
-               return SLJIT_SUCCESS;
-       }
-
-       if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
-               TEST_WRITE_BACK();
-               return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
-       }
-
-       if (argw == next_argw && (next_arg & SLJIT_MEM)) {
-               SLJIT_ASSERT(inp_flags & LOAD_DATA);
-               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
-
-               compiler->cache_arg = SLJIT_IMM;
-               compiler->cache_argw = argw;
-
-               TEST_WRITE_BACK();
-               return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
-       }
-
-       imm = (sljit_uw)(argw - next_argw);
-       if (arg == next_arg && !(inp_flags & WRITE_BACK) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
-               SLJIT_ASSERT(inp_flags & LOAD_DATA);
-               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
-               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & REG_MASK])));
-
-               compiler->cache_arg = arg;
-               compiler->cache_argw = argw;
-
-               GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, 0);
-               return SLJIT_SUCCESS;
-       }
-
-       if ((arg & REG_MASK) == tmp_r) {
-               compiler->cache_arg = SLJIT_IMM;
-               compiler->cache_argw = argw;
-               tmp_r = TMP_REG3;
-       }
-
-       FAIL_IF(load_immediate(compiler, tmp_r, argw));
-       return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
-}
-
-static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
-{
-       if (getput_arg_fast(compiler, flags, reg, arg, argw))
-               return compiler->error;
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
-}
-
-static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
-{
-       if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
-               return compiler->error;
-       return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
-}
-
-static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si inp_flags,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
-{
-       /* arg1 goes to TMP_REG1 or src reg
-          arg2 goes to TMP_REG2, imm or src reg
-          TMP_REG3 can be used for caching
-          result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
-
-       /* We prefers register and simple consts. */
-       sljit_si dst_r;
-       sljit_si src1_r;
-       sljit_si src2_r = 0;
-       sljit_si sugg_src2_r = TMP_REG2;
-       sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
-
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-
-       /* Destination check. */
-       if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
-                       return SLJIT_SUCCESS;
-               dst_r = TMP_REG2;
-       }
-       else if (FAST_IS_REG(dst)) {
-               dst_r = dst;
-               flags |= REG_DEST;
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
-                       sugg_src2_r = dst_r;
-       }
-       else {
-               SLJIT_ASSERT(dst & SLJIT_MEM);
-               if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
-                       flags |= FAST_DEST;
-                       dst_r = TMP_REG2;
-               }
-               else {
-                       flags |= SLOW_DEST;
-                       dst_r = 0;
                }
-       }
 
-       /* Source 1. */
-       if (FAST_IS_REG(src1))
-               src1_r = src1;
-       else if (FAST_IS_REG(src2)) {
-               flags |= ARGS_SWAPPED;
-               src1_r = src2;
-               src2 = src1;
-               src2w = src1w;
-       }
-       else do { /* do { } while(0) is used because of breaks. */
-               src1_r = 0;
-               if ((inp_flags & ALLOW_ANY_IMM) && (src1 & SLJIT_IMM)) {
-                       /* The second check will generate a hit. */
-                       src2_r = get_imm(src1w);
-                       if (src2_r) {
+               if (src1 & SLJIT_IMM) {
+                       src2_reg = get_imm(src1w);
+                       if (src2_reg) {
                                flags |= ARGS_SWAPPED;
                                src1 = src2;
                                src1w = src2w;
                                break;
                        }
                        if (inp_flags & ALLOW_INV_IMM) {
-                               src2_r = get_imm(~src1w);
-                               if (src2_r) {
+                               src2_reg = get_imm(~src1w);
+                               if (src2_reg) {
                                        flags |= ARGS_SWAPPED | INV_IMM;
                                        src1 = src2;
                                        src1w = src2w;
@@ -1673,9 +1509,9 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
                                }
                        }
                        if (GET_OPCODE(op) == SLJIT_ADD) {
-                               src2_r = get_imm(-src1w);
-                               if (src2_r) {
-                                       /* Note: ARGS_SWAPPED is intentionally not applied! */
+                               src2_reg = get_imm(-src1w);
+                               if (src2_reg) {
+                                       /* Note: add is commutative operation. */
                                        src1 = src2;
                                        src1w = src2w;
                                        op = SLJIT_SUB | GET_ALL_FLAGS(op);
@@ -1683,110 +1519,54 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
                                }
                        }
                }
+       } while(0);
 
-               if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
-                       FAIL_IF(compiler->error);
-                       src1_r = TMP_REG1;
-               }
-       } while (0);
+       /* Source 1. */
+       if (FAST_IS_REG(src1))
+               src1_reg = src1;
+       else if (src1 & SLJIT_MEM) {
+               FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
+               src1_reg = TMP_REG1;
+       }
+       else {
+               FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+               src1_reg = TMP_REG1;
+       }
 
-       /* Source 2. */
-       if (src2_r == 0) {
-               if (FAST_IS_REG(src2)) {
-                       src2_r = src2;
-                       flags |= REG_SOURCE;
-                       if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
-                               dst_r = src2_r;
-               }
-               else do { /* do { } while(0) is used because of breaks. */
-                       if ((inp_flags & ALLOW_ANY_IMM) && (src2 & SLJIT_IMM)) {
-                               src2_r = get_imm(src2w);
-                               if (src2_r)
-                                       break;
-                               if (inp_flags & ALLOW_INV_IMM) {
-                                       src2_r = get_imm(~src2w);
-                                       if (src2_r) {
-                                               flags |= INV_IMM;
-                                               break;
-                                       }
-                               }
-                               if (GET_OPCODE(op) == SLJIT_ADD) {
-                                       src2_r = get_imm(-src2w);
-                                       if (src2_r) {
-                                               op = SLJIT_SUB | GET_ALL_FLAGS(op);
-                                               flags &= ~ARGS_SWAPPED;
-                                               break;
-                                       }
-                               }
-                               if (GET_OPCODE(op) == SLJIT_SUB && !(flags & ARGS_SWAPPED)) {
-                                       src2_r = get_imm(-src2w);
-                                       if (src2_r) {
-                                               op = SLJIT_ADD | GET_ALL_FLAGS(op);
-                                               flags &= ~ARGS_SWAPPED;
-                                               break;
-                                       }
-                               }
-                       }
+       /* Destination. */
+       dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
 
-                       /* src2_r is 0. */
-                       if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
-                               FAIL_IF(compiler->error);
-                               src2_r = sugg_src2_r;
-                       }
-               } while (0);
-       }
+       if (op <= SLJIT_MOVU_P) {
+               if (dst & SLJIT_MEM) {
+                       if (inp_flags & BYTE_DATA)
+                               inp_flags &= ~SIGNED_DATA;
 
-       /* src1_r, src2_r and dst_r can be zero (=unprocessed) or non-zero.
-          If they are zero, they must not be registers. */
-       if (src1_r == 0 && src2_r == 0 && dst_r == 0) {
-               if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
-                       SLJIT_ASSERT(!(flags & ARGS_SWAPPED));
-                       flags |= ARGS_SWAPPED;
-                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src2, src2w, src1, src1w));
-                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src1, src1w, dst, dstw));
+                       if (FAST_IS_REG(src2))
+                               return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG2);
                }
-               else {
-                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
-                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
-               }
-               src1_r = TMP_REG1;
-               src2_r = TMP_REG2;
-       }
-       else if (src1_r == 0 && src2_r == 0) {
-               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
-               src1_r = TMP_REG1;
-       }
-       else if (src1_r == 0 && dst_r == 0) {
-               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
-               src1_r = TMP_REG1;
-       }
-       else if (src2_r == 0 && dst_r == 0) {
-               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
-               src2_r = sugg_src2_r;
+
+               if (FAST_IS_REG(src2) && dst_reg != TMP_REG2)
+                       flags |= MOVE_REG_CONV;
        }
 
-       if (dst_r == 0)
-               dst_r = TMP_REG2;
+       /* Source 2. */
+       if (src2_reg == 0) {
+               src2_reg = (op <= SLJIT_MOVU_P) ? dst_reg : TMP_REG2;
 
-       if (src1_r == 0) {
-               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
-               src1_r = TMP_REG1;
+               if (FAST_IS_REG(src2))
+                       src2_reg = src2;
+               else if (src2 & SLJIT_MEM)
+                       FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG2));
+               else
+                       FAIL_IF(load_immediate(compiler, src2_reg, src2w));
        }
 
-       if (src2_r == 0) {
-               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
-               src2_r = sugg_src2_r;
-       }
+       FAIL_IF(emit_single_op(compiler, op, flags, dst_reg, src1_reg, src2_reg));
 
-       FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+       if (!(dst & SLJIT_MEM))
+               return SLJIT_SUCCESS;
 
-       if (flags & (FAST_DEST | SLOW_DEST)) {
-               if (flags & FAST_DEST)
-                       FAIL_IF(getput_arg_fast(compiler, inp_flags, dst_r, dst, dstw));
-               else
-                       FAIL_IF(getput_arg(compiler, inp_flags, dst_r, dst, dstw, 0, 0));
-       }
-       return SLJIT_SUCCESS;
+       return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1);
 }
 
 #ifdef __cplusplus
@@ -1804,8 +1584,11 @@ extern int __aeabi_idivmod(int numerator, int denominator);
 }
 #endif
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
 {
+       sljit_sw saved_reg_list[3];
+       sljit_sw saved_reg_count;
+
        CHECK_ERROR();
        CHECK(check_sljit_emit_op0(compiler, op));
 
@@ -1817,100 +1600,119 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
        case SLJIT_NOP:
                FAIL_IF(push_inst(compiler, NOP));
                break;
-       case SLJIT_LUMUL:
-       case SLJIT_LSMUL:
-#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
-               return push_inst(compiler, (op == SLJIT_LUMUL ? UMULL : SMULL)
+       case SLJIT_LMUL_UW:
+       case SLJIT_LMUL_SW:
+               return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
                        | (reg_map[SLJIT_R1] << 16)
                        | (reg_map[SLJIT_R0] << 12)
                        | (reg_map[SLJIT_R0] << 8)
                        | reg_map[SLJIT_R1]);
-#else
-               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_R1))));
-               return push_inst(compiler, (op == SLJIT_LUMUL ? UMULL : SMULL)
-                       | (reg_map[SLJIT_R1] << 16)
-                       | (reg_map[SLJIT_R0] << 12)
-                       | (reg_map[SLJIT_R0] << 8)
-                       | reg_map[TMP_REG1]);
-#endif
-       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] */));
+       case SLJIT_DIVMOD_UW:
+       case SLJIT_DIVMOD_SW:
+       case SLJIT_DIV_UW:
+       case SLJIT_DIV_SW:
+               SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
+               SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3);
+
+               saved_reg_count = 0;
+               if (compiler->scratches >= 4)
+                       saved_reg_list[saved_reg_count++] = 3;
+               if (compiler->scratches >= 3)
+                       saved_reg_list[saved_reg_count++] = 2;
+               if (op >= SLJIT_DIV_UW)
+                       saved_reg_list[saved_reg_count++] = 1;
+
+               if (saved_reg_count > 0) {
+                       FAIL_IF(push_inst(compiler, 0xe52d0000 | (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_inst(compiler, 0xe58d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));
+                       }
+                       if (saved_reg_count >= 3) {
+                               SLJIT_ASSERT(saved_reg_list[2] < 8);
+                               FAIL_IF(push_inst(compiler, 0xe58d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));
+                       }
                }
-               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 | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+                       ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
 #else
 #error "Software divmod functions are needed"
 #endif
 
-               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 */));
+               if (saved_reg_count > 0) {
+                       if (saved_reg_count >= 3) {
+                               SLJIT_ASSERT(saved_reg_list[2] < 8);
+                               FAIL_IF(push_inst(compiler, 0xe59d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));
+                       }
+                       if (saved_reg_count >= 2) {
+                               SLJIT_ASSERT(saved_reg_list[1] < 8);
+                               FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
+                       }
+                       return push_inst(compiler, 0xe49d0000 | (saved_reg_count >= 3 ? 16 : 8)
+                                               | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
                }
-               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;
        }
 
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
        ADJUST_LOCAL_OFFSET(src, srcw);
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+               if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+                       return emit_op_mem(compiler, PRELOAD_DATA | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);
+#endif
+               return SLJIT_SUCCESS;
+       }
+
        switch (GET_OPCODE(op)) {
        case SLJIT_MOV:
-       case SLJIT_MOV_UI:
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOV_S32:
        case SLJIT_MOV_P:
                return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOV_UB:
-               return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+       case SLJIT_MOV_U8:
+               return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
 
-       case SLJIT_MOV_SB:
-               return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+       case SLJIT_MOV_S8:
+               return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
 
-       case SLJIT_MOV_UH:
-               return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+       case SLJIT_MOV_U16:
+               return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
 
-       case SLJIT_MOV_SH:
-               return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+       case SLJIT_MOV_S16:
+               return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
 
        case SLJIT_MOVU:
-       case SLJIT_MOVU_UI:
-       case SLJIT_MOVU_SI:
+       case SLJIT_MOVU_U32:
+       case SLJIT_MOVU_S32:
        case SLJIT_MOVU_P:
                return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOVU_UB:
-               return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+       case SLJIT_MOVU_U8:
+               return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
 
-       case SLJIT_MOVU_SB:
-               return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+       case SLJIT_MOVU_S8:
+               return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
 
-       case SLJIT_MOVU_UH:
-               return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+       case SLJIT_MOVU_U16:
+               return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
 
-       case SLJIT_MOVU_SH:
-               return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+       case SLJIT_MOVU_S16:
+               return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
 
        case SLJIT_NOT:
                return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
@@ -1929,10 +1731,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1940,6 +1742,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        ADJUST_LOCAL_OFFSET(src1, src1w);
        ADJUST_LOCAL_OFFSET(src2, src2w);
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+               return SLJIT_SUCCESS;
+
        switch (GET_OPCODE(op)) {
        case SLJIT_ADD:
        case SLJIT_ADDC:
@@ -1971,20 +1776,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_register_index(reg));
        return reg_map[reg];
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
        return reg << 1;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1996,43 +1801,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
 /*  Floating point operators                                             */
 /* --------------------------------------------------------------------- */
 
-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-
-/* 0 - no fpu
-   1 - vfp */
-static sljit_si arm_fpu_type = -1;
-
-static void init_compiler(void)
-{
-       if (arm_fpu_type != -1)
-               return;
-
-       /* TODO: Only the OS can help to determine the correct fpu type. */
-       arm_fpu_type = 1;
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
-       return SLJIT_IS_FPU_AVAILABLE;
-#else
-       if (arm_fpu_type == -1)
-               init_compiler();
-       return arm_fpu_type;
-#endif
-}
-
-#else
-
-#define arm_fpu_type 1
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
-{
-       /* Always available. */
-       return 1;
-}
-
-#endif
 
 #define FPU_LOAD (1 << 20)
 #define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \
@@ -2040,83 +1808,62 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
 #define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \
        ((opcode) | (mode) | ((dst) << 12) | (src1) | ((src2) << 16))
 
-static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
 {
-       sljit_sw tmp;
        sljit_uw imm;
-       sljit_sw inst = VSTR_F32 | (flags & (SLJIT_SINGLE_OP | FPU_LOAD));
+       sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD));
+
        SLJIT_ASSERT(arg & SLJIT_MEM);
+       arg &= ~SLJIT_MEM;
 
        if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
-               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))));
-               arg = SLJIT_MEM | TMP_REG1;
+               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG2, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))));
+               arg = TMP_REG2;
                argw = 0;
        }
 
        /* Fast loads and stores. */
-       if ((arg & REG_MASK)) {
+       if (arg) {
                if (!(argw & ~0x3fc))
                        return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2));
                if (!(-argw & ~0x3fc))
                        return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2));
-       }
-
-       if (compiler->cache_arg == arg) {
-               tmp = argw - compiler->cache_argw;
-               if (!(tmp & ~0x3fc))
-                       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, tmp >> 2));
-               if (!(-tmp & ~0x3fc))
-                       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG3, reg, -tmp >> 2));
-               if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) {
-                       FAIL_IF(compiler->error);
-                       compiler->cache_argw = argw;
-                       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0));
-               }
-       }
 
-       if (arg & REG_MASK) {
-               if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {
-                       FAIL_IF(compiler->error);
-                       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0));
-               }
                imm = get_imm(argw & ~0x3fc);
                if (imm) {
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, imm)));
-                       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2));
+                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG2, arg & REG_MASK, imm)));
+                       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, (argw & 0x3fc) >> 2));
                }
                imm = get_imm(-argw & ~0x3fc);
                if (imm) {
                        argw = -argw;
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & REG_MASK, imm)));
-                       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2));
+                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG2, arg & REG_MASK, imm)));
+                       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG2, reg, (argw & 0x3fc) >> 2));
                }
        }
 
-       compiler->cache_arg = arg;
-       compiler->cache_argw = argw;
-       if (arg & REG_MASK) {
-               FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
-               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & REG_MASK, reg_map[TMP_REG1])));
+       if (arg) {
+               FAIL_IF(load_immediate(compiler, TMP_REG2, argw));
+               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG2, arg & REG_MASK, RM(TMP_REG2))));
        }
        else
-               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+               FAIL_IF(load_immediate(compiler, TMP_REG2, argw));
 
-       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0));
+       return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, 0));
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
+       op ^= SLJIT_F32_OP;
+
        if (src & SLJIT_MEM) {
-               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
+               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
                src = TMP_FREG1;
        }
 
-       FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_SINGLE_OP, TMP_FREG1, src, 0)));
-
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
+       FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_F32_OP, TMP_FREG1, src, 0)));
 
        if (FAST_IS_REG(dst))
                return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | (TMP_FREG1 << 16));
@@ -2125,11 +1872,13 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
        return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+       op ^= SLJIT_F32_OP;
 
        if (FAST_IS_REG(src))
                FAIL_IF(push_inst(compiler, VMOV | RD(src) | (TMP_FREG1 << 16)));
@@ -2142,85 +1891,86 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
                FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | (TMP_FREG1 << 16)));
        }
 
-       FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_SINGLE_OP, dst_r, TMP_FREG1, 0)));
+       FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_F32_OP, dst_r, TMP_FREG1, 0)));
 
        if (dst & SLJIT_MEM)
-               return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
+               return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw);
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
+       op ^= SLJIT_F32_OP;
+
        if (src1 & SLJIT_MEM) {
-               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
+               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
                src1 = TMP_FREG1;
        }
 
        if (src2 & SLJIT_MEM) {
-               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
+               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
                src2 = TMP_FREG2;
        }
 
-       FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_SINGLE_OP, src1, src2, 0)));
+       FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_F32_OP, src1, src2, 0)));
        return push_inst(compiler, VMRS);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR();
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       if (GET_OPCODE(op) != SLJIT_CONVD_FROMS)
-               op ^= SLJIT_SINGLE_OP;
 
-       SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error);
+       SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error);
        SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
 
        dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
 
+       if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
+               op ^= SLJIT_F32_OP;
+
        if (src & SLJIT_MEM) {
-               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_r, src, srcw));
+               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw));
                src = dst_r;
        }
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DMOV:
+       case SLJIT_MOV_F64:
                if (src != dst_r) {
                        if (dst_r != TMP_FREG1)
-                               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_SINGLE_OP, dst_r, src, 0)));
+                               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_F32_OP, dst_r, src, 0)));
                        else
                                dst_r = src;
                }
                break;
-       case SLJIT_DNEG:
-               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_SINGLE_OP, dst_r, src, 0)));
+       case SLJIT_NEG_F64:
+               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_F32_OP, dst_r, src, 0)));
                break;
-       case SLJIT_DABS:
-               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_SINGLE_OP, dst_r, src, 0)));
+       case SLJIT_ABS_F64:
+               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_F32_OP, dst_r, src, 0)));
                break;
-       case SLJIT_CONVD_FROMS:
-               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_SINGLE_OP, dst_r, src, 0)));
-               op ^= SLJIT_SINGLE_OP;
+       case SLJIT_CONV_F64_FROM_F32:
+               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_F32_OP, dst_r, src, 0)));
+               op ^= SLJIT_F32_OP;
                break;
        }
 
        if (dst & SLJIT_MEM)
-               return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), dst_r, dst, dstw);
+               return emit_fop_mem(compiler, (op & SLJIT_F32_OP), dst_r, dst, dstw);
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -2228,42 +1978,40 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
        ADJUST_LOCAL_OFFSET(src1, src1w);
        ADJUST_LOCAL_OFFSET(src2, src2w);
 
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       op ^= SLJIT_SINGLE_OP;
+       op ^= SLJIT_F32_OP;
 
        dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
 
        if (src2 & SLJIT_MEM) {
-               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
+               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
                src2 = TMP_FREG2;
        }
 
        if (src1 & SLJIT_MEM) {
-               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
+               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
                src1 = TMP_FREG1;
        }
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DADD:
-               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_SINGLE_OP, dst_r, src2, src1)));
+       case SLJIT_ADD_F64:
+               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));
                break;
 
-       case SLJIT_DSUB:
-               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_SINGLE_OP, dst_r, src2, src1)));
+       case SLJIT_SUB_F64:
+               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));
                break;
 
-       case SLJIT_DMUL:
-               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_SINGLE_OP, dst_r, src2, src1)));
+       case SLJIT_MUL_F64:
+               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));
                break;
 
-       case SLJIT_DDIV:
-               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_SINGLE_OP, dst_r, src2, src1)));
+       case SLJIT_DIV_F64:
+               FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));
                break;
        }
 
        if (dst_r == TMP_FREG1)
-               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw));
+               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw));
 
        return SLJIT_SUCCESS;
 }
@@ -2276,83 +2024,70 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
 /*  Other instructions                                                   */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       /* For UNUSED dst. Uncommon, but possible. */
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
+       SLJIT_ASSERT(reg_map[TMP_REG1] == 14);
 
        if (FAST_IS_REG(dst))
-               return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3)));
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG1)));
 
        /* Memory. */
-       if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw))
-               return compiler->error;
-       /* TMP_REG3 is used for caching. */
-       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3))));
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
+       return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
        ADJUST_LOCAL_OFFSET(src, srcw);
 
+       SLJIT_ASSERT(reg_map[TMP_REG1] == 14);
+
        if (FAST_IS_REG(src))
-               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src))));
-       else if (src & SLJIT_MEM) {
-               if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw))
-                       FAIL_IF(compiler->error);
-               else {
-                       compiler->cache_arg = 0;
-                       compiler->cache_argw = 0;
-                       FAIL_IF(getput_arg(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, 0, 0));
-                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(TMP_REG2))));
-               }
-       }
+               FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, 0, RM(src))));
+       else if (src & SLJIT_MEM)
+               FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG2));
        else if (src & SLJIT_IMM)
-               FAIL_IF(load_immediate(compiler, TMP_REG3, srcw));
-       return push_inst(compiler, BLX | RM(TMP_REG3));
+               FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+
+       return push_inst(compiler, BX | RM(TMP_REG1));
 }
 
 /* --------------------------------------------------------------------- */
 /*  Conditional instructions                                             */
 /* --------------------------------------------------------------------- */
 
-static sljit_uw get_cc(sljit_si type)
+static sljit_uw get_cc(sljit_s32 type)
 {
        switch (type) {
        case SLJIT_EQUAL:
        case SLJIT_MUL_NOT_OVERFLOW:
-       case SLJIT_D_EQUAL:
+       case SLJIT_EQUAL_F64:
                return 0x00000000;
 
        case SLJIT_NOT_EQUAL:
        case SLJIT_MUL_OVERFLOW:
-       case SLJIT_D_NOT_EQUAL:
+       case SLJIT_NOT_EQUAL_F64:
                return 0x10000000;
 
        case SLJIT_LESS:
-       case SLJIT_D_LESS:
+       case SLJIT_LESS_F64:
                return 0x30000000;
 
        case SLJIT_GREATER_EQUAL:
-       case SLJIT_D_GREATER_EQUAL:
+       case SLJIT_GREATER_EQUAL_F64:
                return 0x20000000;
 
        case SLJIT_GREATER:
-       case SLJIT_D_GREATER:
+       case SLJIT_GREATER_F64:
                return 0x80000000;
 
        case SLJIT_LESS_EQUAL:
-       case SLJIT_D_LESS_EQUAL:
+       case SLJIT_LESS_EQUAL_F64:
                return 0x90000000;
 
        case SLJIT_SIG_LESS:
@@ -2368,11 +2103,11 @@ static sljit_uw get_cc(sljit_si type)
                return 0xd0000000;
 
        case SLJIT_OVERFLOW:
-       case SLJIT_D_UNORDERED:
+       case SLJIT_UNORDERED_F64:
                return 0x60000000;
 
        case SLJIT_NOT_OVERFLOW:
-       case SLJIT_D_ORDERED:
+       case SLJIT_ORDERED_F64:
                return 0x70000000;
 
        default:
@@ -2397,7 +2132,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
        return label;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
        struct sljit_jump *jump;
 
@@ -2414,7 +2149,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
        if (type >= SLJIT_FAST_CALL)
                PTR_FAIL_IF(prepare_blx(compiler));
        PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0,
-               type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0));
+               type <= SLJIT_JUMP ? TMP_PC : TMP_REG2, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0));
 
        if (jump->flags & SLJIT_REWRITABLE_JUMP) {
                jump->addr = compiler->size;
@@ -2431,14 +2166,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
 #else
        if (type >= SLJIT_FAST_CALL)
                jump->flags |= IS_BL;
-       PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
-       PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(type)));
+       PTR_FAIL_IF(emit_imm(compiler, TMP_REG2, 0));
+       PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2)) & ~COND_MASK) | get_cc(type)));
        jump->addr = compiler->size;
 #endif
        return jump;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
        struct sljit_jump *jump;
 
@@ -2452,7 +2187,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
                        return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
 
                SLJIT_ASSERT(src & SLJIT_MEM);
-               FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw));
+               FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG2));
                return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2));
        }
 
@@ -2464,74 +2199,99 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
        if (type >= SLJIT_FAST_CALL)
                FAIL_IF(prepare_blx(compiler));
-       FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
+       FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG2, TMP_PC, 0), 0));
        if (type >= SLJIT_FAST_CALL)
                FAIL_IF(emit_blx(compiler));
 #else
-       FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
-       FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
+       FAIL_IF(emit_imm(compiler, TMP_REG2, 0));
+       FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2)));
 #endif
        jump->addr = compiler->size;
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type)
 {
-       sljit_si dst_r, flags = GET_ALL_FLAGS(op);
+       sljit_s32 dst_r, flags = GET_ALL_FLAGS(op);
        sljit_uw cc, ins;
 
        CHECK_ERROR();
-       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
        ADJUST_LOCAL_OFFSET(dst, dstw);
-       ADJUST_LOCAL_OFFSET(src, srcw);
-
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
 
        op = GET_OPCODE(op);
        cc = get_cc(type & 0xff);
-       dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+       dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
 
        if (op < SLJIT_ADD) {
                FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 0)));
                FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc));
-               return (dst_r == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
+               if (dst & SLJIT_MEM)
+                       return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);
+               return SLJIT_SUCCESS;
        }
 
        ins = (op == SLJIT_AND ? AND_DP : (op == SLJIT_OR ? ORR_DP : EOR_DP));
-       if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) {
-               FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc));
-               /* The condition must always be set, even if the ORR/EOR is not executed above. */
-               return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))) : SLJIT_SUCCESS;
-       }
 
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       if (src & SLJIT_MEM) {
-               FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
-               src = TMP_REG1;
-               srcw = 0;
-       } else if (src & SLJIT_IMM) {
+       if (dst & SLJIT_MEM)
+               FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
+
+       FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, dst_r, SRC2_IMM | 1) & ~COND_MASK) | cc));
+
+       if (op == SLJIT_AND)
+               FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, dst_r, SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));
+
+       if (dst & SLJIT_MEM)
+               FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
+
+       if (flags & SLJIT_SET_Z)
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG2, SLJIT_UNUSED, RM(dst_r)));
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+       sljit_uw cc, tmp;
+
+       CHECK_ERROR();
+       CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+       dst_reg &= ~SLJIT_I32_OP;
+
+       cc = get_cc(type & 0xff);
+
+       if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
+               tmp = get_imm(srcw);
+               if (tmp)
+                       return push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_reg, SLJIT_UNUSED, tmp) & ~COND_MASK) | cc);
+
+               tmp = get_imm(~srcw);
+               if (tmp)
+                       return push_inst(compiler, (EMIT_DATA_PROCESS_INS(MVN_DP, 0, dst_reg, SLJIT_UNUSED, tmp) & ~COND_MASK) | cc);
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+               tmp = (sljit_uw) srcw;
+               FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));
+               if (tmp <= 0xffff)
+                       return SLJIT_SUCCESS;
+               return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));
+#else
                FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
                src = TMP_REG1;
-               srcw = 0;
+#endif
        }
 
-       FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 1) & ~COND_MASK) | cc));
-       FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));
-       if (dst_r == TMP_REG2)
-               FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0));
-
-       return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst_r))) : SLJIT_SUCCESS;
+       return push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_reg, SLJIT_UNUSED, RM(src)) & ~COND_MASK) | cc);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+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_si reg;
+       sljit_s32 reg;
 
        CHECK_ERROR_PTR();
        CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -2551,16 +2311,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
        set_const(const_, compiler);
 
        if (dst & SLJIT_MEM)
-               PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
+               PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw, TMP_REG1));
        return const_;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
 {
-       inline_set_jump_addr(addr, new_addr, 1);
+       inline_set_jump_addr(addr, executable_offset, new_target, 1);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
-       inline_set_const(addr, new_constant, 1);
+       inline_set_const(addr, executable_offset, new_constant, 1);
 }
index 044a675eee79e1bfc71e334f71075ff7d482e06d..fd67f502536b1eaaad812a0881e1b57c5e877311 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
 {
        return "ARM-64" SLJIT_CPUINFO;
 }
 
 /* Length of an instruction word */
-typedef sljit_ui sljit_ins;
+typedef sljit_u32 sljit_ins;
 
 #define TMP_ZERO       (0)
 
@@ -43,7 +43,7 @@ typedef sljit_ui sljit_ins;
 #define TMP_FREG1      (0)
 #define TMP_FREG2      (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
 
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
   31, 0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 29, 9, 10, 11, 30, 31
 };
 
@@ -76,6 +76,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
 #define BRK 0xd4200000
 #define CBZ 0xb4000000
 #define CLZ 0xdac01000
+#define CSEL 0x9a800000
 #define CSINC 0x9a800400
 #define EOR 0xca000000
 #define EORI 0xd2000000
@@ -124,7 +125,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
 
 /* dest_reg is the absolute name of the register
    Useful for reordering instructions in the delay slot. */
-static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
 {
        sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
        FAIL_IF(!ptr);
@@ -133,7 +134,7 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_imm64_const(struct sljit_compiler *compiler, sljit_si dst, sljit_uw imm)
+static SLJIT_INLINE sljit_s32 emit_imm64_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)
 {
        FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5)));
        FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 16) & 0xffff) << 5) | (1 << 21)));
@@ -143,7 +144,7 @@ static SLJIT_INLINE sljit_si emit_imm64_const(struct sljit_compiler *compiler, s
 
 static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm)
 {
-       sljit_si dst = inst[0] & 0x1f;
+       sljit_s32 dst = inst[0] & 0x1f;
        SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));
        inst[0] = MOVZ | dst | ((new_imm & 0xffff) << 5);
        inst[1] = MOVK | dst | (((new_imm >> 16) & 0xffff) << 5) | (1 << 21);
@@ -151,7 +152,7 @@ static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm)
        inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21);
 }
 
-static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_s32 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;
@@ -165,9 +166,10 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_ins
                target_addr = jump->u.target;
        else {
                SLJIT_ASSERT(jump->flags & JUMP_LABEL);
-               target_addr = (sljit_uw)(code + jump->u.label->size);
+               target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
        }
-       diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4);
+
+       diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4) - executable_offset;
 
        if (jump->flags & IS_COND) {
                diff += sizeof(sljit_ins);
@@ -211,8 +213,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        sljit_ins *buf_ptr;
        sljit_ins *buf_end;
        sljit_uw word_count;
+       sljit_sw executable_offset;
        sljit_uw addr;
-       sljit_si dst;
+       sljit_s32 dst;
 
        struct sljit_label *label;
        struct sljit_jump *jump;
@@ -228,6 +231,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
        code_ptr = code;
        word_count = 0;
+       executable_offset = SLJIT_EXEC_OFFSET(code);
+
        label = compiler->labels;
        jump = compiler->jumps;
        const_ = compiler->consts;
@@ -242,13 +247,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                        SLJIT_ASSERT(!jump || jump->addr >= word_count);
                        SLJIT_ASSERT(!const_ || const_->addr >= word_count);
                        if (label && label->size == word_count) {
-                               label->addr = (sljit_uw)code_ptr;
+                               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);
+                                       code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
                                        jump = jump->next;
                        }
                        if (const_ && const_->addr == word_count) {
@@ -263,7 +268,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        } while (buf);
 
        if (label && label->size == word_count) {
-               label->addr = (sljit_uw)code_ptr;
+               label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
                label->size = code_ptr - code;
                label = label->next;
        }
@@ -277,9 +282,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        while (jump) {
                do {
                        addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
-                       buf_ptr = (sljit_ins*)jump->addr;
+                       buf_ptr = (sljit_ins *)jump->addr;
+
                        if (jump->flags & PATCH_B) {
-                               addr = (sljit_sw)(addr - jump->addr) >> 2;
+                               addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
                                SLJIT_ASSERT((sljit_sw)addr <= 0x1ffffff && (sljit_sw)addr >= -0x2000000);
                                buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (addr & 0x3ffffff);
                                if (jump->flags & IS_COND)
@@ -287,7 +293,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                                break;
                        }
                        if (jump->flags & PATCH_COND) {
-                               addr = (sljit_sw)(addr - jump->addr) >> 2;
+                               addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
                                SLJIT_ASSERT((sljit_sw)addr <= 0x3ffff && (sljit_sw)addr >= -0x40000);
                                buf_ptr[0] = (buf_ptr[0] & ~0xffffe0) | ((addr & 0x7ffff) << 5);
                                break;
@@ -308,11 +314,37 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        }
 
        compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_offset = executable_offset;
        compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+
+       code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+       code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
        SLJIT_CACHE_FLUSH(code, code_ptr);
        return code;
 }
 
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+       switch (feature_type) {
+       case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+               return SLJIT_IS_FPU_AVAILABLE;
+#else
+               /* Available by default. */
+               return 1;
+#endif
+
+       case SLJIT_HAS_PRE_UPDATE:
+       case SLJIT_HAS_CLZ:
+       case SLJIT_HAS_CMOV:
+               return 1;
+
+       default:
+               return 0;
+       }
+}
+
 /* --------------------------------------------------------------------- */
 /*  Core code generator functions.                                       */
 /* --------------------------------------------------------------------- */
@@ -346,9 +378,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
 #define LOGICAL_IMM_CHECK 0x100
 
-static sljit_ins logical_imm(sljit_sw imm, sljit_si len)
+static sljit_ins logical_imm(sljit_sw imm, sljit_s32 len)
 {
-       sljit_si negated, ones, right;
+       sljit_s32 negated, ones, right;
        sljit_uw mask, uimm;
        sljit_ins ins;
 
@@ -356,16 +388,16 @@ static sljit_ins logical_imm(sljit_sw imm, sljit_si len)
                len &= ~LOGICAL_IMM_CHECK;
                if (len == 32 && (imm == 0 || imm == -1))
                        return 0;
-               if (len == 16 && ((sljit_si)imm == 0 || (sljit_si)imm == -1))
+               if (len == 16 && ((sljit_s32)imm == 0 || (sljit_s32)imm == -1))
                        return 0;
        }
 
        SLJIT_ASSERT((len == 32 && imm != 0 && imm != -1)
-               || (len == 16 && (sljit_si)imm != 0 && (sljit_si)imm != -1));
+               || (len == 16 && (sljit_s32)imm != 0 && (sljit_s32)imm != -1));
        uimm = (sljit_uw)imm;
        while (1) {
                if (len <= 0) {
-                       SLJIT_ASSERT_STOP();
+                       SLJIT_UNREACHABLE();
                        return 0;
                }
                mask = ((sljit_uw)1 << len) - 1;
@@ -410,10 +442,10 @@ static sljit_ins logical_imm(sljit_sw imm, sljit_si len)
 
 #undef COUNT_TRAILING_ZERO
 
-static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_sw simm)
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw simm)
 {
        sljit_uw imm = (sljit_uw)simm;
-       sljit_si i, zeros, ones, first;
+       sljit_s32 i, zeros, ones, first;
        sljit_ins bitmask;
 
        if (imm <= 0xffff)
@@ -512,15 +544,15 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sl
                        dst = TMP_ZERO; \
        }
 
-static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, sljit_si dst, sljit_sw arg1, sljit_sw arg2)
+static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_sw arg1, sljit_sw arg2)
 {
        /* dst must be register, TMP_REG1
           arg1 must be register, TMP_REG1, imm
           arg2 must be register, TMP_REG2, imm */
        sljit_ins inv_bits = (flags & INT_OP) ? (1 << 31) : 0;
        sljit_ins inst_bits;
-       sljit_si op = (flags & 0xffff);
-       sljit_si reg;
+       sljit_s32 op = (flags & 0xffff);
+       sljit_s32 reg;
        sljit_sw imm, nimm;
 
        if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
@@ -635,7 +667,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                        }
                        goto set_flags;
                default:
-                       SLJIT_ASSERT_STOP();
+                       SLJIT_UNREACHABLE();
                        break;
                }
 
@@ -667,34 +699,34 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                if (dst == arg2)
                        return SLJIT_SUCCESS;
                return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(arg2));
-       case SLJIT_MOV_UB:
-       case SLJIT_MOVU_UB:
+       case SLJIT_MOV_U8:
+       case SLJIT_MOVU_U8:
                SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
                return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (7 << 10));
-       case SLJIT_MOV_SB:
-       case SLJIT_MOVU_SB:
+       case SLJIT_MOV_S8:
+       case SLJIT_MOVU_S8:
                SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
                if (!(flags & INT_OP))
                        inv_bits |= 1 << 22;
                return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10));
-       case SLJIT_MOV_UH:
-       case SLJIT_MOVU_UH:
+       case SLJIT_MOV_U16:
+       case SLJIT_MOVU_U16:
                SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
                return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (15 << 10));
-       case SLJIT_MOV_SH:
-       case SLJIT_MOVU_SH:
+       case SLJIT_MOV_S16:
+       case SLJIT_MOVU_S16:
                SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
                if (!(flags & INT_OP))
                        inv_bits |= 1 << 22;
                return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10));
-       case SLJIT_MOV_UI:
-       case SLJIT_MOVU_UI:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOVU_U32:
                SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
                if ((flags & INT_OP) && dst == arg2)
                        return SLJIT_SUCCESS;
                return push_inst(compiler, (ORR ^ (1 << 31)) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
-       case SLJIT_MOV_SI:
-       case SLJIT_MOVU_SI:
+       case SLJIT_MOV_S32:
+       case SLJIT_MOVU_S32:
                SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
                if ((flags & INT_OP) && dst == arg2)
                        return SLJIT_SUCCESS;
@@ -702,7 +734,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
        case SLJIT_NOT:
                SLJIT_ASSERT(arg1 == TMP_REG1);
                FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)));
-               goto set_flags;
+               break; /* Set flags. */
        case SLJIT_NEG:
                SLJIT_ASSERT(arg1 == TMP_REG1);
                if (flags & SET_FLAGS)
@@ -710,8 +742,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
        case SLJIT_CLZ:
                SLJIT_ASSERT(arg1 == TMP_REG1);
-               FAIL_IF(push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2)));
-               goto set_flags;
+               return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2));
        case SLJIT_ADD:
                CHECK_FLAGS(1 << 29);
                return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
@@ -740,24 +771,24 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
        case SLJIT_OR:
                FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
-               goto set_flags;
+               break; /* Set flags. */
        case SLJIT_XOR:
                FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
-               goto set_flags;
+               break; /* Set flags. */
        case SLJIT_SHL:
                FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
-               goto set_flags;
+               break; /* Set flags. */
        case SLJIT_LSHR:
                FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
-               goto set_flags;
+               break; /* Set flags. */
        case SLJIT_ASHR:
                FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
-               goto set_flags;
+               break; /* Set flags. */
+       default:
+               SLJIT_UNREACHABLE();
+               return SLJIT_SUCCESS;
        }
 
-       SLJIT_ASSERT_STOP();
-       return SLJIT_SUCCESS;
-
 set_flags:
        if (flags & SET_FLAGS)
                return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO));
@@ -777,28 +808,28 @@ set_flags:
 
 #define MEM_SIZE_SHIFT(flags) ((flags) >> 8)
 
-static SLJIT_CONST sljit_ins sljit_mem_imm[4] = {
+static const sljit_ins sljit_mem_imm[4] = {
 /* u l */ 0x39400000 /* ldrb [reg,imm] */,
 /* u s */ 0x39000000 /* strb [reg,imm] */,
 /* s l */ 0x39800000 /* ldrsb [reg,imm] */,
 /* s s */ 0x39000000 /* strb [reg,imm] */,
 };
 
-static SLJIT_CONST sljit_ins sljit_mem_simm[4] = {
+static const sljit_ins sljit_mem_simm[4] = {
 /* u l */ 0x38400000 /* ldurb [reg,imm] */,
 /* u s */ 0x38000000 /* sturb [reg,imm] */,
 /* s l */ 0x38800000 /* ldursb [reg,imm] */,
 /* s s */ 0x38000000 /* sturb [reg,imm] */,
 };
 
-static SLJIT_CONST sljit_ins sljit_mem_pre_simm[4] = {
+static const sljit_ins sljit_mem_pre_simm[4] = {
 /* u l */ 0x38400c00 /* ldrb [reg,imm]! */,
 /* u s */ 0x38000c00 /* strb [reg,imm]! */,
 /* s l */ 0x38800c00 /* ldrsb [reg,imm]! */,
 /* s s */ 0x38000c00 /* strb [reg,imm]! */,
 };
 
-static SLJIT_CONST sljit_ins sljit_mem_reg[4] = {
+static const sljit_ins sljit_mem_reg[4] = {
 /* u l */ 0x38606800 /* ldrb [reg,reg] */,
 /* u s */ 0x38206800 /* strb [reg,reg] */,
 /* s l */ 0x38a06800 /* ldrsb [reg,reg] */,
@@ -806,7 +837,7 @@ static SLJIT_CONST sljit_ins sljit_mem_reg[4] = {
 };
 
 /* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
-static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sljit_si reg, sljit_sw value)
+static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value)
 {
        if (value >= 0) {
                if (value <= 0xfff)
@@ -825,9 +856,9 @@ static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sl
 }
 
 /* Can perform an operation using at most 1 instruction. */
-static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
 {
-       sljit_ui shift = MEM_SIZE_SHIFT(flags);
+       sljit_u32 shift = MEM_SIZE_SHIFT(flags);
 
        SLJIT_ASSERT(arg & SLJIT_MEM);
 
@@ -859,6 +890,10 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
        }
 
        arg &= REG_MASK;
+
+       if (arg == SLJIT_UNUSED)
+               return 0;
+
        if (argw >= 0 && (argw >> shift) <= 0xfff && (argw & ((1 << shift) - 1)) == 0) {
                if (SLJIT_UNLIKELY(flags & ARG_TEST))
                        return 1;
@@ -882,7 +917,7 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
 /* see getput_arg below.
    Note: can_cache is called only for binary operators. Those
    operators always uses word arguments without write back. */
-static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
        sljit_sw diff;
        if ((arg & OFFS_REG_MASK) || !(next_arg & SLJIT_MEM))
@@ -906,11 +941,11 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
 }
 
 /* Emit the necessary instructions. See can_cache above. */
-static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg,
-       sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
+       sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
-       sljit_ui shift = MEM_SIZE_SHIFT(flags);
-       sljit_si tmp_r, other_r;
+       sljit_u32 shift = MEM_SIZE_SHIFT(flags);
+       sljit_s32 tmp_r, other_r;
        sljit_sw diff;
 
        SLJIT_ASSERT(arg & SLJIT_MEM);
@@ -919,21 +954,23 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
                next_argw = 0;
        }
 
-       tmp_r = (flags & STORE) ? TMP_REG3 : reg;
+       tmp_r = ((flags & STORE) || (flags == (WORD_SIZE | SIGNED))) ? TMP_REG3 : reg;
 
        if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) {
                /* Update only applies if a base register exists. */
                other_r = OFFS_REG(arg);
                if (!other_r) {
                        other_r = arg & REG_MASK;
-                       if (other_r != reg && argw >= 0 && argw <= 0xffffff) {
+                       SLJIT_ASSERT(other_r != reg);
+
+                       if (argw >= 0 && argw <= 0xffffff) {
                                if ((argw & 0xfff) != 0)
                                        FAIL_IF(push_inst(compiler, ADDI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10)));
                                if (argw >> 12)
                                        FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10)));
                                return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r));
                        }
-                       else if (other_r != reg && argw < 0 && argw >= -0xffffff) {
+                       else if (argw < 0 && argw >= -0xffffff) {
                                argw = -argw;
                                if ((argw & 0xfff) != 0)
                                        FAIL_IF(push_inst(compiler, SUBI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10)));
@@ -966,18 +1003,8 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
 
                /* No caching here. */
                arg &= REG_MASK;
-               argw &= 0x3;
-               if (!argw || argw == shift) {
-                       FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(other_r) | (argw ? (1 << 12) : 0)));
-                       return push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10));
-               }
-               if (arg != reg) {
-                       FAIL_IF(push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10)));
-                       return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg));
-               }
-               FAIL_IF(push_inst(compiler, ADD | RD(TMP_LR) | RN(arg) | RM(other_r) | (argw << 10)));
-               FAIL_IF(push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_LR)));
-               return push_inst(compiler, ORR | RD(arg) | RN(TMP_ZERO) | RM(TMP_LR));
+               FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(other_r)));
+               return push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r));
        }
 
        if (arg & OFFS_REG_MASK) {
@@ -998,16 +1025,16 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
                }
        }
 
-       if (argw >= 0 && argw <= 0xffffff && (argw & ((1 << shift) - 1)) == 0) {
-               FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_r) | RN(arg & REG_MASK) | ((argw >> 12) << 10)));
-               return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30)
-                       | RT(reg) | RN(tmp_r) | ((argw & 0xfff) << (10 - shift)));
-       }
-
        diff = argw - next_argw;
        next_arg = (arg & REG_MASK) && (arg == next_arg) && diff <= 0xfff && diff >= -0xfff && diff != 0;
        arg &= REG_MASK;
 
+       if (arg != SLJIT_UNUSED && argw >= 0 && argw <= 0xffffff && (argw & ((1 << shift) - 1)) == 0) {
+               FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_r) | RN(arg) | ((argw >> 12) << 10)));
+               return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30)
+                       | RT(reg) | RN(tmp_r) | ((argw & 0xfff) << (10 - shift)));
+       }
+
        if (arg && compiler->cache_arg == SLJIT_MEM) {
                if (compiler->cache_argw == argw)
                        return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3));
@@ -1040,7 +1067,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
        return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_REG3));
 }
 
-static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
 {
        if (getput_arg_fast(compiler, flags, reg, arg, argw))
                return compiler->error;
@@ -1049,7 +1076,7 @@ static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_
        return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
 }
 
-static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
 {
        if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
                return compiler->error;
@@ -1060,11 +1087,11 @@ static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit
 /*  Entry, exit                                                          */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
-       sljit_si i, tmp, offs, prev, saved_regs_size;
+       sljit_s32 i, tmp, offs, prev, saved_regs_size;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -1148,9 +1175,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
        CHECK_ERROR();
        CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -1162,10 +1189,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si local_size;
-       sljit_si i, tmp, offs, prev, saved_regs_size;
+       sljit_s32 local_size;
+       sljit_s32 i, tmp, offs, prev, saved_regs_size;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_return(compiler, op, src, srcw));
@@ -1243,9 +1270,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
 /*  Operators                                                            */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
 {
-       sljit_ins inv_bits = (op & SLJIT_INT_OP) ? (1 << 31) : 0;
+       sljit_ins inv_bits = (op & SLJIT_I32_OP) ? (1 << 31) : 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op0(compiler, op));
@@ -1256,31 +1283,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
                return push_inst(compiler, BRK);
        case SLJIT_NOP:
                return push_inst(compiler, NOP);
-       case SLJIT_LUMUL:
-       case SLJIT_LSMUL:
+       case SLJIT_LMUL_UW:
+       case SLJIT_LMUL_SW:
                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_UDIVMOD:
-       case SLJIT_SDIVMOD:
+               return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
+       case SLJIT_DIVMOD_UW:
+       case SLJIT_DIVMOD_SW:
                FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));
-               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, ((op == SLJIT_DIVMOD_UW ? 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));
+       case SLJIT_DIV_UW:
+       case SLJIT_DIV_SW:
+               return push_inst(compiler, ((op == SLJIT_DIV_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1));
        }
 
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r, flags, mem_flags;
-       sljit_si op_flags = GET_ALL_FLAGS(op);
+       sljit_s32 dst_r, flags, mem_flags;
+       sljit_s32 op_flags = GET_ALL_FLAGS(op);
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
@@ -1290,6 +1317,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+               if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) {
+                       SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4);
+
+                       if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8)
+                               dst = 5;
+                       else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16)
+                               dst = 3;
+                       else
+                               dst = 1;
+
+                       /* Signed word sized load is the prefetch instruction. */
+                       return emit_op_mem(compiler, WORD_SIZE | SIGNED, dst, src, srcw);
+               }
+               return SLJIT_SUCCESS;
+       }
+
        dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
 
        op = GET_OPCODE(op);
@@ -1299,72 +1343,72 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
                case SLJIT_MOV_P:
                        flags = WORD_SIZE;
                        break;
-               case SLJIT_MOV_UB:
+               case SLJIT_MOV_U8:
                        flags = BYTE_SIZE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_ub)srcw;
+                               srcw = (sljit_u8)srcw;
                        break;
-               case SLJIT_MOV_SB:
+               case SLJIT_MOV_S8:
                        flags = BYTE_SIZE | SIGNED;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_sb)srcw;
+                               srcw = (sljit_s8)srcw;
                        break;
-               case SLJIT_MOV_UH:
+               case SLJIT_MOV_U16:
                        flags = HALF_SIZE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_uh)srcw;
+                               srcw = (sljit_u16)srcw;
                        break;
-               case SLJIT_MOV_SH:
+               case SLJIT_MOV_S16:
                        flags = HALF_SIZE | SIGNED;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_sh)srcw;
+                               srcw = (sljit_s16)srcw;
                        break;
-               case SLJIT_MOV_UI:
+               case SLJIT_MOV_U32:
                        flags = INT_SIZE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_ui)srcw;
+                               srcw = (sljit_u32)srcw;
                        break;
-               case SLJIT_MOV_SI:
+               case SLJIT_MOV_S32:
                        flags = INT_SIZE | SIGNED;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_si)srcw;
+                               srcw = (sljit_s32)srcw;
                        break;
                case SLJIT_MOVU:
                case SLJIT_MOVU_P:
                        flags = WORD_SIZE | UPDATE;
                        break;
-               case SLJIT_MOVU_UB:
+               case SLJIT_MOVU_U8:
                        flags = BYTE_SIZE | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_ub)srcw;
+                               srcw = (sljit_u8)srcw;
                        break;
-               case SLJIT_MOVU_SB:
+               case SLJIT_MOVU_S8:
                        flags = BYTE_SIZE | SIGNED | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_sb)srcw;
+                               srcw = (sljit_s8)srcw;
                        break;
-               case SLJIT_MOVU_UH:
+               case SLJIT_MOVU_U16:
                        flags = HALF_SIZE | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_uh)srcw;
+                               srcw = (sljit_u16)srcw;
                        break;
-               case SLJIT_MOVU_SH:
+               case SLJIT_MOVU_S16:
                        flags = HALF_SIZE | SIGNED | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_sh)srcw;
+                               srcw = (sljit_s16)srcw;
                        break;
-               case SLJIT_MOVU_UI:
+               case SLJIT_MOVU_U32:
                        flags = INT_SIZE | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_ui)srcw;
+                               srcw = (sljit_u32)srcw;
                        break;
-               case SLJIT_MOVU_SI:
+               case SLJIT_MOVU_S32:
                        flags = INT_SIZE | SIGNED | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_si)srcw;
+                               srcw = (sljit_s32)srcw;
                        break;
                default:
-                       SLJIT_ASSERT_STOP();
+                       SLJIT_UNREACHABLE();
                        flags = 0;
                        break;
                }
@@ -1378,7 +1422,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
                                FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw));
                } else {
                        if (dst_r != TMP_REG1)
-                               return emit_op_imm(compiler, op | ((op_flags & SLJIT_INT_OP) ? INT_OP : 0), dst_r, TMP_REG1, src);
+                               return emit_op_imm(compiler, op | ((op_flags & SLJIT_I32_OP) ? INT_OP : 0), dst_r, TMP_REG1, src);
                        dst_r = src;
                }
 
@@ -1391,9 +1435,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
                return SLJIT_SUCCESS;
        }
 
-       flags = GET_FLAGS(op_flags) ? SET_FLAGS : 0;
+       flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;
        mem_flags = WORD_SIZE;
-       if (op_flags & SLJIT_INT_OP) {
+       if (op_flags & SLJIT_I32_OP) {
                flags |= INT_OP;
                mem_flags = INT_SIZE;
        }
@@ -1411,8 +1455,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
 
        if (src & SLJIT_IMM) {
                flags |= ARG2_IMM;
-               if (op_flags & SLJIT_INT_OP)
-                       srcw = (sljit_si)srcw;
+               if (op_flags & SLJIT_I32_OP)
+                       srcw = (sljit_s32)srcw;
        } else
                srcw = src;
 
@@ -1427,12 +1471,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si dst_r, flags, mem_flags;
+       sljit_s32 dst_r, flags, mem_flags;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1443,10 +1487,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+               return SLJIT_SUCCESS;
+
        dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
-       flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+       flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
        mem_flags = WORD_SIZE;
-       if (op & SLJIT_INT_OP) {
+       if (op & SLJIT_I32_OP) {
                flags |= INT_OP;
                mem_flags = INT_SIZE;
        }
@@ -1512,20 +1559,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_register_index(reg));
        return reg_map[reg];
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
        return reg;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1537,21 +1584,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
 /*  Floating point operators                                             */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
+static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
 {
-#ifdef SLJIT_IS_FPU_AVAILABLE
-       return SLJIT_IS_FPU_AVAILABLE;
-#else
-       /* Available by default. */
-       return 1;
-#endif
-}
-
-static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
-{
-       sljit_ui shift = MEM_SIZE_SHIFT(flags);
+       sljit_u32 shift = MEM_SIZE_SHIFT(flags);
        sljit_ins ins_bits = (shift << 30);
-       sljit_si other_r;
+       sljit_s32 other_r;
        sljit_sw diff;
 
        SLJIT_ASSERT(arg & SLJIT_MEM);
@@ -1600,45 +1637,45 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
        return push_inst(compiler, STR_FI | ins_bits | VT(reg) | RN(TMP_REG3));
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
-       sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+       sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
 
-       if (GET_OPCODE(op) == SLJIT_CONVI_FROMD)
+       if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64)
                inv_bits |= (1 << 31);
 
        if (src & SLJIT_MEM) {
-               emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw);
+               emit_fop_mem(compiler, (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw);
                src = TMP_FREG1;
        }
 
        FAIL_IF(push_inst(compiler, (FCVTZS ^ inv_bits) | RD(dst_r) | VN(src)));
 
-       if (dst_r == TMP_REG1 && dst != SLJIT_UNUSED)
-               return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONVI_FROMD) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw);
+       if (dst & SLJIT_MEM)
+               return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw);
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
-       sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+       sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
 
-       if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
+       if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
                inv_bits |= (1 << 31);
 
        if (src & SLJIT_MEM) {
-               emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONVD_FROMI) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw);
+               emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw);
                src = TMP_REG1;
        } else if (src & SLJIT_IMM) {
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-               if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
-                       srcw = (sljit_si)srcw;
+               if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+                       srcw = (sljit_s32)srcw;
 #endif
                FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
                src = TMP_REG1;
@@ -1647,16 +1684,16 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
        FAIL_IF(push_inst(compiler, (SCVTF ^ inv_bits) | VD(dst_r) | RN(src)));
 
        if (dst & SLJIT_MEM)
-               return emit_fop_mem(compiler, ((op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw);
+               return emit_fop_mem(compiler, ((op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw);
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE;
-       sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
+       sljit_s32 mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE;
+       sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
 
        if (src1 & SLJIT_MEM) {
                emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w);
@@ -1671,11 +1708,11 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler
        return push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r, mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE;
+       sljit_s32 dst_r, mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE;
        sljit_ins inv_bits;
 
        CHECK_ERROR();
@@ -1685,16 +1722,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
        SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x100) == WORD_SIZE, must_be_one_bit_difference);
        SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
 
-       inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
+       inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
        dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
 
        if (src & SLJIT_MEM) {
-               emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONVD_FROMS) ? (mem_flags ^ 0x100) : mem_flags, dst_r, src, srcw);
+               emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x100) : mem_flags, dst_r, src, srcw);
                src = dst_r;
        }
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DMOV:
+       case SLJIT_MOV_F64:
                if (src != dst_r) {
                        if (dst_r != TMP_FREG1)
                                FAIL_IF(push_inst(compiler, (FMOV ^ inv_bits) | VD(dst_r) | VN(src)));
@@ -1702,14 +1739,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
                                dst_r = src;
                }
                break;
-       case SLJIT_DNEG:
+       case SLJIT_NEG_F64:
                FAIL_IF(push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(src)));
                break;
-       case SLJIT_DABS:
+       case SLJIT_ABS_F64:
                FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src)));
                break;
-       case SLJIT_CONVD_FROMS:
-               FAIL_IF(push_inst(compiler, FCVT | ((op & SLJIT_SINGLE_OP) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src)));
+       case SLJIT_CONV_F64_FROM_F32:
+               FAIL_IF(push_inst(compiler, FCVT | ((op & SLJIT_F32_OP) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src)));
                break;
        }
 
@@ -1718,13 +1755,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si dst_r, mem_flags = (op & SLJIT_SINGLE_OP) ? INT_SIZE : WORD_SIZE;
-       sljit_ins inv_bits = (op & SLJIT_SINGLE_OP) ? (1 << 22) : 0;
+       sljit_s32 dst_r, mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE;
+       sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1746,16 +1783,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
        }
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DADD:
+       case SLJIT_ADD_F64:
                FAIL_IF(push_inst(compiler, (FADD ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
                break;
-       case SLJIT_DSUB:
+       case SLJIT_SUB_F64:
                FAIL_IF(push_inst(compiler, (FSUB ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
                break;
-       case SLJIT_DMUL:
+       case SLJIT_MUL_F64:
                FAIL_IF(push_inst(compiler, (FMUL ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
                break;
-       case SLJIT_DDIV:
+       case SLJIT_DIV_F64:
                FAIL_IF(push_inst(compiler, (FDIV ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
                break;
        }
@@ -1769,16 +1806,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
 /*  Other instructions                                                   */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       /* For UNUSED dst. Uncommon, but possible. */
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
-
        if (FAST_IS_REG(dst))
                return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR));
 
@@ -1786,7 +1819,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
        return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
@@ -1806,33 +1839,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
 /*  Conditional instructions                                             */
 /* --------------------------------------------------------------------- */
 
-static sljit_uw get_cc(sljit_si type)
+static sljit_uw get_cc(sljit_s32 type)
 {
        switch (type) {
        case SLJIT_EQUAL:
        case SLJIT_MUL_NOT_OVERFLOW:
-       case SLJIT_D_EQUAL:
+       case SLJIT_EQUAL_F64:
                return 0x1;
 
        case SLJIT_NOT_EQUAL:
        case SLJIT_MUL_OVERFLOW:
-       case SLJIT_D_NOT_EQUAL:
+       case SLJIT_NOT_EQUAL_F64:
                return 0x0;
 
        case SLJIT_LESS:
-       case SLJIT_D_LESS:
+       case SLJIT_LESS_F64:
                return 0x2;
 
        case SLJIT_GREATER_EQUAL:
-       case SLJIT_D_GREATER_EQUAL:
+       case SLJIT_GREATER_EQUAL_F64:
                return 0x3;
 
        case SLJIT_GREATER:
-       case SLJIT_D_GREATER:
+       case SLJIT_GREATER_F64:
                return 0x9;
 
        case SLJIT_LESS_EQUAL:
-       case SLJIT_D_LESS_EQUAL:
+       case SLJIT_LESS_EQUAL_F64:
                return 0x8;
 
        case SLJIT_SIG_LESS:
@@ -1848,15 +1881,15 @@ static sljit_uw get_cc(sljit_si type)
                return 0xc;
 
        case SLJIT_OVERFLOW:
-       case SLJIT_D_UNORDERED:
+       case SLJIT_UNORDERED_F64:
                return 0x7;
 
        case SLJIT_NOT_OVERFLOW:
-       case SLJIT_D_ORDERED:
+       case SLJIT_ORDERED_F64:
                return 0x6;
 
        default:
-               SLJIT_ASSERT_STOP();
+               SLJIT_UNREACHABLE();
                return 0xe;
        }
 }
@@ -1877,7 +1910,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
        return label;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
        struct sljit_jump *jump;
 
@@ -1903,11 +1936,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
        return jump;
 }
 
-static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src, sljit_sw srcw)
 {
        struct sljit_jump *jump;
-       sljit_ins inv_bits = (type & SLJIT_INT_OP) ? (1 << 31) : 0;
+       sljit_ins inv_bits = (type & SLJIT_I32_OP) ? (1 << 31) : 0;
 
        SLJIT_ASSERT((type & 0xff) == SLJIT_EQUAL || (type & 0xff) == SLJIT_NOT_EQUAL);
        ADJUST_LOCAL_OFFSET(src, srcw);
@@ -1937,7 +1970,7 @@ static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compi
        return jump;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
        struct sljit_jump *jump;
 
@@ -1964,21 +1997,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
        return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type)
 {
-       sljit_si dst_r, flags, mem_flags;
+       sljit_s32 dst_r, src_r, flags, mem_flags;
        sljit_ins cc;
 
        CHECK_ERROR();
-       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
        ADJUST_LOCAL_OFFSET(dst, dstw);
-       ADJUST_LOCAL_OFFSET(src, srcw);
-
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
 
        cc = get_cc(type & 0xff);
        dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
@@ -1992,32 +2020,56 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
 
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
-       flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+       flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
        mem_flags = WORD_SIZE;
-       if (op & SLJIT_INT_OP) {
+       if (op & SLJIT_I32_OP) {
                flags |= INT_OP;
                mem_flags = INT_SIZE;
        }
 
-       if (src & SLJIT_MEM) {
-               FAIL_IF(emit_op_mem2(compiler, mem_flags, TMP_REG1, src, srcw, dst, dstw));
+       src_r = dst;
+
+       if (dst & SLJIT_MEM) {
+               FAIL_IF(emit_op_mem2(compiler, mem_flags, TMP_REG1, dst, dstw, dst, dstw));
+               src_r = TMP_REG1;
+       }
+
+       FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO)));
+       emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src_r, TMP_REG2);
+
+       if (dst & SLJIT_MEM)
+               return emit_op_mem2(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0);
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+       sljit_ins inv_bits = (dst_reg & SLJIT_I32_OP) ? (1 << 31) : 0;
+       sljit_ins cc;
+
+       CHECK_ERROR();
+       CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+       if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
+               if (dst_reg & SLJIT_I32_OP)
+                       srcw = (sljit_s32)srcw;
+               FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
                src = TMP_REG1;
                srcw = 0;
-       } else if (src & SLJIT_IMM)
-               flags |= ARG1_IMM;
+       }
 
-       FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO)));
-       emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src, TMP_REG2);
+       cc = get_cc(type & 0xff);
+       dst_reg &= ~SLJIT_I32_OP;
 
-       if (dst_r != TMP_REG1)
-               return SLJIT_SUCCESS;
-       return emit_op_mem2(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0);
+       return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+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_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR_PTR();
        CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -2027,7 +2079,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
        PTR_FAIL_IF(!const_);
        set_const(const_, compiler);
 
-       dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+       dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
        PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, init_value));
 
        if (dst & SLJIT_MEM)
@@ -2035,16 +2087,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
        return const_;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+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;
-       modify_imm64_const(inst, new_addr);
+       modify_imm64_const(inst, new_target);
+       inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
        SLJIT_CACHE_FLUSH(inst, inst + 4);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
        sljit_ins* inst = (sljit_ins*)addr;
        modify_imm64_const(inst, new_constant);
+       inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
        SLJIT_CACHE_FLUSH(inst, inst + 4);
 }
index f9803f5d44f7b102a60f94384e083a7c8d1fdd1e..29e5566a820c4d051998fc618cae61cc76c41067 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
 {
        return "ARM-Thumb2" SLJIT_CPUINFO;
 }
 
 /* Length of an instruction word. */
-typedef sljit_ui sljit_ins;
+typedef sljit_u32 sljit_ins;
 
 /* Last register + 1. */
 #define TMP_REG1       (SLJIT_NUMBER_OF_REGISTERS + 2)
 #define TMP_REG2       (SLJIT_NUMBER_OF_REGISTERS + 3)
-#define TMP_REG3       (SLJIT_NUMBER_OF_REGISTERS + 4)
-#define TMP_PC         (SLJIT_NUMBER_OF_REGISTERS + 5)
+#define TMP_PC         (SLJIT_NUMBER_OF_REGISTERS + 4)
 
 #define TMP_FREG1      (0)
 #define TMP_FREG2      (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
 
 /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
-       0, 0, 1, 2, 12, 11, 10, 9, 8, 7, 6, 5, 13, 3, 4, 14, 15
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
+       0, 0, 1, 2, 12, 11, 10, 9, 8, 7, 6, 5, 4, 13, 3, 14, 15
 };
 
 #define COPY_BITS(src, from, to, bits) \
@@ -108,7 +107,11 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
 #define BLX            0x4780
 #define BX             0x4700
 #define CLZ            0xfab0f080
+#define CMNI_W         0xf1100f00
+#define CMP            0x4280
 #define CMPI           0x2800
+#define CMPI_W         0xf1b00f00
+#define CMP_X          0x4500
 #define CMP_W          0xebb00f00
 #define EORI           0xf0800000
 #define EORS           0x4040
@@ -181,21 +184,21 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
 #define VSTR_F32       0xed000a00
 #define VSUB_F32       0xee300a40
 
-static sljit_si push_inst16(struct sljit_compiler *compiler, sljit_ins inst)
+static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_ins inst)
 {
-       sljit_uh *ptr;
+       sljit_u16 *ptr;
        SLJIT_ASSERT(!(inst & 0xffff0000));
 
-       ptr = (sljit_uh*)ensure_buf(compiler, sizeof(sljit_uh));
+       ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16));
        FAIL_IF(!ptr);
        *ptr = inst;
        compiler->size++;
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
+static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
 {
-       sljit_uh *ptr = (sljit_uh*)ensure_buf(compiler, sizeof(sljit_ins));
+       sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins));
        FAIL_IF(!ptr);
        *ptr++ = inst >> 16;
        *ptr = inst;
@@ -203,7 +206,7 @@ static sljit_si push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_imm32_const(struct sljit_compiler *compiler, sljit_si dst, sljit_uw imm)
+static SLJIT_INLINE sljit_s32 emit_imm32_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)
 {
        FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) |
                COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
@@ -211,9 +214,9 @@ static SLJIT_INLINE sljit_si emit_imm32_const(struct sljit_compiler *compiler, s
                COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
 }
 
-static SLJIT_INLINE void modify_imm32_const(sljit_uh *inst, sljit_uw new_imm)
+static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm)
 {
-       sljit_si dst = inst[1] & 0x0f00;
+       sljit_s32 dst = inst[1] & 0x0f00;
        SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));
        inst[0] = (MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1);
        inst[1] = dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff);
@@ -221,7 +224,7 @@ static SLJIT_INLINE void modify_imm32_const(sljit_uh *inst, sljit_uw new_imm)
        inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16);
 }
 
-static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uh *code_ptr, sljit_uh *code)
+static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
 {
        sljit_sw diff;
 
@@ -232,7 +235,7 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uh
                /* Branch to ARM code is not optimized yet. */
                if (!(jump->u.target & 0x1))
                        return 0;
-               diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2)) >> 1;
+               diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset) >> 1;
        }
        else {
                SLJIT_ASSERT(jump->flags & JUMP_LABEL);
@@ -276,25 +279,27 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uh
        return 0;
 }
 
-static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
+static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw executable_offset)
 {
-       sljit_si type = (jump->flags >> 4) & 0xf;
+       sljit_s32 type = (jump->flags >> 4) & 0xf;
        sljit_sw diff;
-       sljit_uh *jump_inst;
-       sljit_si s, j1, j2;
+       sljit_u16 *jump_inst;
+       sljit_s32 s, j1, j2;
 
        if (SLJIT_UNLIKELY(type == 0)) {
-               modify_imm32_const((sljit_uh*)jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);
+               modify_imm32_const((sljit_u16*)jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);
                return;
        }
 
        if (jump->flags & JUMP_ADDR) {
                SLJIT_ASSERT(jump->u.target & 0x1);
-               diff = ((sljit_sw)jump->u.target - (sljit_sw)(jump->addr + 4)) >> 1;
+               diff = ((sljit_sw)jump->u.target - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1;
        }
-       else
-               diff = ((sljit_sw)(jump->u.label->addr) - (sljit_sw)(jump->addr + 4)) >> 1;
-       jump_inst = (sljit_uh*)jump->addr;
+       else {
+               SLJIT_ASSERT(jump->u.label->addr & 0x1);
+               diff = ((sljit_sw)(jump->u.label->addr) - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1;
+       }
+       jump_inst = (sljit_u16*)jump->addr;
 
        switch (type) {
        case 1:
@@ -336,17 +341,18 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
        else if (type == 6) /* Encoding T1 of 'BL' instruction */
                jump_inst[1] |= 0xd000;
        else
-               SLJIT_ASSERT_STOP();
+               SLJIT_UNREACHABLE();
 }
 
 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
 {
        struct sljit_memory_fragment *buf;
-       sljit_uh *code;
-       sljit_uh *code_ptr;
-       sljit_uh *buf_ptr;
-       sljit_uh *buf_end;
+       sljit_u16 *code;
+       sljit_u16 *code_ptr;
+       sljit_u16 *buf_ptr;
+       sljit_u16 *buf_end;
        sljit_uw half_count;
+       sljit_sw executable_offset;
 
        struct sljit_label *label;
        struct sljit_jump *jump;
@@ -356,18 +362,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        CHECK_PTR(check_sljit_generate_code(compiler));
        reverse_buf(compiler);
 
-       code = (sljit_uh*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_uh));
+       code = (sljit_u16*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_u16));
        PTR_FAIL_WITH_EXEC_IF(code);
        buf = compiler->buf;
 
        code_ptr = code;
        half_count = 0;
+       executable_offset = SLJIT_EXEC_OFFSET(code);
+
        label = compiler->labels;
        jump = compiler->jumps;
        const_ = compiler->consts;
 
        do {
-               buf_ptr = (sljit_uh*)buf->memory;
+               buf_ptr = (sljit_u16*)buf->memory;
                buf_end = buf_ptr + (buf->used_size >> 1);
                do {
                        *code_ptr = *buf_ptr++;
@@ -376,13 +384,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                        SLJIT_ASSERT(!jump || jump->addr >= half_count);
                        SLJIT_ASSERT(!const_ || const_->addr >= half_count);
                        if (label && label->size == half_count) {
-                               label->addr = ((sljit_uw)code_ptr) | 0x1;
+                               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);
+                                       code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
                                        jump = jump->next;
                        }
                        if (const_ && const_->addr == half_count) {
@@ -397,7 +405,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        } while (buf);
 
        if (label && label->size == half_count) {
-               label->addr = ((sljit_uw)code_ptr) | 0x1;
+               label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
                label->size = code_ptr - code;
                label = label->next;
        }
@@ -409,17 +417,43 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
        jump = compiler->jumps;
        while (jump) {
-               set_jump_instruction(jump);
+               set_jump_instruction(jump, executable_offset);
                jump = jump->next;
        }
 
        compiler->error = SLJIT_ERR_COMPILED;
-       compiler->executable_size = (code_ptr - code) * sizeof(sljit_uh);
+       compiler->executable_offset = executable_offset;
+       compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16);
+
+       code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+       code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
        SLJIT_CACHE_FLUSH(code, code_ptr);
        /* Set thumb mode flag. */
        return (void*)((sljit_uw)code | 0x1);
 }
 
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+       switch (feature_type) {
+       case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+               return SLJIT_IS_FPU_AVAILABLE;
+#else
+               /* Available by default. */
+               return 1;
+#endif
+
+       case SLJIT_HAS_PRE_UPDATE:
+       case SLJIT_HAS_CLZ:
+       case SLJIT_HAS_CMOV:
+               return 1;
+
+       default:
+               return 0;
+       }
+}
+
 /* --------------------------------------------------------------------- */
 /*  Core code generator functions.                                       */
 /* --------------------------------------------------------------------- */
@@ -428,7 +462,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 static sljit_uw get_imm(sljit_uw imm)
 {
        /* Thumb immediate form. */
-       sljit_si counter;
+       sljit_s32 counter;
 
        if (imm <= 0xff)
                return imm;
@@ -474,7 +508,7 @@ static sljit_uw get_imm(sljit_uw imm)
        return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1);
 }
 
-static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_uw imm)
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)
 {
        sljit_uw tmp;
 
@@ -500,24 +534,20 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sl
 
 #define ARG1_IMM       0x0010000
 #define ARG2_IMM       0x0020000
-#define KEEP_FLAGS     0x0040000
 /* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */
 #define SET_FLAGS      0x0100000
 #define UNUSED_RETURN  0x0200000
-#define SLOW_DEST      0x0400000
-#define SLOW_SRC1      0x0800000
-#define SLOW_SRC2      0x1000000
 
-static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, sljit_si dst, sljit_uw arg1, sljit_uw arg2)
+static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_uw arg1, sljit_uw arg2)
 {
        /* dst must be register, TMP_REG1
-          arg1 must be register, TMP_REG1, imm
-          arg2 must be register, TMP_REG2, imm */
-       sljit_si reg;
+          arg1 must be register, imm
+          arg2 must be register, imm */
+       sljit_s32 reg;
        sljit_uw imm, nimm;
 
        if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
-               /* Both are immediates. */
+               /* Both are immediates, no temporaries are used. */
                flags &= ~ARG1_IMM;
                FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
                arg1 = TMP_REG1;
@@ -533,7 +563,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                        /* No form with immediate operand. */
                        break;
                case SLJIT_MOV:
-                       SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);
+                       SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG2);
                        return load_immediate(compiler, dst, imm);
                case SLJIT_NOT:
                        if (!(flags & SET_FLAGS))
@@ -543,7 +573,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                        break;
                case SLJIT_ADD:
                        nimm = -imm;
-                       if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
+                       if (IS_2_LO_REGS(reg, dst)) {
                                if (imm <= 0x7)
                                        return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
                                if (nimm <= 0x7)
@@ -561,9 +591,12 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                                if (nimm <= 0xfff)
                                        return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm));
                        }
-                       imm = get_imm(imm);
-                       if (imm != INVALID_IMM)
-                               return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       nimm = get_imm(imm);
+                       if (nimm != INVALID_IMM)
+                               return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
+                       nimm = get_imm(-imm);
+                       if (nimm != INVALID_IMM)
+                               return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
                        break;
                case SLJIT_ADDC:
                        imm = get_imm(imm);
@@ -571,16 +604,27 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                                return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
                        break;
                case SLJIT_SUB:
+                       /* SUB operation can be replaced by ADD because of the negative carry flag. */
                        if (flags & ARG1_IMM) {
-                               if (!(flags & KEEP_FLAGS) && imm == 0 && IS_2_LO_REGS(reg, dst))
+                               if (imm == 0 && IS_2_LO_REGS(reg, dst))
                                        return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
                                imm = get_imm(imm);
                                if (imm != INVALID_IMM)
                                        return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
                                break;
                        }
+                       if (flags & UNUSED_RETURN) {
+                               if (imm <= 0xff && reg_map[reg] <= 7)
+                                       return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
+                               nimm = get_imm(imm);
+                               if (nimm != INVALID_IMM)
+                                       return push_inst32(compiler, CMPI_W | RN4(reg) | nimm);
+                               nimm = get_imm(-imm);
+                               if (nimm != INVALID_IMM)
+                                       return push_inst32(compiler, CMNI_W | RN4(reg) | nimm);
+                       }
                        nimm = -imm;
-                       if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
+                       if (IS_2_LO_REGS(reg, dst)) {
                                if (imm <= 0x7)
                                        return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
                                if (nimm <= 0x7)
@@ -591,8 +635,6 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                                        if (nimm <= 0xff)
                                                return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst));
                                }
-                               if (imm <= 0xff && (flags & UNUSED_RETURN))
-                                       return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
                        }
                        if (!(flags & SET_FLAGS)) {
                                if (imm <= 0xfff)
@@ -600,9 +642,12 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                                if (nimm <= 0xfff)
                                        return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm));
                        }
-                       imm = get_imm(imm);
-                       if (imm != INVALID_IMM)
-                               return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       nimm = get_imm(imm);
+                       if (nimm != INVALID_IMM)
+                               return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
+                       nimm = get_imm(-imm);
+                       if (nimm != INVALID_IMM)
+                               return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
                        break;
                case SLJIT_SUBC:
                        if (flags & ARG1_IMM)
@@ -647,141 +692,143 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
                        }
                        switch (flags & 0xffff) {
                        case SLJIT_SHL:
-                               if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
+                               if (IS_2_LO_REGS(dst, reg))
                                        return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6));
                                return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
                        case SLJIT_LSHR:
-                               if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
+                               if (IS_2_LO_REGS(dst, reg))
                                        return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6));
                                return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
                        default: /* SLJIT_ASHR */
-                               if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
+                               if (IS_2_LO_REGS(dst, reg))
                                        return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6));
                                return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
                        }
                default:
-                       SLJIT_ASSERT_STOP();
+                       SLJIT_UNREACHABLE();
                        break;
                }
 
                if (flags & ARG2_IMM) {
-                       FAIL_IF(load_immediate(compiler, TMP_REG2, arg2));
-                       arg2 = TMP_REG2;
+                       imm = arg2;
+                       arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+                       FAIL_IF(load_immediate(compiler, arg2, imm));
                }
                else {
-                       FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
-                       arg1 = TMP_REG1;
+                       imm = arg1;
+                       arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+                       FAIL_IF(load_immediate(compiler, arg1, imm));
                }
+
+               SLJIT_ASSERT(arg1 != arg2);
        }
 
        /* Both arguments are registers. */
        switch (flags & 0xffff) {
        case SLJIT_MOV:
-       case SLJIT_MOV_UI:
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOV_S32:
        case SLJIT_MOV_P:
        case SLJIT_MOVU:
-       case SLJIT_MOVU_UI:
-       case SLJIT_MOVU_SI:
+       case SLJIT_MOVU_U32:
+       case SLJIT_MOVU_S32:
        case SLJIT_MOVU_P:
-               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
                if (dst == arg2)
                        return SLJIT_SUCCESS;
                return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
-       case SLJIT_MOV_UB:
-       case SLJIT_MOVU_UB:
-               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+       case SLJIT_MOV_U8:
+       case SLJIT_MOVU_U8:
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
                if (IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2));
-       case SLJIT_MOV_SB:
-       case SLJIT_MOVU_SB:
-               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+       case SLJIT_MOV_S8:
+       case SLJIT_MOVU_S8:
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
                if (IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2));
-       case SLJIT_MOV_UH:
-       case SLJIT_MOVU_UH:
-               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+       case SLJIT_MOV_U16:
+       case SLJIT_MOVU_U16:
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
                if (IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2));
-       case SLJIT_MOV_SH:
-       case SLJIT_MOVU_SH:
-               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+       case SLJIT_MOV_S16:
+       case SLJIT_MOVU_S16:
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
                if (IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, SXTH_W | RD4(dst) | RM4(arg2));
        case SLJIT_NOT:
-               SLJIT_ASSERT(arg1 == TMP_REG1);
-               if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+               SLJIT_ASSERT(arg1 == TMP_REG2);
+               if (IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, MVNS | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(arg2));
        case SLJIT_CLZ:
-               SLJIT_ASSERT(arg1 == TMP_REG1);
+               SLJIT_ASSERT(arg1 == TMP_REG2);
                FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)));
-               if (flags & SET_FLAGS) {
-                       if (reg_map[dst] <= 7)
-                               return push_inst16(compiler, CMPI | RDN3(dst));
-                       return push_inst32(compiler, ADD_WI | SET_FLAGS | RN4(dst) | RD4(dst));
-               }
                return SLJIT_SUCCESS;
        case SLJIT_ADD:
-               if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2))
+               if (IS_3_LO_REGS(dst, arg1, arg2))
                        return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2));
                if (dst == arg1 && !(flags & SET_FLAGS))
                        return push_inst16(compiler, ADD | SET_REGS44(dst, arg2));
                return push_inst32(compiler, ADD_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        case SLJIT_ADDC:
-               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+               if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        case SLJIT_SUB:
-               if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2))
+               if (flags & UNUSED_RETURN) {
+                       if (IS_2_LO_REGS(arg1, arg2))
+                               return push_inst16(compiler, CMP | RD3(arg1) | RN3(arg2));
+                       return push_inst16(compiler, CMP_X | SET_REGS44(arg1, arg2));
+               }
+               if (IS_3_LO_REGS(dst, arg1, arg2))
                        return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2));
                return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        case SLJIT_SUBC:
-               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+               if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        case SLJIT_MUL:
                if (!(flags & SET_FLAGS))
                        return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2));
-               SLJIT_ASSERT(reg_map[TMP_REG2] <= 7 && dst != TMP_REG2);
+               SLJIT_ASSERT(dst != TMP_REG2);
                FAIL_IF(push_inst32(compiler, SMULL | RT4(dst) | RD4(TMP_REG2) | RN4(arg1) | RM4(arg2)));
                /* cmp TMP_REG2, dst asr #31. */
                return push_inst32(compiler, CMP_W | RN4(TMP_REG2) | 0x70e0 | RM4(dst));
        case SLJIT_AND:
-               if (!(flags & KEEP_FLAGS)) {
-                       if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
-                               return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2));
-                       if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2))
-                               return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2));
-               }
+               if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2));
+               if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2))
+                       return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2));
                return push_inst32(compiler, AND_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        case SLJIT_OR:
-               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+               if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, ORRS | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, ORR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        case SLJIT_XOR:
-               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+               if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        case SLJIT_SHL:
-               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+               if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        case SLJIT_LSHR:
-               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+               if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        case SLJIT_ASHR:
-               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+               if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
                        return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2));
                return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
        }
 
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_SUCCESS;
 }
 
@@ -791,9 +838,9 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
 #define WORD_SIZE      0x00
 #define BYTE_SIZE      0x04
 #define HALF_SIZE      0x08
+#define PRELOAD                0x0c
 
 #define UPDATE         0x10
-#define ARG_TEST       0x20
 
 #define IS_WORD_SIZE(flags)            (!(flags & (BYTE_SIZE | HALF_SIZE)))
 #define OFFSET_CHECK(imm, shift)       (!(argw & ~(imm << shift)))
@@ -813,7 +860,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
   s = store
 */
 
-static SLJIT_CONST sljit_ins sljit_mem16[12] = {
+static const sljit_ins sljit_mem16[12] = {
 /* w u l */ 0x5800 /* ldr */,
 /* w u s */ 0x5000 /* str */,
 /* w s l */ 0x5800 /* ldr */,
@@ -830,7 +877,7 @@ static SLJIT_CONST sljit_ins sljit_mem16[12] = {
 /* h s s */ 0x5200 /* strh */,
 };
 
-static SLJIT_CONST sljit_ins sljit_mem16_imm5[12] = {
+static const sljit_ins sljit_mem16_imm5[12] = {
 /* w u l */ 0x6800 /* ldr imm5 */,
 /* w u s */ 0x6000 /* str imm5 */,
 /* w s l */ 0x6800 /* ldr imm5 */,
@@ -849,7 +896,7 @@ static SLJIT_CONST sljit_ins sljit_mem16_imm5[12] = {
 
 #define MEM_IMM8       0xc00
 #define MEM_IMM12      0x800000
-static SLJIT_CONST sljit_ins sljit_mem32[12] = {
+static const sljit_ins sljit_mem32[13] = {
 /* w u l */ 0xf8500000 /* ldr.w */,
 /* w u s */ 0xf8400000 /* str.w */,
 /* w s l */ 0xf8500000 /* ldr.w */,
@@ -864,10 +911,12 @@ static SLJIT_CONST sljit_ins sljit_mem32[12] = {
 /* h u s */ 0xf8200000 /* strsh.w */,
 /* h s l */ 0xf9300000 /* ldrsh.w */,
 /* h s s */ 0xf8200000 /* strsh.w */,
+
+/* p u l */ 0xf8100000 /* pld */,
 };
 
 /* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
-static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sljit_si reg, sljit_sw value)
+static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value)
 {
        if (value >= 0) {
                if (value <= 0xfff)
@@ -887,20 +936,67 @@ static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sl
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-/* Can perform an operation using at most 1 instruction. */
-static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
+       sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
 {
-       sljit_si other_r, shift;
+       sljit_s32 other_r;
+       sljit_s32 update = flags & UPDATE;
+       sljit_uw tmp;
 
        SLJIT_ASSERT(arg & SLJIT_MEM);
+       SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
+       flags &= ~UPDATE;
+       arg &= ~SLJIT_MEM;
+
+       if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
+               tmp = get_imm(argw & ~0xfff);
+               if (tmp != INVALID_IMM) {
+                       FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | tmp));
+                       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg) | (argw & 0xfff));
+               }
+
+               FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+               if (IS_2_LO_REGS(reg, tmp_reg) && sljit_mem16_imm5[flags])
+                       return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(tmp_reg));
+               return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg));
+       }
 
-       if (SLJIT_UNLIKELY(flags & UPDATE)) {
-               if ((arg & REG_MASK) && !(arg & OFFS_REG_MASK) && argw <= 0xff && argw >= -0xff) {
-                       if (SLJIT_UNLIKELY(flags & ARG_TEST))
-                               return 1;
+       if (SLJIT_UNLIKELY(update)) {
+               SLJIT_ASSERT(reg != arg);
 
-                       flags &= ~UPDATE;
+               if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+                       other_r = OFFS_REG(arg);
                        arg &= 0xf;
+
+                       if (IS_3_LO_REGS(reg, arg, other_r))
+                               FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
+                       else
+                               FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r)));
+                       return push_inst16(compiler, ADD | SET_REGS44(arg, other_r));
+               }
+
+               if (argw > 0xff) {
+                       tmp = get_imm(argw & ~0xff);
+                       if (tmp != INVALID_IMM) {
+                               push_inst32(compiler, ADD_WI | RD4(arg) | RN4(arg) | tmp);
+                               argw = argw & 0xff;
+                       }
+               }
+               else if (argw < -0xff) {
+                       tmp = get_imm(-argw & ~0xff);
+                       if (tmp != INVALID_IMM) {
+                               push_inst32(compiler, SUB_WI | RD4(arg) | RN4(arg) | tmp);
+                               argw = -(-argw & 0xff);
+                       }
+               }
+
+               if (argw == 0) {
+                       if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags])
+                               return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg));
+                       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg));
+               }
+
+               if (argw <= 0xff && argw >= -0xff) {
                        if (argw >= 0)
                                argw |= 0x200;
                        else {
@@ -908,238 +1004,100 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
                        }
 
                        SLJIT_ASSERT(argw >= 0 && (argw & 0xff) <= 0xff);
-                       FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw));
-                       return -1;
+                       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw);
                }
-               return 0;
+
+               FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+
+               SLJIT_ASSERT(reg != tmp_reg);
+
+               if (IS_3_LO_REGS(reg, arg, tmp_reg))
+                       FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg)));
+               else
+                       FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg)));
+               return push_inst16(compiler, ADD | SET_REGS44(arg, tmp_reg));
        }
 
        if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
-               if (SLJIT_UNLIKELY(flags & ARG_TEST))
-                       return 1;
-
                argw &= 0x3;
                other_r = OFFS_REG(arg);
                arg &= 0xf;
 
                if (!argw && IS_3_LO_REGS(reg, arg, other_r))
-                       FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
-               else
-                       FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)));
-               return -1;
+                       return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r));
+               return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4));
        }
 
-       if (!(arg & REG_MASK) || argw > 0xfff || argw < -0xff)
-               return 0;
-
-       if (SLJIT_UNLIKELY(flags & ARG_TEST))
-               return 1;
+       if (argw > 0xfff) {
+               tmp = get_imm(argw & ~0xfff);
+               if (tmp != INVALID_IMM) {
+                       push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp);
+                       arg = tmp_reg;
+                       argw = argw & 0xfff;
+               }
+       }
+       else if (argw < -0xff) {
+               tmp = get_imm(-argw & ~0xff);
+               if (tmp != INVALID_IMM) {
+                       push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp);
+                       arg = tmp_reg;
+                       argw = -(-argw & 0xff);
+               }
+       }
 
-       arg &= 0xf;
        if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {
-               shift = 3;
+               tmp = 3;
                if (IS_WORD_SIZE(flags)) {
                        if (OFFSET_CHECK(0x1f, 2))
-                               shift = 2;
+                               tmp = 2;
                }
                else if (flags & BYTE_SIZE)
                {
                        if (OFFSET_CHECK(0x1f, 0))
-                               shift = 0;
+                               tmp = 0;
                }
                else {
                        SLJIT_ASSERT(flags & HALF_SIZE);
                        if (OFFSET_CHECK(0x1f, 1))
-                               shift = 1;
-               }
-
-               if (shift != 3) {
-                       FAIL_IF(push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - shift))));
-                       return -1;
-               }
-       }
-
-       /* SP based immediate. */
-       if (SLJIT_UNLIKELY(arg == SLJIT_SP) && OFFSET_CHECK(0xff, 2) && IS_WORD_SIZE(flags) && reg_map[reg] <= 7) {
-               FAIL_IF(push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2)));
-               return -1;
-       }
-
-       if (argw >= 0)
-               FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
-       else
-               FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw));
-       return -1;
-}
-
-/* see getput_arg below.
-   Note: can_cache is called only for binary operators. Those
-   operators always uses word arguments without write back. */
-static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
-{
-       sljit_sw diff;
-       if ((arg & OFFS_REG_MASK) || !(next_arg & SLJIT_MEM))
-               return 0;
-
-       if (!(arg & REG_MASK)) {
-               diff = argw - next_argw;
-               if (diff <= 0xfff && diff >= -0xfff)
-                       return 1;
-               return 0;
-       }
-
-       if (argw == next_argw)
-               return 1;
-
-       diff = argw - next_argw;
-       if (arg == next_arg && diff <= 0xfff && diff >= -0xfff)
-               return 1;
-
-       return 0;
-}
-
-/* Emit the necessary instructions. See can_cache above. */
-static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg,
-       sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
-{
-       sljit_si tmp_r, other_r;
-       sljit_sw diff;
-
-       SLJIT_ASSERT(arg & SLJIT_MEM);
-       if (!(next_arg & SLJIT_MEM)) {
-               next_arg = 0;
-               next_argw = 0;
-       }
-
-       tmp_r = (flags & STORE) ? TMP_REG3 : reg;
-
-       if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) {
-               /* Update only applies if a base register exists. */
-               /* There is no caching here. */
-               other_r = OFFS_REG(arg);
-               arg &= 0xf;
-               flags &= ~UPDATE;
-
-               if (!other_r) {
-                       if (!(argw & ~0xfff)) {
-                               FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
-                               return push_inst32(compiler, ADDWI | RD4(arg) | RN4(arg) | IMM12(argw));
-                       }
-
-                       if (compiler->cache_arg == SLJIT_MEM) {
-                               if (argw == compiler->cache_argw) {
-                                       other_r = TMP_REG3;
-                                       argw = 0;
-                               }
-                               else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
-                                       FAIL_IF(compiler->error);
-                                       compiler->cache_argw = argw;
-                                       other_r = TMP_REG3;
-                                       argw = 0;
-                               }
-                       }
-
-                       if (argw) {
-                               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
-                               compiler->cache_arg = SLJIT_MEM;
-                               compiler->cache_argw = argw;
-                               other_r = TMP_REG3;
-                               argw = 0;
-                       }
-               }
-
-               argw &= 0x3;
-               if (!argw && IS_3_LO_REGS(reg, arg, other_r)) {
-                       FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
-                       return push_inst16(compiler, ADD | SET_REGS44(arg, other_r));
-               }
-               FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)));
-               return push_inst32(compiler, ADD_W | RD4(arg) | RN4(arg) | RM4(other_r) | (argw << 6));
-       }
-       flags &= ~UPDATE;
-
-       SLJIT_ASSERT(!(arg & OFFS_REG_MASK));
-
-       if (compiler->cache_arg == arg) {
-               diff = argw - compiler->cache_argw;
-               if (!(diff & ~0xfff))
-                       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | diff);
-               if (!((compiler->cache_argw - argw) & ~0xff))
-                       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(TMP_REG3) | (compiler->cache_argw - argw));
-               if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, diff) != SLJIT_ERR_UNSUPPORTED) {
-                       FAIL_IF(compiler->error);
-                       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0);
-               }
-       }
-
-       next_arg = (arg & REG_MASK) && (arg == next_arg) && (argw != next_argw);
-       arg &= 0xf;
-       if (arg && compiler->cache_arg == SLJIT_MEM) {
-               if (compiler->cache_argw == argw)
-                       return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
-               if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
-                       FAIL_IF(compiler->error);
-                       compiler->cache_argw = argw;
-                       return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
+                               tmp = 1;
                }
-       }
 
-       compiler->cache_argw = argw;
-       if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) {
-               FAIL_IF(compiler->error);
-               compiler->cache_arg = SLJIT_MEM | arg;
-               arg = 0;
+               if (tmp < 3)
+                       return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp)));
        }
-       else {
-               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
-               compiler->cache_arg = SLJIT_MEM;
-
-               diff = argw - next_argw;
-               if (next_arg && diff <= 0xfff && diff >= -0xfff) {
-                       FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, arg)));
-                       compiler->cache_arg = SLJIT_MEM | arg;
-                       arg = 0;
-               }
+       else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && OFFSET_CHECK(0xff, 2) && reg_map[reg] <= 7) {
+               /* SP based immediate. */
+               return push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2));
        }
 
-       if (arg)
-               return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
-       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0);
-}
+       if (argw >= 0 && argw <= 0xfff)
+               return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw);
+       else if (argw < 0 && argw >= -0xff)
+               return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw);
 
-static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
-{
-       if (getput_arg_fast(compiler, flags, reg, arg, argw))
-               return compiler->error;
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
-}
+       SLJIT_ASSERT(arg != tmp_reg);
 
-static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
-{
-       if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
-               return compiler->error;
-       return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+       FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+       if (IS_3_LO_REGS(reg, arg, tmp_reg))
+               return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg));
+       return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg));
 }
 
 /* --------------------------------------------------------------------- */
 /*  Entry, exit                                                          */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
-       sljit_si size, i, tmp;
-       sljit_ins push;
+       sljit_s32 size, i, tmp;
+       sljit_ins push = 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
        set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
 
-       push = (1 << 4);
-
        tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
        for (i = SLJIT_S0; i >= tmp; i--)
                push |= 1 << reg_map[i];
@@ -1152,7 +1110,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
                : push_inst16(compiler, PUSH | (1 << 8) | push));
 
        /* Stack must be aligned to 8 bytes: (LR, R4) */
-       size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
+       size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
        local_size = ((size + local_size + 7) & ~7) - size;
        compiler->local_size = local_size;
        if (local_size > 0) {
@@ -1172,25 +1130,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
-       sljit_si size;
+       sljit_s32 size;
 
        CHECK_ERROR();
        CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
        set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
 
-       size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
+       size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
        compiler->local_size = ((size + local_size + 7) & ~7) - size;
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si i, tmp;
-       sljit_ins pop;
+       sljit_s32 i, tmp;
+       sljit_ins pop = 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_return(compiler, op, src, srcw));
@@ -1204,8 +1162,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
                        FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_SP, SLJIT_SP, compiler->local_size));
        }
 
-       pop = (1 << 4);
-
        tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
        for (i = SLJIT_S0; i >= tmp; i--)
                pop |= 1 << reg_map[i];
@@ -1237,7 +1193,7 @@ extern int __aeabi_idivmod(int numerator, int denominator);
 }
 #endif
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
 {
        sljit_sw saved_reg_list[3];
        sljit_sw saved_reg_count;
@@ -1251,26 +1207,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
                return push_inst16(compiler, BKPT);
        case SLJIT_NOP:
                return push_inst16(compiler, NOP);
-       case SLJIT_LUMUL:
-       case SLJIT_LSMUL:
-               return push_inst32(compiler, (op == SLJIT_LUMUL ? UMULL : SMULL)
+       case SLJIT_LMUL_UW:
+       case SLJIT_LMUL_SW:
+               return push_inst32(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
                        | (reg_map[SLJIT_R1] << 8)
                        | (reg_map[SLJIT_R0] << 12)
                        | (reg_map[SLJIT_R0] << 16)
                        | reg_map[SLJIT_R1]);
-       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);
+       case SLJIT_DIVMOD_UW:
+       case SLJIT_DIVMOD_SW:
+       case SLJIT_DIV_UW:
+       case SLJIT_DIV_SW:
+               SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
+               SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12);
 
                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)
+               if (op >= SLJIT_DIV_UW)
                        saved_reg_list[saved_reg_count++] = 1;
 
                if (saved_reg_count > 0) {
@@ -1288,7 +1244,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
 
 #if defined(__GNUC__)
                FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
-                       ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+                       ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
 #else
 #error "Software divmod functions are needed"
 #endif
@@ -1311,20 +1267,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r, flags;
-       sljit_si op_flags = GET_ALL_FLAGS(op);
+       sljit_s32 dst_r, flags;
+       sljit_s32 op_flags = GET_ALL_FLAGS(op);
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
        ADJUST_LOCAL_OFFSET(src, srcw);
 
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+               /* Since TMP_PC has index 15, IS_2_LO_REGS and IS_3_LO_REGS checks always fail. */
+               if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+                       return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1);
+               return SLJIT_SUCCESS;
+       }
 
        dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
 
@@ -1332,83 +1292,77 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
                switch (op) {
                case SLJIT_MOV:
-               case SLJIT_MOV_UI:
-               case SLJIT_MOV_SI:
+               case SLJIT_MOV_U32:
+               case SLJIT_MOV_S32:
                case SLJIT_MOV_P:
                        flags = WORD_SIZE;
                        break;
-               case SLJIT_MOV_UB:
+               case SLJIT_MOV_U8:
                        flags = BYTE_SIZE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_ub)srcw;
+                               srcw = (sljit_u8)srcw;
                        break;
-               case SLJIT_MOV_SB:
+               case SLJIT_MOV_S8:
                        flags = BYTE_SIZE | SIGNED;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_sb)srcw;
+                               srcw = (sljit_s8)srcw;
                        break;
-               case SLJIT_MOV_UH:
+               case SLJIT_MOV_U16:
                        flags = HALF_SIZE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_uh)srcw;
+                               srcw = (sljit_u16)srcw;
                        break;
-               case SLJIT_MOV_SH:
+               case SLJIT_MOV_S16:
                        flags = HALF_SIZE | SIGNED;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_sh)srcw;
+                               srcw = (sljit_s16)srcw;
                        break;
                case SLJIT_MOVU:
-               case SLJIT_MOVU_UI:
-               case SLJIT_MOVU_SI:
+               case SLJIT_MOVU_U32:
+               case SLJIT_MOVU_S32:
                case SLJIT_MOVU_P:
                        flags = WORD_SIZE | UPDATE;
                        break;
-               case SLJIT_MOVU_UB:
+               case SLJIT_MOVU_U8:
                        flags = BYTE_SIZE | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_ub)srcw;
+                               srcw = (sljit_u8)srcw;
                        break;
-               case SLJIT_MOVU_SB:
+               case SLJIT_MOVU_S8:
                        flags = BYTE_SIZE | SIGNED | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_sb)srcw;
+                               srcw = (sljit_s8)srcw;
                        break;
-               case SLJIT_MOVU_UH:
+               case SLJIT_MOVU_U16:
                        flags = HALF_SIZE | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_uh)srcw;
+                               srcw = (sljit_u16)srcw;
                        break;
-               case SLJIT_MOVU_SH:
+               case SLJIT_MOVU_S16:
                        flags = HALF_SIZE | SIGNED | UPDATE;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_sh)srcw;
+                               srcw = (sljit_s16)srcw;
                        break;
                default:
-                       SLJIT_ASSERT_STOP();
+                       SLJIT_UNREACHABLE();
                        flags = 0;
                        break;
                }
 
                if (src & SLJIT_IMM)
-                       FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw));
+                       FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, srcw));
                else if (src & SLJIT_MEM) {
-                       if (getput_arg_fast(compiler, flags, dst_r, src, srcw))
-                               FAIL_IF(compiler->error);
-                       else
-                               FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw));
+                       FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, ((flags & UPDATE) && dst_r == TMP_REG1) ? TMP_REG2 : TMP_REG1));
                } else {
                        if (dst_r != TMP_REG1)
-                               return emit_op_imm(compiler, op, dst_r, TMP_REG1, src);
+                               return emit_op_imm(compiler, op, dst_r, TMP_REG2, src);
                        dst_r = src;
                }
 
-               if (dst & SLJIT_MEM) {
-                       if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw))
-                               return compiler->error;
-                       else
-                               return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0);
-               }
-               return SLJIT_SUCCESS;
+               if (!(dst & SLJIT_MEM))
+                       return SLJIT_SUCCESS;
+
+               return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, (dst_r == TMP_REG1) ? TMP_REG2 : TMP_REG1);
        }
 
        if (op == SLJIT_NEG) {
@@ -1419,37 +1373,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
                return sljit_emit_op2(compiler, SLJIT_SUB | op_flags, dst, dstw, SLJIT_IMM, 0, src, srcw);
        }
 
-       flags = (GET_FLAGS(op_flags) ? SET_FLAGS : 0) | ((op_flags & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
-       if (src & SLJIT_MEM) {
-               if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src, srcw))
-                       FAIL_IF(compiler->error);
-               else
-                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw));
-               src = TMP_REG2;
-       }
+       flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;
 
        if (src & SLJIT_IMM)
                flags |= ARG2_IMM;
+       else if (src & SLJIT_MEM) {
+               FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
+               srcw = TMP_REG1;
+       }
        else
                srcw = src;
 
-       emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, srcw);
+       emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, srcw);
 
-       if (dst & SLJIT_MEM) {
-               if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw))
-                       return compiler->error;
-               else
-                       return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0);
-       }
-       return SLJIT_SUCCESS;
+       if (!(dst & SLJIT_MEM))
+               return SLJIT_SUCCESS;
+       return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si dst_r, flags;
+       sljit_s32 dst_reg, flags, src2_reg;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1457,92 +1404,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        ADJUST_LOCAL_OFFSET(src1, src1w);
        ADJUST_LOCAL_OFFSET(src2, src2w);
 
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-
-       dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
-       flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
-
-       if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw))
-               flags |= SLOW_DEST;
-
-       if (src1 & SLJIT_MEM) {
-               if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG1, src1, src1w))
-                       FAIL_IF(compiler->error);
-               else
-                       flags |= SLOW_SRC1;
-       }
-       if (src2 & SLJIT_MEM) {
-               if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src2, src2w))
-                       FAIL_IF(compiler->error);
-               else
-                       flags |= SLOW_SRC2;
-       }
-
-       if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
-               if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
-                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, src1, src1w));
-                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw));
-               }
-               else {
-                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, src2, src2w));
-                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw));
-               }
-       }
-       else if (flags & SLOW_SRC1)
-               FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw));
-       else if (flags & SLOW_SRC2)
-               FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw));
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+               return SLJIT_SUCCESS;
 
-       if (src1 & SLJIT_MEM)
-               src1 = TMP_REG1;
-       if (src2 & SLJIT_MEM)
-               src2 = TMP_REG2;
+       dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+       flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
 
        if (src1 & SLJIT_IMM)
                flags |= ARG1_IMM;
+       else if (src1 & SLJIT_MEM) {
+               emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1);
+               src1w = TMP_REG1;
+       }
        else
                src1w = src1;
+
        if (src2 & SLJIT_IMM)
                flags |= ARG2_IMM;
+       else if (src2 & SLJIT_MEM) {
+               src2_reg = (!(flags & ARG1_IMM) && (src1w == TMP_REG1)) ? TMP_REG2 : TMP_REG1;
+               emit_op_mem(compiler, WORD_SIZE, src2_reg, src2, src2w, src2_reg);
+               src2w = src2_reg;
+       }
        else
                src2w = src2;
 
        if (dst == SLJIT_UNUSED)
                flags |= UNUSED_RETURN;
 
-       emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);
+       emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, src1w, src2w);
 
-       if (dst & SLJIT_MEM) {
-               if (!(flags & SLOW_DEST)) {
-                       getput_arg_fast(compiler, WORD_SIZE | STORE, dst_r, dst, dstw);
-                       return compiler->error;
-               }
-               return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, 0, 0);
-       }
-       return SLJIT_SUCCESS;
+       if (!(dst & SLJIT_MEM))
+               return SLJIT_SUCCESS;
+       return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG2);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_register_index(reg));
        return reg_map[reg];
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
        return reg << 1;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
 
        if (size == 2)
-               return push_inst16(compiler, *(sljit_uh*)instruction);
+               return push_inst16(compiler, *(sljit_u16*)instruction);
        return push_inst32(compiler, *(sljit_ins*)instruction);
 }
 
@@ -1550,30 +1466,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
 /*  Floating point operators                                             */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
-       return SLJIT_IS_FPU_AVAILABLE;
-#else
-       /* Available by default. */
-       return 1;
-#endif
-}
-
 #define FPU_LOAD (1 << 20)
 
-static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
 {
-       sljit_sw tmp;
        sljit_uw imm;
-       sljit_sw inst = VSTR_F32 | (flags & (SLJIT_SINGLE_OP | FPU_LOAD));
+       sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD));
 
        SLJIT_ASSERT(arg & SLJIT_MEM);
 
        /* Fast loads and stores. */
        if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
-               FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG2) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6)));
-               arg = SLJIT_MEM | TMP_REG2;
+               FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6)));
+               arg = SLJIT_MEM | TMP_REG1;
                argw = 0;
        }
 
@@ -1584,21 +1489,6 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
                        return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | (-argw >> 2));
        }
 
-       /* Slow cases */
-       SLJIT_ASSERT(!(arg & OFFS_REG_MASK));
-       if (compiler->cache_arg == arg) {
-               tmp = argw - compiler->cache_argw;
-               if (!(tmp & ~0x3fc))
-                       return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg) | (tmp >> 2));
-               if (!(-tmp & ~0x3fc))
-                       return push_inst32(compiler, inst | RN4(TMP_REG3) | DD4(reg) | (-tmp >> 2));
-               if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) {
-                       FAIL_IF(compiler->error);
-                       compiler->cache_argw = argw;
-                       return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
-               }
-       }
-
        if (arg & REG_MASK) {
                if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {
                        FAIL_IF(compiler->error);
@@ -1617,28 +1507,24 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
                }
        }
 
-       compiler->cache_arg = arg;
-       compiler->cache_argw = argw;
-
-       FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+       FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
        if (arg & REG_MASK)
-               FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, (arg & REG_MASK))));
-       return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
+               FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, (arg & REG_MASK))));
+       return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
+       op ^= SLJIT_F32_OP;
+
        if (src & SLJIT_MEM) {
-               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
+               FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
                src = TMP_FREG1;
        }
 
-       FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_SINGLE_OP) | DD4(TMP_FREG1) | DM4(src)));
-
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
+       FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_F32_OP) | DD4(TMP_FREG1) | DM4(src)));
 
        if (FAST_IS_REG(dst))
                return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1));
@@ -1647,11 +1533,13 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
        return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+       op ^= SLJIT_F32_OP;
 
        if (FAST_IS_REG(src))
                FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1)));
@@ -1664,85 +1552,86 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
                FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | DN4(TMP_FREG1)));
        }
 
-       FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(TMP_FREG1)));
+       FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(TMP_FREG1)));
 
        if (dst & SLJIT_MEM)
-               return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
+               return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw);
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
+       op ^= SLJIT_F32_OP;
+
        if (src1 & SLJIT_MEM) {
-               emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
+               emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
                src1 = TMP_FREG1;
        }
 
        if (src2 & SLJIT_MEM) {
-               emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);
+               emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);
                src2 = TMP_FREG2;
        }
 
-       FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_SINGLE_OP) | DD4(src1) | DM4(src2)));
+       FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_F32_OP) | DD4(src1) | DM4(src2)));
        return push_inst32(compiler, VMRS);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR();
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       if (GET_OPCODE(op) != SLJIT_CONVD_FROMS)
-               op ^= SLJIT_SINGLE_OP;
 
-       SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100), float_transfer_bit_error);
+       SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error);
        SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
 
        dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
 
+       if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
+               op ^= SLJIT_F32_OP;
+
        if (src & SLJIT_MEM) {
-               emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_r, src, srcw);
+               emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw);
                src = dst_r;
        }
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DMOV:
+       case SLJIT_MOV_F64:
                if (src != dst_r) {
                        if (dst_r != TMP_FREG1)
-                               FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
+                               FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));
                        else
                                dst_r = src;
                }
                break;
-       case SLJIT_DNEG:
-               FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
+       case SLJIT_NEG_F64:
+               FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));
                break;
-       case SLJIT_DABS:
-               FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
+       case SLJIT_ABS_F64:
+               FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));
                break;
-       case SLJIT_CONVD_FROMS:
-               FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DM4(src)));
-               op ^= SLJIT_SINGLE_OP;
+       case SLJIT_CONV_F64_FROM_F32:
+               FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));
+               op ^= SLJIT_F32_OP;
                break;
        }
 
        if (dst & SLJIT_MEM)
-               return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), dst_r, dst, dstw);
+               return emit_fop_mem(compiler, (op & SLJIT_F32_OP), dst_r, dst, dstw);
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1750,38 +1639,36 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
        ADJUST_LOCAL_OFFSET(src1, src1w);
        ADJUST_LOCAL_OFFSET(src2, src2w);
 
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       op ^= SLJIT_SINGLE_OP;
+       op ^= SLJIT_F32_OP;
 
        dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
        if (src1 & SLJIT_MEM) {
-               emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
+               emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
                src1 = TMP_FREG1;
        }
        if (src2 & SLJIT_MEM) {
-               emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);
+               emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);
                src2 = TMP_FREG2;
        }
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DADD:
-               FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
+       case SLJIT_ADD_F64:
+               FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
                break;
-       case SLJIT_DSUB:
-               FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
+       case SLJIT_SUB_F64:
+               FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
                break;
-       case SLJIT_DMUL:
-               FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
+       case SLJIT_MUL_F64:
+               FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
                break;
-       case SLJIT_DDIV:
-               FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_SINGLE_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
+       case SLJIT_DIV_F64:
+               FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
                break;
        }
 
        if (!(dst & SLJIT_MEM))
                return SLJIT_SUCCESS;
-       return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
+       return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw);
 }
 
 #undef FPU_LOAD
@@ -1790,83 +1677,70 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
 /*  Other instructions                                                   */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       /* For UNUSED dst. Uncommon, but possible. */
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
+       SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
 
        if (FAST_IS_REG(dst))
-               return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3));
+               return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2));
 
        /* Memory. */
-       if (getput_arg_fast(compiler, WORD_SIZE | STORE, TMP_REG3, dst, dstw))
-               return compiler->error;
-       /* TMP_REG3 is used for caching. */
-       FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, TMP_REG3)));
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0);
+       return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
        ADJUST_LOCAL_OFFSET(src, srcw);
 
+       SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
+
        if (FAST_IS_REG(src))
-               FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src)));
+               FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));
        else if (src & SLJIT_MEM) {
-               if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw))
-                       FAIL_IF(compiler->error);
-               else {
-                       compiler->cache_arg = 0;
-                       compiler->cache_argw = 0;
-                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, 0, 0));
-                       FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, TMP_REG2)));
-               }
+               FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));
        }
        else if (src & SLJIT_IMM)
-               FAIL_IF(load_immediate(compiler, TMP_REG3, srcw));
-       return push_inst16(compiler, BLX | RN3(TMP_REG3));
+               FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
+       return push_inst16(compiler, BX | RN3(TMP_REG2));
 }
 
 /* --------------------------------------------------------------------- */
 /*  Conditional instructions                                             */
 /* --------------------------------------------------------------------- */
 
-static sljit_uw get_cc(sljit_si type)
+static sljit_uw get_cc(sljit_s32 type)
 {
        switch (type) {
        case SLJIT_EQUAL:
        case SLJIT_MUL_NOT_OVERFLOW:
-       case SLJIT_D_EQUAL:
+       case SLJIT_EQUAL_F64:
                return 0x0;
 
        case SLJIT_NOT_EQUAL:
        case SLJIT_MUL_OVERFLOW:
-       case SLJIT_D_NOT_EQUAL:
+       case SLJIT_NOT_EQUAL_F64:
                return 0x1;
 
        case SLJIT_LESS:
-       case SLJIT_D_LESS:
+       case SLJIT_LESS_F64:
                return 0x3;
 
        case SLJIT_GREATER_EQUAL:
-       case SLJIT_D_GREATER_EQUAL:
+       case SLJIT_GREATER_EQUAL_F64:
                return 0x2;
 
        case SLJIT_GREATER:
-       case SLJIT_D_GREATER:
+       case SLJIT_GREATER_F64:
                return 0x8;
 
        case SLJIT_LESS_EQUAL:
-       case SLJIT_D_LESS_EQUAL:
+       case SLJIT_LESS_EQUAL_F64:
                return 0x9;
 
        case SLJIT_SIG_LESS:
@@ -1882,15 +1756,15 @@ static sljit_uw get_cc(sljit_si type)
                return 0xd;
 
        case SLJIT_OVERFLOW:
-       case SLJIT_D_UNORDERED:
+       case SLJIT_UNORDERED_F64:
                return 0x6;
 
        case SLJIT_NOT_OVERFLOW:
-       case SLJIT_D_ORDERED:
+       case SLJIT_ORDERED_F64:
                return 0x7;
 
        default: /* SLJIT_JUMP */
-               SLJIT_ASSERT_STOP();
+               SLJIT_UNREACHABLE();
                return 0xe;
        }
 }
@@ -1911,7 +1785,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
        return label;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
        struct sljit_jump *jump;
        sljit_ins cc;
@@ -1944,7 +1818,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
        return jump;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
        struct sljit_jump *jump;
 
@@ -1957,7 +1831,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
                if (FAST_IS_REG(src))
                        return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src));
 
-               FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw));
+               FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw, TMP_REG1));
                if (type >= SLJIT_FAST_CALL)
                        return push_inst16(compiler, BLX | RN3(TMP_REG1));
        }
@@ -1972,25 +1846,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
        return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type)
 {
-       sljit_si dst_r, flags = GET_ALL_FLAGS(op);
-       sljit_ins cc, ins;
+       sljit_s32 dst_r, flags = GET_ALL_FLAGS(op);
+       sljit_ins cc;
 
        CHECK_ERROR();
-       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
        ADJUST_LOCAL_OFFSET(dst, dstw);
-       ADJUST_LOCAL_OFFSET(src, srcw);
-
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
 
        op = GET_OPCODE(op);
        cc = get_cc(type & 0xff);
-       dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+       dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
 
        if (op < SLJIT_ADD) {
                FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
@@ -1998,66 +1867,92 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
                        FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1));
                        FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0));
                } else {
+                       /* The movsi (immediate) instruction does not set flags in IT block. */
                        FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1));
                        FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0));
                }
-               if (dst_r != TMP_REG2)
+               if (!(dst & SLJIT_MEM))
                        return SLJIT_SUCCESS;
-               return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw);
+               return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2);
        }
 
-       ins = (op == SLJIT_AND ? ANDI : (op == SLJIT_OR ? ORRI : EORI));
-       if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) {
-               /* Does not change the other bits. */
+       if (dst & SLJIT_MEM)
+               FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));
+
+       if (op == SLJIT_AND) {
+               FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
+               FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 1));
+               FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 0));
+       }
+       else {
                FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
-               FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst) | 1));
-               if (flags & SLJIT_SET_E) {
-                       /* The condition must always be set, even if the ORRI/EORI is not executed above. */
-                       if (reg_map[dst] <= 7)
-                               return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst));
-                       return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst));
-               }
+               FAIL_IF(push_inst32(compiler, ((op == SLJIT_OR) ? ORRI : EORI) | RN4(dst_r) | RD4(dst_r) | 1));
+       }
+
+       if (dst & SLJIT_MEM)
+               FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2));
+
+       if (!(flags & SLJIT_SET_Z))
                return SLJIT_SUCCESS;
+
+       /* The condition must always be set, even if the ORR/EORI is not executed above. */
+       if (reg_map[dst_r] <= 7)
+               return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst_r));
+       return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+       sljit_uw cc, tmp;
+
+       CHECK_ERROR();
+       CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+       dst_reg &= ~SLJIT_I32_OP;
+
+       cc = get_cc(type & 0xff);
+
+       if (!(src & SLJIT_IMM)) {
+               FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+               return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src));
        }
 
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-       if (src & SLJIT_MEM) {
-               FAIL_IF(emit_op_mem2(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw));
-               src = TMP_REG2;
-               srcw = 0;
-       } else if (src & SLJIT_IMM) {
-               FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
-               src = TMP_REG2;
-               srcw = 0;
+       tmp = (sljit_uw) srcw;
+
+       if (tmp < 0x10000) {
+               /* set low 16 bits, set hi 16 bits to 0. */
+               FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+               return push_inst32(compiler, MOVW | RD4(dst_reg) |
+                       COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff));
        }
 
-       if (op == SLJIT_AND || src != dst_r) {
-               FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
-               FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
-               FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 0));
+       tmp = get_imm(srcw);
+       if (tmp != INVALID_IMM) {
+               FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+               return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);
        }
-       else {
+
+       tmp = get_imm(~srcw);
+       if (tmp != INVALID_IMM) {
                FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
-               FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
+               return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);
        }
 
-       if (dst_r == TMP_REG2)
-               FAIL_IF(emit_op_mem2(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0));
+       FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4));
 
-       if (flags & SLJIT_SET_E) {
-               /* The condition must always be set, even if the ORR/EORI is not executed above. */
-               if (reg_map[dst_r] <= 7)
-                       return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst_r));
-               return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r));
-       }
-       return SLJIT_SUCCESS;
+       tmp = (sljit_uw) srcw;
+       FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg) |
+               COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)));
+       return push_inst32(compiler, MOVT | RD4(dst_reg) |
+               COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+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_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR_PTR();
        CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -2067,24 +1962,26 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
        PTR_FAIL_IF(!const_);
        set_const(const_, compiler);
 
-       dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+       dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
        PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value));
 
        if (dst & SLJIT_MEM)
-               PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw));
+               PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
        return const_;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
 {
-       sljit_uh *inst = (sljit_uh*)addr;
-       modify_imm32_const(inst, new_addr);
+       sljit_u16 *inst = (sljit_u16*)addr;
+       modify_imm32_const(inst, new_target);
+       inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
        SLJIT_CACHE_FLUSH(inst, inst + 4);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
-       sljit_uh *inst = (sljit_uh*)addr;
+       sljit_u16 *inst = (sljit_u16*)addr;
        modify_imm32_const(inst, new_constant);
+       inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
        SLJIT_CACHE_FLUSH(inst, inst + 4);
 }
index b2b60d7a4c9d576ce41020378857bdabd0633e72..62e16106b12b8ee689ab0768f2716eb34fcc5601 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -26,7 +26,7 @@
 
 /* mips 32-bit arch dependent functions. */
 
-static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
 {
        if (!(imm & ~0xffff))
                return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
@@ -40,50 +40,52 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
 
 #define EMIT_LOGICAL(op_imm, op_norm) \
        if (flags & SRC2_IMM) { \
-               if (op & SLJIT_SET_E) \
+               if (op & SLJIT_SET_Z) \
                        FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
-               if (CHECK_FLAGS(SLJIT_SET_E)) \
+               if (!(flags & UNUSED_DEST)) \
                        FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
        } \
        else { \
-               if (op & SLJIT_SET_E) \
+               if (op & SLJIT_SET_Z) \
                        FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
-               if (CHECK_FLAGS(SLJIT_SET_E)) \
+               if (!(flags & UNUSED_DEST)) \
                        FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
        }
 
 #define EMIT_SHIFT(op_imm, op_v) \
        if (flags & SRC2_IMM) { \
-               if (op & SLJIT_SET_E) \
+               if (op & SLJIT_SET_Z) \
                        FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
-               if (CHECK_FLAGS(SLJIT_SET_E)) \
+               if (!(flags & UNUSED_DEST)) \
                        FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
        } \
        else { \
-               if (op & SLJIT_SET_E) \
+               if (op & SLJIT_SET_Z) \
                        FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
-               if (CHECK_FLAGS(SLJIT_SET_E)) \
+               if (!(flags & UNUSED_DEST)) \
                        FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \
        }
 
-static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
-       sljit_si dst, sljit_si src1, sljit_sw src2)
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+       sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
 {
+       sljit_s32 is_overflow, is_carry, is_handled;
+
        switch (GET_OPCODE(op)) {
        case SLJIT_MOV:
-       case SLJIT_MOV_UI:
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOV_S32:
        case SLJIT_MOV_P:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if (dst != src2)
                        return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UB:
-       case SLJIT_MOV_SB:
+       case SLJIT_MOV_U8:
+       case SLJIT_MOV_S8:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SB) {
+                       if (op == SLJIT_MOV_S8) {
 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
                                return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
 #else
@@ -93,15 +95,16 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                        }
                        return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
                }
-               else if (dst != src2)
-                       SLJIT_ASSERT_STOP();
+               else {
+                       SLJIT_ASSERT(dst == src2);
+               }
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UH:
-       case SLJIT_MOV_SH:
+       case SLJIT_MOV_U16:
+       case SLJIT_MOV_S16:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SH) {
+                       if (op == SLJIT_MOV_S16) {
 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
                                return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
 #else
@@ -111,24 +114,25 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                        }
                        return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
                }
-               else if (dst != src2)
-                       SLJIT_ASSERT_STOP();
+               else {
+                       SLJIT_ASSERT(dst == src2);
+               }
                return SLJIT_SUCCESS;
 
        case SLJIT_NOT:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
-               if (op & SLJIT_SET_E)
+               if (op & SLJIT_SET_Z)
                        FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
-               if (CHECK_FLAGS(SLJIT_SET_E))
+               if (!(flags & UNUSED_DEST))
                        FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
                return SLJIT_SUCCESS;
 
        case SLJIT_CLZ:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
-               if (op & SLJIT_SET_E)
+               if (op & SLJIT_SET_Z)
                        FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
-               if (CHECK_FLAGS(SLJIT_SET_E))
+               if (!(flags & UNUSED_DEST))
                        FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
 #else
                if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
@@ -145,130 +149,192 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
                FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
                FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
-               if (op & SLJIT_SET_E)
-                       return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
 #endif
                return SLJIT_SUCCESS;
 
        case SLJIT_ADD:
+               is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+               is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
                if (flags & SRC2_IMM) {
-                       if (op & SLJIT_SET_O) {
+                       if (is_overflow) {
                                if (src2 >= 0)
-                                       FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
                                else
-                                       FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
                        }
-                       if (op & SLJIT_SET_E)
+                       else if (op & SLJIT_SET_Z)
                                FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
-                       if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
+
+                       if (is_overflow || is_carry) {
                                if (src2 >= 0)
-                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
                                else {
-                                       FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
-                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+                                       FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
                                }
                        }
                        /* dst may be the same as src1 or src2. */
-                       if (CHECK_FLAGS(SLJIT_SET_E))
+                       if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
                                FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
                }
                else {
-                       if (op & SLJIT_SET_O)
-                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-                       if (op & SLJIT_SET_E)
+                       if (is_overflow)
+                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+                       else if (op & SLJIT_SET_Z)
                                FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
-                       if (op & (SLJIT_SET_C | SLJIT_SET_O))
-                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
+
+                       if (is_overflow || is_carry)
+                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
                        /* dst may be the same as src1 or src2. */
-                       if (CHECK_FLAGS(SLJIT_SET_E))
+                       if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
                                FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
                }
 
                /* a + b >= a | b (otherwise, the carry should be set to 1). */
-               if (op & (SLJIT_SET_C | SLJIT_SET_O))
-                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
-               if (!(op & SLJIT_SET_O))
+               if (is_overflow || is_carry)
+                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+               if (!is_overflow)
                        return SLJIT_SUCCESS;
-               FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
-               FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-               FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-               return push_inst(compiler, SLL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+               FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+               FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+               if (op & SLJIT_SET_Z)
+                       FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
 
        case SLJIT_ADDC:
+               is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
                if (flags & SRC2_IMM) {
-                       if (op & SLJIT_SET_C) {
+                       if (is_carry) {
                                if (src2 >= 0)
-                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
                                else {
-                                       FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
-                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
                                }
                        }
                        FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
                } else {
-                       if (op & SLJIT_SET_C)
-                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                       if (is_carry)
+                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
                        /* dst may be the same as src1 or src2. */
                        FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
                }
-               if (op & SLJIT_SET_C)
-                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+               if (is_carry)
+                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
 
-               FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
-               if (!(op & SLJIT_SET_C))
+               FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+               if (!is_carry)
                        return SLJIT_SUCCESS;
 
-               /* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
-               FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+               /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
+               FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
                /* Set carry flag. */
-               return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
+               return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
 
        case SLJIT_SUB:
-               if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
+               if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
                        FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
                        src2 = TMP_REG2;
                        flags &= ~SRC2_IMM;
                }
 
+               is_handled = 0;
+
+               if (flags & SRC2_IMM) {
+                       if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
+                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+                               is_handled = 1;
+                       }
+                       else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
+                               FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+                               is_handled = 1;
+                       }
+               }
+
+               if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
+                       is_handled = 1;
+
+                       if (flags & SRC2_IMM) {
+                               FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+                               src2 = TMP_REG2;
+                               flags &= ~SRC2_IMM;
+                       }
+
+                       if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
+                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+                       }
+                       else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
+                       {
+                               FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+                       }
+                       else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
+                               FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+                       }
+                       else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
+                       {
+                               FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+                       }
+               }
+
+               if (is_handled) {
+                       if (flags & SRC2_IMM) {
+                               if (op & SLJIT_SET_Z)
+                                       FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
+                               if (!(flags & UNUSED_DEST))
+                                       return push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst));
+                       }
+                       else {
+                               if (op & SLJIT_SET_Z)
+                                       FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+                               if (!(flags & UNUSED_DEST))
+                                       return push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst));
+                       }
+                       return SLJIT_SUCCESS;
+               }
+
+               is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+               is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
                if (flags & SRC2_IMM) {
-                       if (op & SLJIT_SET_O) {
+                       if (is_overflow) {
                                if (src2 >= 0)
-                                       FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
                                else
-                                       FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
                        }
-                       if (op & SLJIT_SET_E)
+                       else if (op & SLJIT_SET_Z)
                                FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
-                       if (op & (SLJIT_SET_C | SLJIT_SET_O))
-                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+
+                       if (is_overflow || is_carry)
+                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
                        /* dst may be the same as src1 or src2. */
-                       if (CHECK_FLAGS(SLJIT_SET_E))
+                       if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
                                FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
                }
                else {
-                       if (op & SLJIT_SET_O)
-                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-                       if (op & SLJIT_SET_E)
+                       if (is_overflow)
+                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+                       else if (op & SLJIT_SET_Z)
                                FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
-                       if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
-                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
-                       if (op & SLJIT_SET_U)
-                               FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
-                       if (op & SLJIT_SET_S) {
-                               FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
-                               FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
-                       }
+
+                       if (is_overflow || is_carry)
+                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
                        /* dst may be the same as src1 or src2. */
-                       if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
+                       if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
                                FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
                }
 
-               if (!(op & SLJIT_SET_O))
+               if (!is_overflow)
                        return SLJIT_SUCCESS;
-               FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
-               FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-               FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-               return push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+               FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+               FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+               if (op & SLJIT_SET_Z)
+                       FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
 
        case SLJIT_SUBC:
                if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
@@ -277,28 +343,31 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                        flags &= ~SRC2_IMM;
                }
 
+               is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
                if (flags & SRC2_IMM) {
-                       if (op & SLJIT_SET_C)
-                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
+                       if (is_carry)
+                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
                        /* dst may be the same as src1 or src2. */
                        FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
                }
                else {
-                       if (op & SLJIT_SET_C)
-                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                       if (is_carry)
+                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
                        /* dst may be the same as src1 or src2. */
                        FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
                }
 
-               if (op & SLJIT_SET_C)
-                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
+               if (is_carry)
+                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
 
-               FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
-               return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
+               FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+               return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
 
        case SLJIT_MUL:
                SLJIT_ASSERT(!(flags & SRC2_IMM));
-               if (!(op & SLJIT_SET_O)) {
+
+               if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
                        return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
 #else
@@ -307,10 +376,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
 #endif
                }
                FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
-               FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
+               FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
                FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
-               FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
-               return push_inst(compiler, SUBU | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
+               FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
+               return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
 
        case SLJIT_AND:
                EMIT_LOGICAL(ANDI, AND);
@@ -337,30 +406,32 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                return SLJIT_SUCCESS;
        }
 
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
 {
        FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
        return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+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;
+       sljit_ins *inst = (sljit_ins *)addr;
 
-       inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
-       inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
+       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);
        SLJIT_CACHE_FLUSH(inst, inst + 2);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
-       sljit_ins *inst = (sljit_ins*)addr;
+       sljit_ins *inst = (sljit_ins *)addr;
 
        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);
        SLJIT_CACHE_FLUSH(inst, inst + 2);
 }
index 185fb5768e2a6c5054c98ff994bfd938b3f213a1..dd114bb27af9b641aaebb8b1ea3ca73a61f2ba58 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
 
 /* mips 64-bit arch dependent functions. */
 
-static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
 {
-       sljit_si shift = 32;
-       sljit_si shift2;
-       sljit_si inv = 0;
+       sljit_s32 shift = 32;
+       sljit_s32 shift2;
+       sljit_s32 inv = 0;
        sljit_ins ins;
        sljit_uw uimm;
 
@@ -119,48 +119,49 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
 }
 
 #define SELECT_OP(a, b) \
-       (!(op & SLJIT_INT_OP) ? a : b)
+       (!(op & SLJIT_I32_OP) ? a : b)
 
 #define EMIT_LOGICAL(op_imm, op_norm) \
        if (flags & SRC2_IMM) { \
-               if (op & SLJIT_SET_E) \
+               if (op & SLJIT_SET_Z) \
                        FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
-               if (CHECK_FLAGS(SLJIT_SET_E)) \
+               if (!(flags & UNUSED_DEST)) \
                        FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
        } \
        else { \
-               if (op & SLJIT_SET_E) \
+               if (op & SLJIT_SET_Z) \
                        FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
-               if (CHECK_FLAGS(SLJIT_SET_E)) \
+               if (!(flags & UNUSED_DEST)) \
                        FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
        }
 
 #define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
        if (flags & SRC2_IMM) { \
                if (src2 >= 32) { \
-                       SLJIT_ASSERT(!(op & SLJIT_INT_OP)); \
+                       SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \
                        ins = op_dimm32; \
                        src2 -= 32; \
                } \
                else \
-                       ins = (op & SLJIT_INT_OP) ? op_imm : op_dimm; \
-               if (op & SLJIT_SET_E) \
+                       ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \
+               if (op & SLJIT_SET_Z) \
                        FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
-               if (CHECK_FLAGS(SLJIT_SET_E)) \
+               if (!(flags & UNUSED_DEST)) \
                        FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
        } \
        else { \
-               ins = (op & SLJIT_INT_OP) ? op_v : op_dv; \
-               if (op & SLJIT_SET_E) \
+               ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \
+               if (op & SLJIT_SET_Z) \
                        FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
-               if (CHECK_FLAGS(SLJIT_SET_E)) \
+               if (!(flags & UNUSED_DEST)) \
                        FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
        }
 
-static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
-       sljit_si dst, sljit_si src1, sljit_sw src2)
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+       sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
 {
        sljit_ins ins;
+       sljit_s32 is_overflow, is_carry, is_handled;
 
        switch (GET_OPCODE(op)) {
        case SLJIT_MOV:
@@ -170,57 +171,59 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                        return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UB:
-       case SLJIT_MOV_SB:
+       case SLJIT_MOV_U8:
+       case SLJIT_MOV_S8:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SB) {
+                       if (op == SLJIT_MOV_S8) {
                                FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
                                return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
                        }
                        return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
                }
-               else if (dst != src2)
-                       SLJIT_ASSERT_STOP();
+               else {
+                       SLJIT_ASSERT(dst == src2);
+               }
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UH:
-       case SLJIT_MOV_SH:
+       case SLJIT_MOV_U16:
+       case SLJIT_MOV_S16:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SH) {
+                       if (op == SLJIT_MOV_S16) {
                                FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
                                return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
                        }
                        return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
                }
-               else if (dst != src2)
-                       SLJIT_ASSERT_STOP();
+               else {
+                       SLJIT_ASSERT(dst == src2);
+               }
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UI:
-               SLJIT_ASSERT(!(op & SLJIT_INT_OP));
+       case SLJIT_MOV_U32:
+               SLJIT_ASSERT(!(op & SLJIT_I32_OP));
                FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
                return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
 
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_S32:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
 
        case SLJIT_NOT:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
-               if (op & SLJIT_SET_E)
+               if (op & SLJIT_SET_Z)
                        FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
-               if (CHECK_FLAGS(SLJIT_SET_E))
+               if (!(flags & UNUSED_DEST))
                        FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
                return SLJIT_SUCCESS;
 
        case SLJIT_CLZ:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
-               if (op & SLJIT_SET_E)
+               if (op & SLJIT_SET_Z)
                        FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
-               if (CHECK_FLAGS(SLJIT_SET_E))
+               if (!(flags & UNUSED_DEST))
                        FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
 #else
                if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
@@ -231,136 +234,198 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
                /* Check zero. */
                FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
-               FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_INT_OP) ? 32 : 64), UNMOVABLE_INS));
+               FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS));
                FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
                /* Loop for searching the highest bit. */
                FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
                FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
                FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
-               if (op & SLJIT_SET_E)
-                       return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
 #endif
                return SLJIT_SUCCESS;
 
        case SLJIT_ADD:
+               is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+               is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
                if (flags & SRC2_IMM) {
-                       if (op & SLJIT_SET_O) {
+                       if (is_overflow) {
                                if (src2 >= 0)
-                                       FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
                                else
-                                       FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
                        }
-                       if (op & SLJIT_SET_E)
+                       else if (op & SLJIT_SET_Z)
                                FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
-                       if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
+
+                       if (is_overflow || is_carry) {
                                if (src2 >= 0)
-                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
                                else {
-                                       FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
-                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+                                       FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
                                }
                        }
                        /* dst may be the same as src1 or src2. */
-                       if (CHECK_FLAGS(SLJIT_SET_E))
+                       if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
                                FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
                }
                else {
-                       if (op & SLJIT_SET_O)
-                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-                       if (op & SLJIT_SET_E)
+                       if (is_overflow)
+                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+                       else if (op & SLJIT_SET_Z)
                                FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
-                       if (op & (SLJIT_SET_C | SLJIT_SET_O))
-                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
+
+                       if (is_overflow || is_carry)
+                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
                        /* dst may be the same as src1 or src2. */
-                       if (CHECK_FLAGS(SLJIT_SET_E))
+                       if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
                                FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
                }
 
                /* a + b >= a | b (otherwise, the carry should be set to 1). */
-               if (op & (SLJIT_SET_C | SLJIT_SET_O))
-                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
-               if (!(op & SLJIT_SET_O))
+               if (is_overflow || is_carry)
+                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+               if (!is_overflow)
                        return SLJIT_SUCCESS;
-               FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
-               FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-               FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-               return push_inst(compiler, SELECT_OP(DSRL32, SLL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+               FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+               FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+               if (op & SLJIT_SET_Z)
+                       FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
 
        case SLJIT_ADDC:
+               is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
                if (flags & SRC2_IMM) {
-                       if (op & SLJIT_SET_C) {
+                       if (is_carry) {
                                if (src2 >= 0)
-                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
                                else {
-                                       FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
-                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
                                }
                        }
                        FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
                } else {
-                       if (op & SLJIT_SET_C)
-                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                       if (is_carry)
+                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
                        /* dst may be the same as src1 or src2. */
                        FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
                }
-               if (op & SLJIT_SET_C)
-                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+               if (is_carry)
+                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
 
-               FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
-               if (!(op & SLJIT_SET_C))
+               FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+               if (!is_carry)
                        return SLJIT_SUCCESS;
 
-               /* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
-               FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+               /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
+               FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
                /* Set carry flag. */
-               return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG);
+               return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
 
        case SLJIT_SUB:
-               if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
+               if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
                        FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
                        src2 = TMP_REG2;
                        flags &= ~SRC2_IMM;
                }
 
+               is_handled = 0;
+
                if (flags & SRC2_IMM) {
-                       if (op & SLJIT_SET_O) {
+                       if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
+                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+                               is_handled = 1;
+                       }
+                       else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
+                               FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+                               is_handled = 1;
+                       }
+               }
+
+               if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
+                       is_handled = 1;
+
+                       if (flags & SRC2_IMM) {
+                               FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+                               src2 = TMP_REG2;
+                               flags &= ~SRC2_IMM;
+                       }
+
+                       if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
+                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+                       }
+                       else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
+                       {
+                               FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+                       }
+                       else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
+                               FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+                       }
+                       else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
+                       {
+                               FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+                       }
+               }
+
+               if (is_handled) {
+                       if (flags & SRC2_IMM) {
+                               if (op & SLJIT_SET_Z)
+                                       FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
+                               if (!(flags & UNUSED_DEST))
+                                       return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
+                       }
+                       else {
+                               if (op & SLJIT_SET_Z)
+                                       FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+                               if (!(flags & UNUSED_DEST))
+                                       return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
+                       }
+                       return SLJIT_SUCCESS;
+               }
+
+               is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+               is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
+               if (flags & SRC2_IMM) {
+                       if (is_overflow) {
                                if (src2 >= 0)
-                                       FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
                                else
-                                       FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                                       FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
                        }
-                       if (op & SLJIT_SET_E)
+                       else if (op & SLJIT_SET_Z)
                                FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
-                       if (op & (SLJIT_SET_C | SLJIT_SET_O))
-                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+
+                       if (is_overflow || is_carry)
+                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
                        /* dst may be the same as src1 or src2. */
-                       if (CHECK_FLAGS(SLJIT_SET_E))
+                       if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
                                FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
                }
                else {
-                       if (op & SLJIT_SET_O)
-                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-                       if (op & SLJIT_SET_E)
+                       if (is_overflow)
+                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+                       else if (op & SLJIT_SET_Z)
                                FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
-                       if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
-                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
-                       if (op & SLJIT_SET_U)
-                               FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
-                       if (op & SLJIT_SET_S) {
-                               FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
-                               FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
-                       }
+
+                       if (is_overflow || is_carry)
+                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
                        /* dst may be the same as src1 or src2. */
-                       if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
+                       if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
                                FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
                }
 
-               if (!(op & SLJIT_SET_O))
+               if (!is_overflow)
                        return SLJIT_SUCCESS;
-               FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
-               FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-               FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
-               return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
+               FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+               FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+               if (op & SLJIT_SET_Z)
+                       FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
 
        case SLJIT_SUBC:
                if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
@@ -369,30 +434,33 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                        flags &= ~SRC2_IMM;
                }
 
+               is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+
                if (flags & SRC2_IMM) {
-                       if (op & SLJIT_SET_C)
-                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG));
+                       if (is_carry)
+                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
                        /* dst may be the same as src1 or src2. */
                        FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
                }
                else {
-                       if (op & SLJIT_SET_C)
-                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                       if (is_carry)
+                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
                        /* dst may be the same as src1 or src2. */
                        FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
                }
 
-               if (op & SLJIT_SET_C)
-                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG));
+               if (is_carry)
+                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
 
-               FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
-               return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
+               FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+               return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
 
        case SLJIT_MUL:
                SLJIT_ASSERT(!(flags & SRC2_IMM));
-               if (!(op & SLJIT_SET_O)) {
+
+               if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
-                       if (op & SLJIT_INT_OP)
+                       if (op & SLJIT_I32_OP)
                                return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
                        FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
                        return push_inst(compiler, MFLO | D(dst), DR(dst));
@@ -402,10 +470,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
 #endif
                }
                FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
-               FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG));
+               FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
                FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
-               FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG));
-               return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
+               FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
+               return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
 
        case SLJIT_AND:
                EMIT_LOGICAL(ANDI, AND);
@@ -432,11 +500,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                return SLJIT_SUCCESS;
        }
 
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
 {
        FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
        FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
@@ -446,24 +514,26 @@ static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_s
        return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+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;
+       sljit_ins *inst = (sljit_ins *)addr;
 
-       inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
-       inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
-       inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
-       inst[5] = (inst[5] & 0xffff0000) | (new_addr & 0xffff);
+       inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
+       inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
+       inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
+       inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff);
+       inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
        SLJIT_CACHE_FLUSH(inst, inst + 6);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
-       sljit_ins *inst = (sljit_ins*)addr;
+       sljit_ins *inst = (sljit_ins *)addr;
 
        inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
        inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
        inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
        inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
+       inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
        SLJIT_CACHE_FLUSH(inst, inst + 6);
 }
index cf3535f81a77c7383068b4198bc159701eb9892f..ee207fe1191573c654f1a3c12ceb15c77a464ed6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -27,7 +27,7 @@
 /* Latest MIPS architecture. */
 /* Automatically detect SLJIT_MIPS_R1 */
 
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
 {
 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
@@ -42,7 +42,7 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
 
 /* Length of an instruction word
    Both for mips-32 and mips-64 */
-typedef sljit_ui sljit_ins;
+typedef sljit_u32 sljit_ins;
 
 #define TMP_REG1       (SLJIT_NUMBER_OF_REGISTERS + 2)
 #define TMP_REG2       (SLJIT_NUMBER_OF_REGISTERS + 3)
@@ -57,19 +57,14 @@ typedef sljit_ui sljit_ins;
 #define RETURN_ADDR_REG        31
 
 /* Flags are kept in volatile registers. */
-#define EQUAL_FLAG     12
-/* And carry flag as well. */
-#define ULESS_FLAG     13
-#define UGREATER_FLAG  14
-#define LESS_FLAG      15
-#define GREATER_FLAG   31
-#define OVERFLOW_FLAG  1
+#define EQUAL_FLAG     31
+#define OTHER_FLAG     1
 
 #define TMP_FREG1      (0)
 #define TMP_FREG2      ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1)
 
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
-       0, 2, 5, 6, 7, 8, 9, 10, 11, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 3, 25, 4
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
+       0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 3, 25, 4
 };
 
 /* --------------------------------------------------------------------- */
@@ -178,7 +173,13 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
 #define CLZ            (HI(28) | LO(32))
 #define DCLZ           (HI(28) | LO(36))
+#define MOVF           (HI(0) | (0 << 16) | LO(1))
+#define MOVN           (HI(0) | LO(11))
+#define MOVT           (HI(0) | (1 << 16) | LO(1))
+#define MOVZ           (HI(0) | LO(10))
 #define MUL            (HI(28) | LO(2))
+#define PREF           (HI(51))
+#define PREFX          (HI(19) | LO(15))
 #define SEB            (HI(31) | (16 << 6) | LO(32))
 #define SEH            (HI(31) | (24 << 6) | LO(32))
 #endif
@@ -201,7 +202,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
 
 /* dest_reg is the absolute name of the register
    Useful for reordering instructions in the delay slot. */
-static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_si delay_slot)
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)
 {
        SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS
                || delay_slot == ((ins >> 11) & 0x1f) || delay_slot == ((ins >> 16) & 0x1f));
@@ -213,12 +214,12 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_ins invert_branch(sljit_si flags)
+static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags)
 {
        return (flags & IS_BIT26_COND) ? (1 << 26) : (1 << 16);
 }
 
-static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_ins* 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;
@@ -237,9 +238,10 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
                target_addr = jump->u.target;
        else {
                SLJIT_ASSERT(jump->flags & JUMP_LABEL);
-               target_addr = (sljit_uw)(code + jump->u.label->size);
+               target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
        }
-       inst = (sljit_ins*)jump->addr;
+
+       inst = (sljit_ins *)jump->addr;
        if (jump->flags & IS_COND)
                inst--;
 
@@ -250,7 +252,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
 
        /* B instructions. */
        if (jump->flags & IS_MOVABLE) {
-               diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
+               diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;
                if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
                        jump->flags |= PATCH_B;
 
@@ -268,7 +270,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
                }
        }
        else {
-               diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1)) >> 2;
+               diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
                if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
                        jump->flags |= PATCH_B;
 
@@ -364,6 +366,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        sljit_ins *buf_ptr;
        sljit_ins *buf_end;
        sljit_uw word_count;
+       sljit_sw executable_offset;
        sljit_uw addr;
 
        struct sljit_label *label;
@@ -380,9 +383,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
        code_ptr = code;
        word_count = 0;
+       executable_offset = SLJIT_EXEC_OFFSET(code);
+
        label = compiler->labels;
        jump = compiler->jumps;
        const_ = compiler->consts;
+
        do {
                buf_ptr = (sljit_ins*)buf->memory;
                buf_end = buf_ptr + (buf->used_size >> 2);
@@ -393,8 +399,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                        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)code_ptr;
+                               label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
                                label->size = code_ptr - code;
                                label = label->next;
                        }
@@ -404,7 +409,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 #else
                                jump->addr = (sljit_uw)(code_ptr - 7);
 #endif
-                               code_ptr = detect_jump_type(jump, code_ptr, code);
+                               code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
                                jump = jump->next;
                        }
                        if (const_ && const_->addr == word_count) {
@@ -434,16 +439,16 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        while (jump) {
                do {
                        addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
-                       buf_ptr = (sljit_ins*)jump->addr;
+                       buf_ptr = (sljit_ins *)jump->addr;
 
                        if (jump->flags & PATCH_B) {
-                               addr = (sljit_sw)(addr - (jump->addr + sizeof(sljit_ins))) >> 2;
+                               addr = (sljit_sw)(addr - ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins))) >> 2;
                                SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
                                buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | (addr & 0xffff);
                                break;
                        }
                        if (jump->flags & PATCH_J) {
-                               SLJIT_ASSERT((addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff));
+                               SLJIT_ASSERT((addr & ~0xfffffff) == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~0xfffffff));
                                buf_ptr[0] |= (addr >> 2) & 0x03ffffff;
                                break;
                        }
@@ -476,7 +481,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        }
 
        compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_offset = executable_offset;
        compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+
+       code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+       code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
 #ifndef __GNUC__
        SLJIT_CACHE_FLUSH(code, code_ptr);
 #else
@@ -486,6 +496,31 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        return code;
 }
 
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+       switch (feature_type) {
+       case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+               return SLJIT_IS_FPU_AVAILABLE;
+#elif defined(__GNUC__)
+               sljit_sw fir;
+               asm ("cfc1 %0, $0" : "=r"(fir));
+               return (fir >> 22) & 0x1;
+#else
+#error "FIR check is not implemented for this architecture"
+#endif
+
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+       case SLJIT_HAS_CLZ:
+       case SLJIT_HAS_CMOV:
+               return 1;
+#endif
+
+       default:
+               return 0;
+       }
+}
+
 /* --------------------------------------------------------------------- */
 /*  Entry, exit                                                          */
 /* --------------------------------------------------------------------- */
@@ -520,10 +555,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 #define SLOW_SRC2      0x20000
 #define SLOW_DEST      0x40000
 
-/* Only these flags are set. UNUSED_DEST is not set when no flags should be set. */
-#define CHECK_FLAGS(list) \
-       (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list))))
-
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
 #define STACK_STORE    SW
 #define STACK_LOAD     LW
@@ -538,12 +569,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 #include "sljitNativeMIPS_64.c"
 #endif
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
        sljit_ins base;
-       sljit_si i, tmp, offs;
+       sljit_s32 i, tmp, offs;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -575,12 +606,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
 
        tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
        for (i = SLJIT_S0; i >= tmp; i--) {
-               offs -= (sljit_si)(sizeof(sljit_sw));
+               offs -= (sljit_s32)(sizeof(sljit_sw));
                FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
        }
 
        for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
-               offs -= (sljit_si)(sizeof(sljit_sw));
+               offs -= (sljit_s32)(sizeof(sljit_sw));
                FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
        }
 
@@ -594,9 +625,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
        CHECK_ERROR();
        CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -611,9 +642,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si local_size, i, tmp, offs;
+       sljit_s32 local_size, i, tmp, offs;
        sljit_ins base;
 
        CHECK_ERROR();
@@ -631,19 +662,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
                local_size = 0;
        }
 
-       FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - (sljit_si)sizeof(sljit_sw)), RETURN_ADDR_REG));
-       offs = local_size - (sljit_si)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
+       FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - (sljit_s32)sizeof(sljit_sw)), RETURN_ADDR_REG));
+       offs = local_size - (sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
 
        tmp = compiler->scratches;
        for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
                FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));
-               offs += (sljit_si)(sizeof(sljit_sw));
+               offs += (sljit_s32)(sizeof(sljit_sw));
        }
 
        tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
        for (i = tmp; i <= SLJIT_S0; i++) {
                FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));
-               offs += (sljit_si)(sizeof(sljit_sw));
+               offs += (sljit_s32)(sizeof(sljit_sw));
        }
 
        SLJIT_ASSERT(offs == local_size - (sljit_sw)(sizeof(sljit_sw)));
@@ -668,7 +699,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
 #define ARCH_32_64(a, b)       b
 #endif
 
-static SLJIT_CONST sljit_ins data_transfer_insts[16 + 4] = {
+static const sljit_ins data_transfer_insts[16 + 4] = {
 /* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
 /* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
 /* u b s */ HI(40) /* sb */,
@@ -698,7 +729,7 @@ static SLJIT_CONST sljit_ins data_transfer_insts[16 + 4] = {
 /* reg_ar is an absoulute register! */
 
 /* Can perform an operation using at most 1 instruction. */
-static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
 {
        SLJIT_ASSERT(arg & SLJIT_MEM);
 
@@ -716,7 +747,7 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
 /* See getput_arg below.
    Note: can_cache is called only for binary operators. Those
    operators always uses word arguments without write back. */
-static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
        SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
 
@@ -739,9 +770,9 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
 }
 
 /* Emit the necessary instructions. See can_cache above. */
-static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
-       sljit_si tmp_ar, base, delay_slot;
+       sljit_s32 tmp_ar, base, delay_slot;
 
        SLJIT_ASSERT(arg & SLJIT_MEM);
        if (!(next_arg & SLJIT_MEM)) {
@@ -759,34 +790,28 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
        base = arg & REG_MASK;
 
        if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
-               argw &= 0x3;
-               if ((flags & WRITE_BACK) && reg_ar == DR(base)) {
-                       SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar);
-                       FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
-                       reg_ar = DR(TMP_REG1);
+               if (SLJIT_UNLIKELY(flags & WRITE_BACK)) {
+                       SLJIT_ASSERT(argw == 0);
+                       FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | D(base), DR(base)));
+                       return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
                }
 
+               argw &= 0x3;
+
                /* Using the cache. */
                if (argw == compiler->cache_argw) {
-                       if (!(flags & WRITE_BACK)) {
-                               if (arg == compiler->cache_arg)
+                       if (arg == compiler->cache_arg)
+                               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
+
+                       if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
+                               if (arg == next_arg && argw == (next_argw & 0x3)) {
+                                       compiler->cache_arg = arg;
+                                       compiler->cache_argw = argw;
+                                       FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
                                        return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
-                               if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
-                                       if (arg == next_arg && argw == (next_argw & 0x3)) {
-                                               compiler->cache_arg = arg;
-                                               compiler->cache_argw = argw;
-                                               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
-                                               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
-                                       }
-                                       FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
-                                       return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
-                               }
-                       }
-                       else {
-                               if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
-                                       FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
-                                       return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
                                }
+                               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
+                               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
                        }
                }
 
@@ -796,35 +821,18 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
                        FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
                }
 
-               if (!(flags & WRITE_BACK)) {
-                       if (arg == next_arg && argw == (next_argw & 0x3)) {
-                               compiler->cache_arg = arg;
-                               compiler->cache_argw = argw;
-                               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
-                               tmp_ar = DR(TMP_REG3);
-                       }
-                       else
-                               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
-                       return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
+               if (arg == next_arg && argw == (next_argw & 0x3)) {
+                       compiler->cache_arg = arg;
+                       compiler->cache_argw = argw;
+                       FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
+                       tmp_ar = DR(TMP_REG3);
                }
-               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(base), DR(base)));
-               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
+               else
+                       FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
+               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
        }
 
        if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) {
-               /* Update only applies if a base register exists. */
-               if (reg_ar == DR(base)) {
-                       SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar);
-                       if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
-                               FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar) | IMM(argw), MOVABLE_INS));
-                               if (argw)
-                                       return push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base));
-                               return SLJIT_SUCCESS;
-                       }
-                       FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
-                       reg_ar = DR(TMP_REG1);
-               }
-
                if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
                        if (argw)
                                FAIL_IF(push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base)));
@@ -878,7 +886,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
        return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
 }
 
-static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
 {
        if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
                return compiler->error;
@@ -887,26 +895,26 @@ static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_
        return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0);
 }
 
-static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
 {
        if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
                return compiler->error;
        return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
 }
 
-static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        /* arg1 goes to TMP_REG1 or src reg
           arg2 goes to TMP_REG2, imm or src reg
           TMP_REG3 can be used for caching
           result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
-       sljit_si dst_r = TMP_REG2;
-       sljit_si src1_r;
+       sljit_s32 dst_r = TMP_REG2;
+       sljit_s32 src1_r;
        sljit_sw src2_r = 0;
-       sljit_si sugg_src2_r = TMP_REG2;
+       sljit_s32 sugg_src2_r = TMP_REG2;
 
        if (!(flags & ALT_KEEP_CACHE)) {
                compiler->cache_arg = 0;
@@ -914,15 +922,13 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
        }
 
        if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
-                       return SLJIT_SUCCESS;
-               if (GET_FLAGS(op))
-                       flags |= UNUSED_DEST;
+               SLJIT_ASSERT(HAS_FLAGS(op));
+               flags |= UNUSED_DEST;
        }
        else if (FAST_IS_REG(dst)) {
                dst_r = dst;
                flags |= REG_DEST;
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
                        sugg_src2_r = dst_r;
        }
        else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
@@ -976,7 +982,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
        if (FAST_IS_REG(src2)) {
                src2_r = src2;
                flags |= REG2_SOURCE;
-               if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+               if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
                        dst_r = src2_r;
        }
        else if (src2 & SLJIT_IMM) {
@@ -987,7 +993,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
                        }
                        else {
                                src2_r = 0;
-                               if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) && (dst & SLJIT_MEM))
+                               if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))
                                        dst_r = 0;
                        }
                }
@@ -1029,10 +1035,10 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
 {
 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
-       sljit_si int_op = op & SLJIT_INT_OP;
+       sljit_s32 int_op = op & SLJIT_I32_OP;
 #endif
 
        CHECK_ERROR();
@@ -1044,20 +1050,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
                return push_inst(compiler, BREAK, UNMOVABLE_INS);
        case SLJIT_NOP:
                return push_inst(compiler, NOP, UNMOVABLE_INS);
-       case SLJIT_LUMUL:
-       case SLJIT_LSMUL:
+       case SLJIT_LMUL_UW:
+       case SLJIT_LMUL_SW:
 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
-               FAIL_IF(push_inst(compiler, (op == SLJIT_LUMUL ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+               FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
 #else
-               FAIL_IF(push_inst(compiler, (op == SLJIT_LUMUL ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+               FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | 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));
-       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);
+       case SLJIT_DIVMOD_UW:
+       case SLJIT_DIVMOD_SW:
+       case SLJIT_DIV_UW:
+       case SLJIT_DIV_SW:
+               SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, 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));
@@ -1065,28 +1071,51 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
 
 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
                if (int_op)
-                       FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+                       FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
                else
-                       FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+                       FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
 #else
-               FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+               FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
 #endif
 
                FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
-               return (op >= SLJIT_UDIVI) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
+               return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
        }
 
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
+        sljit_s32 src, sljit_sw srcw)
+{
+       if (!(src & OFFS_REG_MASK)) {
+               if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)
+                       return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);
+
+               FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
+               return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
+       }
+
+       srcw &= 0x3;
+
+       if (SLJIT_UNLIKELY(srcw != 0)) {
+               FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));
+               return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
+       }
+
+       return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
+}
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
 #      define flags 0
 #else
-       sljit_si flags = 0;
+       sljit_s32 flags = 0;
 #endif
 
        CHECK_ERROR();
@@ -1094,11 +1123,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        ADJUST_LOCAL_OFFSET(dst, dstw);
        ADJUST_LOCAL_OFFSET(src, srcw);
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+               if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+                       return emit_prefetch(compiler, src, srcw);
+#endif
+               return SLJIT_SUCCESS;
+       }
+
 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
-       if ((op & SLJIT_INT_OP) && GET_OPCODE(op) >= SLJIT_NOT) {
+       if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT) {
                flags |= INT_DATA | SIGNED_DATA;
                if (src & SLJIT_IMM)
-                       srcw = (sljit_si)srcw;
+                       srcw = (sljit_s32)srcw;
        }
 #endif
 
@@ -1107,61 +1144,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        case SLJIT_MOV_P:
                return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOV_UI:
+       case SLJIT_MOV_U32:
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-               return emit_op(compiler, SLJIT_MOV_UI, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+               return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 #else
-               return emit_op(compiler, SLJIT_MOV_UI, INT_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ui)srcw : srcw);
+               return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
 #endif
 
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_S32:
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-               return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+               return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 #else
-               return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_si)srcw : srcw);
+               return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw);
 #endif
 
-       case SLJIT_MOV_UB:
-               return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+       case SLJIT_MOV_U8:
+               return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
 
-       case SLJIT_MOV_SB:
-               return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+       case SLJIT_MOV_S8:
+               return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
 
-       case SLJIT_MOV_UH:
-               return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+       case SLJIT_MOV_U16:
+               return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
 
-       case SLJIT_MOV_SH:
-               return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+       case SLJIT_MOV_S16:
+               return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
 
        case SLJIT_MOVU:
        case SLJIT_MOVU_P:
                return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOVU_UI:
+       case SLJIT_MOVU_U32:
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-               return emit_op(compiler, SLJIT_MOV_UI, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+               return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 #else
-               return emit_op(compiler, SLJIT_MOV_UI, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ui)srcw : srcw);
+               return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
 #endif
 
-       case SLJIT_MOVU_SI:
+       case SLJIT_MOVU_S32:
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-               return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+               return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 #else
-               return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_si)srcw : srcw);
+               return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw);
 #endif
 
-       case SLJIT_MOVU_UB:
-               return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+       case SLJIT_MOVU_U8:
+               return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
 
-       case SLJIT_MOVU_SB:
-               return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+       case SLJIT_MOVU_S8:
+               return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
 
-       case SLJIT_MOVU_UH:
-               return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+       case SLJIT_MOVU_U16:
+               return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
 
-       case SLJIT_MOVU_SH:
-               return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+       case SLJIT_MOVU_S16:
+               return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
 
        case SLJIT_NOT:
                return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
@@ -1180,15 +1217,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
 #endif
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
 #      define flags 0
 #else
-       sljit_si flags = 0;
+       sljit_s32 flags = 0;
 #endif
 
        CHECK_ERROR();
@@ -1197,13 +1234,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        ADJUST_LOCAL_OFFSET(src1, src1w);
        ADJUST_LOCAL_OFFSET(src2, src2w);
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+               return SLJIT_SUCCESS;
+
 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
-       if (op & SLJIT_INT_OP) {
+       if (op & SLJIT_I32_OP) {
                flags |= INT_DATA | SIGNED_DATA;
                if (src1 & SLJIT_IMM)
-                       src1w = (sljit_si)src1w;
+                       src1w = (sljit_s32)src1w;
                if (src2 & SLJIT_IMM)
-                       src2w = (sljit_si)src2w;
+                       src2w = (sljit_s32)src2w;
        }
 #endif
 
@@ -1232,7 +1272,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
                        src2w &= 0x1f;
 #else
                if (src2 & SLJIT_IMM) {
-                       if (op & SLJIT_INT_OP)
+                       if (op & SLJIT_I32_OP)
                                src2w &= 0x1f;
                        else
                                src2w &= 0x3f;
@@ -1248,20 +1288,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
 #endif
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_register_index(reg));
        return reg_map[reg];
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
        return reg << 1;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1273,30 +1313,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
 /*  Floating point operators                                             */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
-       return SLJIT_IS_FPU_AVAILABLE;
-#elif defined(__GNUC__)
-       sljit_sw fir;
-       asm ("cfc1 %0, $0" : "=r"(fir));
-       return (fir >> 22) & 0x1;
-#else
-#error "FIR check is not implemented for this architecture"
-#endif
-}
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
+#define FMT(op) (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) << (21 - 8))
 
-#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 7))
-#define FMT(op) (((op & SLJIT_SINGLE_OP) ^ SLJIT_SINGLE_OP) << (21 - 8))
-
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
 #      define flags 0
 #else
-       sljit_si flags = (GET_OPCODE(op) == SLJIT_CONVW_FROMD) << 21;
+       sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64) << 21;
 #endif
 
        if (src & SLJIT_MEM) {
@@ -1308,9 +1335,6 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
 
        FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
 
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
-
        if (FAST_IS_REG(dst))
                return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
 
@@ -1322,17 +1346,17 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
 #endif
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
 #      define flags 0
 #else
-       sljit_si flags = (GET_OPCODE(op) == SLJIT_CONVD_FROMW) << 21;
+       sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) << 21;
 #endif
 
-       sljit_si dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
 
        if (FAST_IS_REG(src))
                FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
@@ -1342,14 +1366,14 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
        }
        else {
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-               if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
-                       srcw = (sljit_si)srcw;
+               if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+                       srcw = (sljit_s32)srcw;
 #endif
                FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
                FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
        }
 
-       FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | (((op & SLJIT_SINGLE_OP) ^ SLJIT_SINGLE_OP) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
+       FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
 
        if (dst & SLJIT_MEM)
                return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
@@ -1360,10 +1384,12 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
 #endif
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
+       sljit_ins inst;
+
        if (src1 & SLJIT_MEM) {
                FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
                src1 = TMP_FREG1;
@@ -1378,42 +1404,43 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler
        else
                src2 <<= 1;
 
-       /* src2 and src1 are swapped. */
-       if (op & SLJIT_SET_E) {
-               FAIL_IF(push_inst(compiler, C_UEQ_S | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS));
-               FAIL_IF(push_inst(compiler, CFC1 | TA(EQUAL_FLAG) | DA(FCSR_REG), EQUAL_FLAG));
-               FAIL_IF(push_inst(compiler, SRL | TA(EQUAL_FLAG) | DA(EQUAL_FLAG) | SH_IMM(23), EQUAL_FLAG));
-               FAIL_IF(push_inst(compiler, ANDI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG));
-       }
-       if (op & SLJIT_SET_S) {
-               /* Mixing the instructions for the two checks. */
-               FAIL_IF(push_inst(compiler, C_ULT_S | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS));
-               FAIL_IF(push_inst(compiler, CFC1 | TA(ULESS_FLAG) | DA(FCSR_REG), ULESS_FLAG));
-               FAIL_IF(push_inst(compiler, C_ULT_S | FMT(op) | FT(src1) | FS(src2), UNMOVABLE_INS));
-               FAIL_IF(push_inst(compiler, SRL | TA(ULESS_FLAG) | DA(ULESS_FLAG) | SH_IMM(23), ULESS_FLAG));
-               FAIL_IF(push_inst(compiler, ANDI | SA(ULESS_FLAG) | TA(ULESS_FLAG) | IMM(1), ULESS_FLAG));
-               FAIL_IF(push_inst(compiler, CFC1 | TA(UGREATER_FLAG) | DA(FCSR_REG), UGREATER_FLAG));
-               FAIL_IF(push_inst(compiler, SRL | TA(UGREATER_FLAG) | DA(UGREATER_FLAG) | SH_IMM(23), UGREATER_FLAG));
-               FAIL_IF(push_inst(compiler, ANDI | SA(UGREATER_FLAG) | TA(UGREATER_FLAG) | IMM(1), UGREATER_FLAG));
-       }
-       return push_inst(compiler, C_UN_S | FMT(op) | FT(src2) | FS(src1), FCSR_FCC);
+       switch (GET_FLAG_TYPE(op)) {
+       case SLJIT_EQUAL_F64:
+       case SLJIT_NOT_EQUAL_F64:
+               inst = C_UEQ_S;
+               break;
+       case SLJIT_LESS_F64:
+       case SLJIT_GREATER_EQUAL_F64:
+               inst = C_ULT_S;
+               break;
+       case SLJIT_GREATER_F64:
+       case SLJIT_LESS_EQUAL_F64:
+               inst = C_ULE_S;
+               break;
+       default:
+               SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED_F64 || GET_FLAG_TYPE(op) == SLJIT_ORDERED_F64);
+               inst = C_UN_S;
+               break;
+       }
+
+       return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR();
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
 
-       SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
+       SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
        SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
 
-       if (GET_OPCODE(op) == SLJIT_CONVD_FROMS)
-               op ^= SLJIT_SINGLE_OP;
+       if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
+               op ^= SLJIT_F32_OP;
 
        dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
 
@@ -1425,7 +1452,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
                src <<= 1;
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DMOV:
+       case SLJIT_MOV_F64:
                if (src != dst_r) {
                        if (dst_r != TMP_FREG1)
                                FAIL_IF(push_inst(compiler, MOV_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
@@ -1433,15 +1460,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
                                dst_r = src;
                }
                break;
-       case SLJIT_DNEG:
+       case SLJIT_NEG_F64:
                FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
                break;
-       case SLJIT_DABS:
+       case SLJIT_ABS_F64:
                FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
                break;
-       case SLJIT_CONVD_FROMS:
-               FAIL_IF(push_inst(compiler, CVT_S_S | ((op & SLJIT_SINGLE_OP) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
-               op ^= SLJIT_SINGLE_OP;
+       case SLJIT_CONV_F64_FROM_F32:
+               FAIL_IF(push_inst(compiler, CVT_S_S | ((op & SLJIT_F32_OP) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
+               op ^= SLJIT_F32_OP;
                break;
        }
 
@@ -1450,12 +1477,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si dst_r, flags = 0;
+       sljit_s32 dst_r, flags = 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1509,19 +1536,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
                src2 = TMP_FREG2;
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DADD:
+       case SLJIT_ADD_F64:
                FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
                break;
 
-       case SLJIT_DSUB:
+       case SLJIT_SUB_F64:
                FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
                break;
 
-       case SLJIT_DMUL:
+       case SLJIT_MUL_F64:
                FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
                break;
 
-       case SLJIT_DDIV:
+       case SLJIT_DIV_F64:
                FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
                break;
        }
@@ -1536,16 +1563,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
 /*  Other instructions                                                   */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       /* For UNUSED dst. Uncommon, but possible. */
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
-
        if (FAST_IS_REG(dst))
                return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst));
 
@@ -1553,7 +1576,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
        return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
@@ -1617,12 +1640,12 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
        flags = IS_BIT16_COND; \
        delay_check = FCSR_FCC;
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
        struct sljit_jump *jump;
        sljit_ins inst;
-       sljit_si flags = 0;
-       sljit_si delay_check = UNMOVABLE_INS;
+       sljit_s32 flags = 0;
+       sljit_s32 delay_check = UNMOVABLE_INS;
 
        CHECK_ERROR_PTR();
        CHECK_PTR(check_sljit_emit_jump(compiler, type));
@@ -1634,55 +1657,39 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
 
        switch (type) {
        case SLJIT_EQUAL:
-       case SLJIT_D_NOT_EQUAL:
                BR_NZ(EQUAL_FLAG);
                break;
        case SLJIT_NOT_EQUAL:
-       case SLJIT_D_EQUAL:
                BR_Z(EQUAL_FLAG);
                break;
        case SLJIT_LESS:
-       case SLJIT_D_LESS:
-               BR_Z(ULESS_FLAG);
-               break;
-       case SLJIT_GREATER_EQUAL:
-       case SLJIT_D_GREATER_EQUAL:
-               BR_NZ(ULESS_FLAG);
-               break;
        case SLJIT_GREATER:
-       case SLJIT_D_GREATER:
-               BR_Z(UGREATER_FLAG);
-               break;
-       case SLJIT_LESS_EQUAL:
-       case SLJIT_D_LESS_EQUAL:
-               BR_NZ(UGREATER_FLAG);
-               break;
        case SLJIT_SIG_LESS:
-               BR_Z(LESS_FLAG);
-               break;
-       case SLJIT_SIG_GREATER_EQUAL:
-               BR_NZ(LESS_FLAG);
-               break;
        case SLJIT_SIG_GREATER:
-               BR_Z(GREATER_FLAG);
-               break;
-       case SLJIT_SIG_LESS_EQUAL:
-               BR_NZ(GREATER_FLAG);
-               break;
        case SLJIT_OVERFLOW:
        case SLJIT_MUL_OVERFLOW:
-               BR_Z(OVERFLOW_FLAG);
+               BR_Z(OTHER_FLAG);
                break;
+       case SLJIT_GREATER_EQUAL:
+       case SLJIT_LESS_EQUAL:
+       case SLJIT_SIG_GREATER_EQUAL:
+       case SLJIT_SIG_LESS_EQUAL:
        case SLJIT_NOT_OVERFLOW:
        case SLJIT_MUL_NOT_OVERFLOW:
-               BR_NZ(OVERFLOW_FLAG);
-               break;
-       case SLJIT_D_UNORDERED:
-               BR_F();
+               BR_NZ(OTHER_FLAG);
                break;
-       case SLJIT_D_ORDERED:
+       case SLJIT_NOT_EQUAL_F64:
+       case SLJIT_GREATER_EQUAL_F64:
+       case SLJIT_GREATER_F64:
+       case SLJIT_ORDERED_F64:
                BR_T();
                break;
+       case SLJIT_EQUAL_F64:
+       case SLJIT_LESS_F64:
+       case SLJIT_LESS_EQUAL_F64:
+       case SLJIT_UNORDERED_F64:
+               BR_F();
+               break;
        default:
                /* Not conditional branch. */
                inst = 0;
@@ -1733,12 +1740,12 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
                        src2 = 0; \
        }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        struct sljit_jump *jump;
-       sljit_si flags;
+       sljit_s32 flags;
        sljit_ins inst;
 
        CHECK_ERROR_PTR();
@@ -1748,7 +1755,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
 
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
-       flags = ((type & SLJIT_INT_OP) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+       flags = ((type & SLJIT_I32_OP) ? INT_DATA : WORD_DATA) | LOAD_DATA;
        if (src1 & SLJIT_MEM) {
                PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
                src1 = TMP_REG1;
@@ -1854,86 +1861,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
 #undef RESOLVE_IMM1
 #undef RESOLVE_IMM2
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
-{
-       struct sljit_jump *jump;
-       sljit_ins inst;
-       sljit_si if_true;
-
-       CHECK_ERROR_PTR();
-       CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));
-
-       compiler->cache_arg = 0;
-       compiler->cache_argw = 0;
-
-       if (src1 & SLJIT_MEM) {
-               PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
-               src1 = TMP_FREG1;
-       }
-       else
-               src1 <<= 1;
-
-       if (src2 & SLJIT_MEM) {
-               PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
-               src2 = TMP_FREG2;
-       }
-       else
-               src2 <<= 1;
-
-       jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
-       PTR_FAIL_IF(!jump);
-       set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
-       jump->flags |= IS_BIT16_COND;
-
-       switch (type & 0xff) {
-       case SLJIT_D_EQUAL:
-               inst = C_UEQ_S;
-               if_true = 1;
-               break;
-       case SLJIT_D_NOT_EQUAL:
-               inst = C_UEQ_S;
-               if_true = 0;
-               break;
-       case SLJIT_D_LESS:
-               inst = C_ULT_S;
-               if_true = 1;
-               break;
-       case SLJIT_D_GREATER_EQUAL:
-               inst = C_ULT_S;
-               if_true = 0;
-               break;
-       case SLJIT_D_GREATER:
-               inst = C_ULE_S;
-               if_true = 0;
-               break;
-       case SLJIT_D_LESS_EQUAL:
-               inst = C_ULE_S;
-               if_true = 1;
-               break;
-       case SLJIT_D_UNORDERED:
-               inst = C_UN_S;
-               if_true = 1;
-               break;
-       default: /* Make compilers happy. */
-               SLJIT_ASSERT_STOP();
-       case SLJIT_D_ORDERED:
-               inst = C_UN_S;
-               if_true = 0;
-               break;
-       }
-
-       PTR_FAIL_IF(push_inst(compiler, inst | FMT(type) | FT(src2) | FS(src1), UNMOVABLE_INS));
-       /* Intentionally the other opcode. */
-       PTR_FAIL_IF(push_inst(compiler, (if_true ? BC1F : BC1T) | JUMP_LENGTH, UNMOVABLE_INS));
-       PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
-       PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
-       jump->addr = compiler->size;
-       PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
-       return jump;
-}
-
 #undef JUMP_LENGTH
 #undef BR_Z
 #undef BR_NZ
@@ -1943,9 +1870,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
 #undef FLOAT_DATA
 #undef FMT
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si src_r = TMP_REG2;
+       sljit_s32 src_r = TMP_REG2;
        struct sljit_jump *jump = NULL;
 
        CHECK_ERROR();
@@ -2001,124 +1928,169 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type)
 {
-       sljit_si sugg_dst_ar, dst_ar;
-       sljit_si flags = GET_ALL_FLAGS(op);
+       sljit_s32 src_ar, dst_ar;
+       sljit_s32 saved_op = op;
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-#      define mem_type WORD_DATA
+       sljit_s32 mem_type = WORD_DATA;
 #else
-       sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
+       sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
 #endif
 
        CHECK_ERROR();
-       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
-
        op = GET_OPCODE(op);
 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
-       if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI)
+       if (op == SLJIT_MOV_S32)
                mem_type = INT_DATA | SIGNED_DATA;
 #endif
-       sugg_dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
+       dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
 
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
-       if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
-               ADJUST_LOCAL_OFFSET(src, srcw);
-               FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
-               src = TMP_REG1;
-               srcw = 0;
-       }
+
+       if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+               FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));
 
        switch (type & 0xff) {
        case SLJIT_EQUAL:
        case SLJIT_NOT_EQUAL:
-               FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
-               dst_ar = sugg_dst_ar;
-               break;
-       case SLJIT_LESS:
-       case SLJIT_GREATER_EQUAL:
-       case SLJIT_D_LESS:
-       case SLJIT_D_GREATER_EQUAL:
-               dst_ar = ULESS_FLAG;
-               break;
-       case SLJIT_GREATER:
-       case SLJIT_LESS_EQUAL:
-       case SLJIT_D_GREATER:
-       case SLJIT_D_LESS_EQUAL:
-               dst_ar = UGREATER_FLAG;
-               break;
-       case SLJIT_SIG_LESS:
-       case SLJIT_SIG_GREATER_EQUAL:
-               dst_ar = LESS_FLAG;
-               break;
-       case SLJIT_SIG_GREATER:
-       case SLJIT_SIG_LESS_EQUAL:
-               dst_ar = GREATER_FLAG;
-               break;
-       case SLJIT_OVERFLOW:
-       case SLJIT_NOT_OVERFLOW:
-               dst_ar = OVERFLOW_FLAG;
+               FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
+               src_ar = dst_ar;
                break;
        case SLJIT_MUL_OVERFLOW:
        case SLJIT_MUL_NOT_OVERFLOW:
-               FAIL_IF(push_inst(compiler, SLTIU | SA(OVERFLOW_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
-               dst_ar = sugg_dst_ar;
+               FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
+               src_ar = dst_ar;
                type ^= 0x1; /* Flip type bit for the XORI below. */
                break;
-       case SLJIT_D_EQUAL:
-       case SLJIT_D_NOT_EQUAL:
-               dst_ar = EQUAL_FLAG;
-               break;
-
-       case SLJIT_D_UNORDERED:
-       case SLJIT_D_ORDERED:
-               FAIL_IF(push_inst(compiler, CFC1 | TA(sugg_dst_ar) | DA(FCSR_REG), sugg_dst_ar));
-               FAIL_IF(push_inst(compiler, SRL | TA(sugg_dst_ar) | DA(sugg_dst_ar) | SH_IMM(23), sugg_dst_ar));
-               FAIL_IF(push_inst(compiler, ANDI | SA(sugg_dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
-               dst_ar = sugg_dst_ar;
+       case SLJIT_GREATER_F64:
+       case SLJIT_LESS_EQUAL_F64:
+               type ^= 0x1; /* Flip type bit for the XORI below. */
+       case SLJIT_EQUAL_F64:
+       case SLJIT_NOT_EQUAL_F64:
+       case SLJIT_LESS_F64:
+       case SLJIT_GREATER_EQUAL_F64:
+       case SLJIT_UNORDERED_F64:
+       case SLJIT_ORDERED_F64:
+               FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
+               FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
+               FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
+               src_ar = dst_ar;
                break;
 
        default:
-               SLJIT_ASSERT_STOP();
-               dst_ar = sugg_dst_ar;
+               src_ar = OTHER_FLAG;
                break;
        }
 
        if (type & 0x1) {
-               FAIL_IF(push_inst(compiler, XORI | SA(dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
-               dst_ar = sugg_dst_ar;
+               FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));
+               src_ar = dst_ar;
        }
 
-       if (op >= SLJIT_ADD) {
-               if (DR(TMP_REG2) != dst_ar)
-                       FAIL_IF(push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
-               return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
+       if (op < SLJIT_ADD) {
+               if (dst & SLJIT_MEM)
+                       return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);
+
+               if (src_ar != dst_ar)
+                       return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);
+               return SLJIT_SUCCESS;
        }
 
+       /* OTHER_FLAG cannot be specified as src2 argument at the moment. */
+       if (DR(TMP_REG2) != src_ar)
+               FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
+
+       mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;
+
        if (dst & SLJIT_MEM)
-               return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw);
+               return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+       return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);
+}
 
-       if (sugg_dst_ar != dst_ar)
-               return push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | DA(sugg_dst_ar), sugg_dst_ar);
-       return SLJIT_SUCCESS;
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+       sljit_ins ins;
+#endif
 
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-#      undef mem_type
+       CHECK_ERROR();
+       CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+
+       if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+               if (dst_reg & SLJIT_I32_OP)
+                       srcw = (sljit_s32)srcw;
+#endif
+               FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
+               src = TMP_REG1;
+               srcw = 0;
+       }
+
+       dst_reg &= ~SLJIT_I32_OP;
+
+       switch (type & 0xff) {
+       case SLJIT_EQUAL:
+               ins = MOVZ | TA(EQUAL_FLAG);
+               break;
+       case SLJIT_NOT_EQUAL:
+               ins = MOVN | TA(EQUAL_FLAG);
+               break;
+       case SLJIT_LESS:
+       case SLJIT_GREATER:
+       case SLJIT_SIG_LESS:
+       case SLJIT_SIG_GREATER:
+       case SLJIT_OVERFLOW:
+       case SLJIT_MUL_OVERFLOW:
+               ins = MOVN | TA(OTHER_FLAG);
+               break;
+       case SLJIT_GREATER_EQUAL:
+       case SLJIT_LESS_EQUAL:
+       case SLJIT_SIG_GREATER_EQUAL:
+       case SLJIT_SIG_LESS_EQUAL:
+       case SLJIT_NOT_OVERFLOW:
+       case SLJIT_MUL_NOT_OVERFLOW:
+               ins = MOVZ | TA(OTHER_FLAG);
+               break;
+       case SLJIT_EQUAL_F64:
+       case SLJIT_LESS_F64:
+       case SLJIT_LESS_EQUAL_F64:
+       case SLJIT_UNORDERED_F64:
+               ins = MOVT;
+               break;
+       case SLJIT_NOT_EQUAL_F64:
+       case SLJIT_GREATER_EQUAL_F64:
+       case SLJIT_GREATER_F64:
+       case SLJIT_ORDERED_F64:
+               ins = MOVF;
+               break;
+       default:
+               ins = MOVZ | TA(OTHER_FLAG);
+               SLJIT_UNREACHABLE();
+               break;
+       }
+
+       return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg));
+
+#else
+       return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
 #endif
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+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_si reg;
+       sljit_s32 reg;
 
        CHECK_ERROR_PTR();
        CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -2128,7 +2100,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
        PTR_FAIL_IF(!const_);
        set_const(const_, compiler);
 
-       reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+       reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
 
        PTR_FAIL_IF(emit_const(compiler, reg, init_value));
 
index b14b75ceb51c50487f4855ea75b59e047dc9bbb6..fc185f784754c917cd2454c87e6c910fca6d1cce 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -26,7 +26,7 @@
 
 /* ppc 32-bit arch dependent functions. */
 
-static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
 {
        if (imm <= SIMM_MAX && imm >= SIMM_MIN)
                return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
@@ -41,39 +41,39 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
 #define INS_CLEAR_LEFT(dst, src, from) \
        (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))
 
-static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
-       sljit_si dst, sljit_si src1, sljit_si src2)
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+       sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
 {
        switch (op) {
        case SLJIT_MOV:
-       case SLJIT_MOV_UI:
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOV_S32:
        case SLJIT_MOV_P:
                SLJIT_ASSERT(src1 == TMP_REG1);
                if (dst != src2)
                        return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UB:
-       case SLJIT_MOV_SB:
+       case SLJIT_MOV_U8:
+       case SLJIT_MOV_S8:
                SLJIT_ASSERT(src1 == TMP_REG1);
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SB)
+                       if (op == SLJIT_MOV_S8)
                                return push_inst(compiler, EXTSB | S(src2) | A(dst));
                        return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
                }
-               else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
+               else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
                        return push_inst(compiler, EXTSB | S(src2) | A(dst));
                else {
                        SLJIT_ASSERT(dst == src2);
                }
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UH:
-       case SLJIT_MOV_SH:
+       case SLJIT_MOV_U16:
+       case SLJIT_MOV_S16:
                SLJIT_ASSERT(src1 == TMP_REG1);
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SH)
+                       if (op == SLJIT_MOV_S16)
                                return push_inst(compiler, EXTSH | S(src2) | A(dst));
                        return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
                }
@@ -88,77 +88,86 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
 
        case SLJIT_NEG:
                SLJIT_ASSERT(src1 == TMP_REG1);
-               return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
+               /* Setting XER SO is not enough, CR SO is also needed. */
+               return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
 
        case SLJIT_CLZ:
                SLJIT_ASSERT(src1 == TMP_REG1);
-               return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
+               return push_inst(compiler, CNTLZW | S(src2) | A(dst));
 
        case SLJIT_ADD:
                if (flags & ALT_FORM1) {
-                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
-                       SLJIT_ASSERT(src2 == TMP_REG2);
-                       return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
+                       /* Setting XER SO is not enough, CR SO is also needed. */
+                       return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
                }
+
                if (flags & ALT_FORM2) {
                        /* Flags does not set: BIN_IMM_EXTS unnecessary. */
                        SLJIT_ASSERT(src2 == TMP_REG2);
-                       return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+                       if (flags & ALT_FORM3)
+                               return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+                       if (flags & ALT_FORM4) {
+                               FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));
+                               src1 = dst;
+                       }
+
+                       return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));
                }
                if (flags & ALT_FORM3) {
                        SLJIT_ASSERT(src2 == TMP_REG2);
                        return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
                }
-               if (flags & ALT_FORM4) {
-                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
-                       FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
-                       return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
-               }
                if (!(flags & ALT_SET_FLAGS))
                        return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
-               return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+               if (flags & ALT_FORM4)
+                       return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+               return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
 
        case SLJIT_ADDC:
-               if (flags & ALT_FORM1) {
-                       FAIL_IF(push_inst(compiler, MFXER | D(0)));
-                       FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
-                       return push_inst(compiler, MTXER | S(0));
-               }
                return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
 
        case SLJIT_SUB:
                if (flags & ALT_FORM1) {
+                       if (flags & ALT_FORM2) {
+                               FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
+                               if (!(flags & ALT_FORM3))
+                                       return SLJIT_SUCCESS;
+                               return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
+                       }
+                       FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
+                       if (!(flags & ALT_FORM3))
+                               return SLJIT_SUCCESS;
+                       return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+               }
+
+               if (flags & ALT_FORM2) {
+                       /* Setting XER SO is not enough, CR SO is also needed. */
+                       return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+               }
+
+               if (flags & ALT_FORM3) {
                        /* Flags does not set: BIN_IMM_EXTS unnecessary. */
                        SLJIT_ASSERT(src2 == TMP_REG2);
                        return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
                }
-               if (flags & (ALT_FORM2 | ALT_FORM3)) {
-                       SLJIT_ASSERT(src2 == TMP_REG2);
-                       if (flags & ALT_FORM2)
-                               FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
-                       if (flags & ALT_FORM3)
-                               return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm);
-                       return SLJIT_SUCCESS;
-               }
-               if (flags & (ALT_FORM4 | ALT_FORM5)) {
-                       if (flags & ALT_FORM4)
-                               FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
-                       if (flags & ALT_FORM5)
-                               FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
-                       return SLJIT_SUCCESS;
+
+               if (flags & ALT_FORM4) {
+                       if (flags & ALT_FORM5) {
+                               SLJIT_ASSERT(src2 == TMP_REG2);
+                               return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm);
+                       }
+                       return push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2));
                }
+
                if (!(flags & ALT_SET_FLAGS))
                        return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
-               if (flags & ALT_FORM6)
-                       FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
-               return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+               if (flags & ALT_FORM5)
+                       return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+               return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
 
        case SLJIT_SUBC:
-               if (flags & ALT_FORM1) {
-                       FAIL_IF(push_inst(compiler, MFXER | D(0)));
-                       FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
-                       return push_inst(compiler, MTXER | S(0));
-               }
                return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
 
        case SLJIT_MUL:
@@ -166,7 +175,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                        SLJIT_ASSERT(src2 == TMP_REG2);
                        return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
                }
-               return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
+               return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
 
        case SLJIT_AND:
                if (flags & ALT_FORM1) {
@@ -228,42 +237,40 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
 
        case SLJIT_ASHR:
-               if (flags & ALT_FORM3)
-                       FAIL_IF(push_inst(compiler, MFXER | D(0)));
                if (flags & ALT_FORM1) {
                        SLJIT_ASSERT(src2 == TMP_REG2);
                        compiler->imm &= 0x1f;
-                       FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
+                       return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
                }
-               else
-                       FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)));
-               return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
+               return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
        }
 
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
 {
        FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
        return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+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;
+       sljit_ins *inst = (sljit_ins *)addr;
 
-       inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
-       inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
+       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);
        SLJIT_CACHE_FLUSH(inst, inst + 2);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
-       sljit_ins *inst = (sljit_ins*)addr;
+       sljit_ins *inst = (sljit_ins *)addr;
 
        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);
        SLJIT_CACHE_FLUSH(inst, inst + 2);
 }
index 182ac7b3da55b825922b5aae5b50d880cbbedc97..5366c30d90c30b20c50eeb1539eba7e39a78f680 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -41,7 +41,7 @@
 #define PUSH_RLDICR(reg, shift) \
        push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
 
-static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
 {
        sljit_uw tmp;
        sljit_uw shift;
@@ -145,8 +145,8 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
                src1 = TMP_REG1; \
        }
 
-static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
-       sljit_si dst, sljit_si src1, sljit_si src2)
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+       sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
 {
        switch (op) {
        case SLJIT_MOV:
@@ -156,11 +156,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                        return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UI:
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOV_S32:
                SLJIT_ASSERT(src1 == TMP_REG1);
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SI)
+                       if (op == SLJIT_MOV_S32)
                                return push_inst(compiler, EXTSW | S(src2) | A(dst));
                        return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
                }
@@ -169,26 +169,26 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                }
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UB:
-       case SLJIT_MOV_SB:
+       case SLJIT_MOV_U8:
+       case SLJIT_MOV_S8:
                SLJIT_ASSERT(src1 == TMP_REG1);
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SB)
+                       if (op == SLJIT_MOV_S8)
                                return push_inst(compiler, EXTSB | S(src2) | A(dst));
                        return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
                }
-               else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
+               else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
                        return push_inst(compiler, EXTSB | S(src2) | A(dst));
                else {
                        SLJIT_ASSERT(dst == src2);
                }
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UH:
-       case SLJIT_MOV_SH:
+       case SLJIT_MOV_U16:
+       case SLJIT_MOV_S16:
                SLJIT_ASSERT(src1 == TMP_REG1);
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SH)
+                       if (op == SLJIT_MOV_S16)
                                return push_inst(compiler, EXTSH | S(src2) | A(dst));
                        return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
                }
@@ -204,84 +204,118 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
 
        case SLJIT_NEG:
                SLJIT_ASSERT(src1 == TMP_REG1);
+
+               if ((flags & (ALT_FORM1 | ALT_SIGN_EXT)) == (ALT_FORM1 | ALT_SIGN_EXT)) {
+                       FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
+                       FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(TMP_REG2)));
+                       return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
+               }
+
                UN_EXTS();
-               return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
+               /* Setting XER SO is not enough, CR SO is also needed. */
+               return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
 
        case SLJIT_CLZ:
                SLJIT_ASSERT(src1 == TMP_REG1);
                if (flags & ALT_FORM1)
-                       return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
-               return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
+                       return push_inst(compiler, CNTLZW | S(src2) | A(dst));
+               return push_inst(compiler, CNTLZD | S(src2) | A(dst));
 
        case SLJIT_ADD:
                if (flags & ALT_FORM1) {
-                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
-                       SLJIT_ASSERT(src2 == TMP_REG2);
-                       return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
+                       if (flags & ALT_SIGN_EXT) {
+                               FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
+                               src1 = TMP_REG1;
+                               FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
+                               src2 = TMP_REG2;
+                       }
+                       /* Setting XER SO is not enough, CR SO is also needed. */
+                       FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));
+                       if (flags & ALT_SIGN_EXT)
+                               return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
+                       return SLJIT_SUCCESS;
                }
+
                if (flags & ALT_FORM2) {
                        /* Flags does not set: BIN_IMM_EXTS unnecessary. */
                        SLJIT_ASSERT(src2 == TMP_REG2);
-                       return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+                       if (flags & ALT_FORM3)
+                               return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+                       if (flags & ALT_FORM4) {
+                               FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));
+                               src1 = dst;
+                       }
+
+                       return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));
                }
                if (flags & ALT_FORM3) {
                        SLJIT_ASSERT(src2 == TMP_REG2);
                        BIN_IMM_EXTS();
                        return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
                }
-               if (flags & ALT_FORM4) {
-                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
-                       FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
-                       return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
-               }
                if (!(flags & ALT_SET_FLAGS))
                        return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
                BIN_EXTS();
-               return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+               if (flags & ALT_FORM4)
+                       return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+               return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
 
        case SLJIT_ADDC:
-               if (flags & ALT_FORM1) {
-                       FAIL_IF(push_inst(compiler, MFXER | D(0)));
-                       FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
-                       return push_inst(compiler, MTXER | S(0));
-               }
                BIN_EXTS();
                return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
 
        case SLJIT_SUB:
                if (flags & ALT_FORM1) {
+                       if (flags & ALT_FORM2) {
+                               FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
+                               if (!(flags & ALT_FORM3))
+                                       return SLJIT_SUCCESS;
+                               return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
+                       }
+                       FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
+                       if (!(flags & ALT_FORM3))
+                               return SLJIT_SUCCESS;
+                       return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+               }
+
+               if (flags & ALT_FORM2) {
+                       if (flags & ALT_SIGN_EXT) {
+                               FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
+                               src1 = TMP_REG1;
+                               FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
+                               src2 = TMP_REG2;
+                       }
+                       /* Setting XER SO is not enough, CR SO is also needed. */
+                       FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
+                       if (flags & ALT_SIGN_EXT)
+                               return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
+                       return SLJIT_SUCCESS;
+               }
+
+               if (flags & ALT_FORM3) {
                        /* Flags does not set: BIN_IMM_EXTS unnecessary. */
                        SLJIT_ASSERT(src2 == TMP_REG2);
                        return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
                }
-               if (flags & (ALT_FORM2 | ALT_FORM3)) {
-                       SLJIT_ASSERT(src2 == TMP_REG2);
-                       if (flags & ALT_FORM2)
-                               FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
-                       if (flags & ALT_FORM3)
-                               return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
-                       return SLJIT_SUCCESS;
-               }
-               if (flags & (ALT_FORM4 | ALT_FORM5)) {
-                       if (flags & ALT_FORM4)
-                               FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
-                       if (flags & ALT_FORM5)
-                               return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
-                       return SLJIT_SUCCESS;
+
+               if (flags & ALT_FORM4) {
+                       if (flags & ALT_FORM5) {
+                               SLJIT_ASSERT(src2 == TMP_REG2);
+                               return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
+                       }
+                       return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
                }
+
                if (!(flags & ALT_SET_FLAGS))
                        return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
                BIN_EXTS();
-               if (flags & ALT_FORM6)
-                       FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
-               return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+               if (flags & ALT_FORM5)
+                       return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+               return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
 
        case SLJIT_SUBC:
-               if (flags & ALT_FORM1) {
-                       FAIL_IF(push_inst(compiler, MFXER | D(0)));
-                       FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
-                       return push_inst(compiler, MTXER | S(0));
-               }
                BIN_EXTS();
                return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
 
@@ -292,8 +326,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                }
                BIN_EXTS();
                if (flags & ALT_FORM2)
-                       return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
-               return push_inst(compiler, MULLD | OERC(flags) | D(dst) | A(src2) | B(src1));
+                       return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
+               return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
 
        case SLJIT_AND:
                if (flags & ALT_FORM1) {
@@ -345,10 +379,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                                compiler->imm &= 0x1f;
                                return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
                        }
-                       else {
-                               compiler->imm &= 0x3f;
-                               return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
-                       }
+                       compiler->imm &= 0x3f;
+                       return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
                }
                return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
 
@@ -359,37 +391,29 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                                compiler->imm &= 0x1f;
                                return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
                        }
-                       else {
-                               compiler->imm &= 0x3f;
-                               return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
-                       }
+                       compiler->imm &= 0x3f;
+                       return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
                }
                return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
 
        case SLJIT_ASHR:
-               if (flags & ALT_FORM3)
-                       FAIL_IF(push_inst(compiler, MFXER | D(0)));
                if (flags & ALT_FORM1) {
                        SLJIT_ASSERT(src2 == TMP_REG2);
                        if (flags & ALT_FORM2) {
                                compiler->imm &= 0x1f;
-                               FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
-                       }
-                       else {
-                               compiler->imm &= 0x3f;
-                               FAIL_IF(push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)));
+                               return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
                        }
+                       compiler->imm &= 0x3f;
+                       return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));
                }
-               else
-                       FAIL_IF(push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)));
-               return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
+               return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));
        }
 
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
 {
        FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
        FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
@@ -398,18 +422,19 @@ static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_s
        return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+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;
 
-       inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
-       inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
-       inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
-       inst[4] = (inst[4] & 0xffff0000) | (new_addr & 0xffff);
+       inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
+       inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
+       inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
+       inst[4] = (inst[4] & 0xffff0000) | (new_target & 0xffff);
+       inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
        SLJIT_CACHE_FLUSH(inst, inst + 5);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
        sljit_ins *inst = (sljit_ins*)addr;
 
@@ -417,5 +442,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
        inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
        inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
        inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff);
+       inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
        SLJIT_CACHE_FLUSH(inst, inst + 5);
 }
index b6a043f4e48f24edf8d2495e29fb760d4623e96b..775c708f2f95a21ec9247fbfd6a215e4a1aeac34 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
 {
        return "PowerPC" SLJIT_CPUINFO;
 }
 
 /* Length of an instruction word.
    Both for ppc-32 and ppc-64. */
-typedef sljit_ui sljit_ins;
+typedef sljit_u32 sljit_ins;
 
 #if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \
        || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
@@ -46,6 +46,8 @@ typedef sljit_ui sljit_ins;
 #define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
 #endif
 
+#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)
+
 static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
 {
 #ifdef _AIX
@@ -87,6 +89,8 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
 #endif /* _AIX */
 }
 
+#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */
+
 #define TMP_REG1       (SLJIT_NUMBER_OF_REGISTERS + 2)
 #define TMP_REG2       (SLJIT_NUMBER_OF_REGISTERS + 3)
 #define TMP_REG3       (SLJIT_NUMBER_OF_REGISTERS + 4)
@@ -101,7 +105,7 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
 #define TMP_FREG1      (0)
 #define TMP_FREG2      (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
 
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
        0, 3, 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 8, 9, 10, 31, 12
 };
 
@@ -123,9 +127,9 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
 
 /* Instruction bit sections.
    OE and Rc flag (see ALT_SET_FLAGS). */
-#define OERC(flags)    (((flags & ALT_SET_FLAGS) >> 10) | (flags & ALT_SET_FLAGS))
+#define OE(flags)      ((flags) & ALT_SET_FLAGS)
 /* Rc flag (see ALT_SET_FLAGS). */
-#define RC(flags)      ((flags & ALT_SET_FLAGS) >> 10)
+#define RC(flags)      (((flags) & ALT_SET_FLAGS) >> 10)
 #define HI(opcode)     ((opcode) << 26)
 #define LO(opcode)     ((opcode) << 1)
 
@@ -150,6 +154,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
 #define CMPL           (HI(31) | LO(32))
 #define CMPLI          (HI(10))
 #define CROR           (HI(19) | LO(449))
+#define DCBT           (HI(31) | LO(278))
 #define DIVD           (HI(31) | LO(489))
 #define DIVDU          (HI(31) | LO(457))
 #define DIVW           (HI(31) | LO(491))
@@ -236,7 +241,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct
 }
 #endif
 
-static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
 {
        sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
        FAIL_IF(!ptr);
@@ -245,7 +250,7 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_s32 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;
@@ -263,7 +268,7 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_ins
                target_addr = jump->u.target;
        else {
                SLJIT_ASSERT(jump->flags & JUMP_LABEL);
-               target_addr = (sljit_uw)(code + jump->u.label->size);
+               target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
        }
 
 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
@@ -271,7 +276,7 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_ins
                goto keep_address;
 #endif
 
-       diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr)) & ~0x3l;
+       diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;
 
        extra_jump_flags = 0;
        if (jump->flags & IS_COND) {
@@ -292,6 +297,7 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_ins
                jump->flags |= PATCH_B | extra_jump_flags;
                return 1;
        }
+
        if (target_addr <= 0x03ffffff) {
                jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;
                return 1;
@@ -305,6 +311,7 @@ keep_address:
                jump->flags |= PATCH_ABS32;
                return 1;
        }
+
        if (target_addr <= 0x7fffffffffffl) {
                jump->flags |= PATCH_ABS48;
                return 1;
@@ -322,6 +329,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        sljit_ins *buf_ptr;
        sljit_ins *buf_end;
        sljit_uw word_count;
+       sljit_sw executable_offset;
        sljit_uw addr;
 
        struct sljit_label *label;
@@ -345,9 +353,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
        code_ptr = code;
        word_count = 0;
+       executable_offset = SLJIT_EXEC_OFFSET(code);
+
        label = compiler->labels;
        jump = compiler->jumps;
        const_ = compiler->consts;
+
        do {
                buf_ptr = (sljit_ins*)buf->memory;
                buf_end = buf_ptr + (buf->used_size >> 2);
@@ -359,7 +370,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                        /* These structures are ordered by their address. */
                        if (label && label->size == word_count) {
                                /* Just recording the address. */
-                               label->addr = (sljit_uw)code_ptr;
+                               label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
                                label->size = code_ptr - code;
                                label = label->next;
                        }
@@ -369,7 +380,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 #else
                                jump->addr = (sljit_uw)(code_ptr - 6);
 #endif
-                               if (detect_jump_type(jump, code_ptr, code)) {
+                               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;
@@ -416,7 +427,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        } while (buf);
 
        if (label && label->size == word_count) {
-               label->addr = (sljit_uw)code_ptr;
+               label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
                label->size = code_ptr - code;
                label = label->next;
        }
@@ -434,11 +445,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        while (jump) {
                do {
                        addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
-                       buf_ptr = (sljit_ins*)jump->addr;
+                       buf_ptr = (sljit_ins *)jump->addr;
+
                        if (jump->flags & PATCH_B) {
                                if (jump->flags & IS_COND) {
                                        if (!(jump->flags & PATCH_ABS_B)) {
-                                               addr = addr - jump->addr;
+                                               addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
                                                SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
                                                *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
                                        }
@@ -449,7 +461,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                                }
                                else {
                                        if (!(jump->flags & PATCH_ABS_B)) {
-                                               addr = addr - jump->addr;
+                                               addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
                                                SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
                                                *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
                                        }
@@ -460,6 +472,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                                }
                                break;
                        }
+
                        /* Set the fields of immediate loads. */
 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
                        buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
@@ -488,22 +501,48 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        }
 
        compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_offset = executable_offset;
        compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
-       SLJIT_CACHE_FLUSH(code, code_ptr);
+
+       code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
 
 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
        if (((sljit_sw)code_ptr) & 0x4)
                code_ptr++;
+#endif
        sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
+#endif
+
+       code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+       SLJIT_CACHE_FLUSH(code, code_ptr);
+
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
        return code_ptr;
 #else
-       sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
-       return code_ptr;
+       return code;
 #endif
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+       switch (feature_type) {
+       case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+               return SLJIT_IS_FPU_AVAILABLE;
 #else
-       return code;
+               /* Available by default. */
+               return 1;
 #endif
+
+       case SLJIT_HAS_PRE_UPDATE:
+       case SLJIT_HAS_CLZ:
+               return 1;
+
+       default:
+               return 0;
+       }
 }
 
 /* --------------------------------------------------------------------- */
@@ -540,7 +579,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 #define ALT_FORM3      0x040000
 #define ALT_FORM4      0x080000
 #define ALT_FORM5      0x100000
-#define ALT_FORM6      0x200000
 
 /* Source and destination is register. */
 #define REG_DEST       0x000001
@@ -555,7 +593,7 @@ ALT_SIGN_EXT                0x000200
 ALT_SET_FLAGS          0x000400
 ALT_FORM1              0x010000
 ...
-ALT_FORM6              0x200000 */
+ALT_FORM5              0x100000 */
 
 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
 #include "sljitNativePPC_32.c"
@@ -571,32 +609,32 @@ ALT_FORM6         0x200000 */
 #define STACK_LOAD     LD
 #endif
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
-       sljit_si i, tmp, offs;
+       sljit_s32 i, tmp, offs;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
        set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
 
        FAIL_IF(push_inst(compiler, MFLR | D(0)));
-       offs = -(sljit_si)(sizeof(sljit_sw));
+       offs = -(sljit_s32)(sizeof(sljit_sw));
        FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
 
        tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
        for (i = SLJIT_S0; i >= tmp; i--) {
-               offs -= (sljit_si)(sizeof(sljit_sw));
+               offs -= (sljit_s32)(sizeof(sljit_sw));
                FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
        }
 
        for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
-               offs -= (sljit_si)(sizeof(sljit_sw));
+               offs -= (sljit_s32)(sizeof(sljit_sw));
                FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
        }
 
-       SLJIT_ASSERT(offs == -(sljit_si)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));
+       SLJIT_ASSERT(offs == -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));
 
 #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
        FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
@@ -635,9 +673,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
        CHECK_ERROR();
        CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -648,9 +686,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si i, tmp, offs;
+       sljit_s32 i, tmp, offs;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_return(compiler, op, src, srcw));
@@ -670,18 +708,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
        FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
 #endif
 
-       offs = -(sljit_si)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
+       offs = -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
 
        tmp = compiler->scratches;
        for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
                FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
-               offs += (sljit_si)(sizeof(sljit_sw));
+               offs += (sljit_s32)(sizeof(sljit_sw));
        }
 
        tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
        for (i = tmp; i <= SLJIT_S0; i++) {
                FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
-               offs += (sljit_si)(sizeof(sljit_sw));
+               offs += (sljit_s32)(sizeof(sljit_sw));
        }
 
        FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
@@ -722,7 +760,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
        (((inst) & ~(INT_ALIGNED | UPDATE_REQ)) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
 #endif
 
-static SLJIT_CONST sljit_ins data_transfer_insts[64 + 8] = {
+static const sljit_ins data_transfer_insts[64 + 8] = {
 
 /* -------- Unsigned -------- */
 
@@ -841,12 +879,12 @@ static SLJIT_CONST sljit_ins data_transfer_insts[64 + 8] = {
 #undef ARCH_32_64
 
 /* Simple cases, (no caching is required). */
-static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
 {
        sljit_ins inst;
 
        /* Should work when (arg & REG_MASK) == 0. */
-       SLJIT_COMPILE_ASSERT(A(0) == 0, a0_must_be_0);
+       SLJIT_ASSERT(A(0) == 0);
        SLJIT_ASSERT(arg & SLJIT_MEM);
 
        if (arg & OFFS_REG_MASK) {
@@ -891,7 +929,7 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_fl
 /* See getput_arg below.
    Note: can_cache is called only for binary operators. Those operator always
    uses word arguments without write back. */
-static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
        sljit_sw high_short, next_high_short;
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
@@ -940,9 +978,9 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
 #endif
 
 /* Emit the necessary instructions. See can_cache above. */
-static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
-       sljit_si tmp_r;
+       sljit_s32 tmp_r;
        sljit_ins inst;
        sljit_sw high_short, next_high_short;
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
@@ -992,7 +1030,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
 #endif
 
                arg &= REG_MASK;
-               high_short = (sljit_si)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
+               high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
                /* The getput_arg_fast should handle this otherwise. */
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
                SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);
@@ -1001,16 +1039,12 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
 #endif
 
                if (inp_flags & WRITE_BACK) {
-                       if (arg == reg) {
-                               FAIL_IF(push_inst(compiler, OR | S(reg) | A(tmp_r) | B(reg)));
-                               reg = tmp_r;
-                       }
                        tmp_r = arg;
                        FAIL_IF(push_inst(compiler, ADDIS | D(arg) | A(arg) | IMM(high_short >> 16)));
                }
                else if (compiler->cache_arg != (SLJIT_MEM | arg) || high_short != compiler->cache_argw) {
                        if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK)) {
-                               next_high_short = (sljit_si)(next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
+                               next_high_short = (sljit_s32)(next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
                                if (high_short == next_high_short) {
                                        compiler->cache_arg = SLJIT_MEM | arg;
                                        compiler->cache_argw = high_short;
@@ -1107,27 +1141,27 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
 #endif
 }
 
-static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
 {
        if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
                return compiler->error;
        return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
 }
 
-static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si input_flags,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        /* arg1 goes to TMP_REG1 or src reg
           arg2 goes to TMP_REG2, imm or src reg
           TMP_REG3 can be used for caching
           result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
-       sljit_si dst_r;
-       sljit_si src1_r;
-       sljit_si src2_r;
-       sljit_si sugg_src2_r = TMP_REG2;
-       sljit_si flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS);
+       sljit_s32 dst_r;
+       sljit_s32 src1_r;
+       sljit_s32 src2_r;
+       sljit_s32 sugg_src2_r = TMP_REG2;
+       sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
 
        if (!(input_flags & ALT_KEEP_CACHE)) {
                compiler->cache_arg = 0;
@@ -1136,14 +1170,12 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
 
        /* Destination check. */
        if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
-                       return SLJIT_SUCCESS;
                dst_r = TMP_REG2;
        }
        else if (FAST_IS_REG(dst)) {
                dst_r = dst;
                flags |= REG_DEST;
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
                        sugg_src2_r = dst_r;
        }
        else {
@@ -1178,7 +1210,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
        if (FAST_IS_REG(src2)) {
                src2_r = src2;
                flags |= REG2_SOURCE;
-               if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+               if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
                        dst_r = src2_r;
        }
        else if (src2 & SLJIT_IMM) {
@@ -1243,10 +1275,10 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
 {
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-       sljit_si int_op = op & SLJIT_INT_OP;
+       sljit_s32 int_op = op & SLJIT_I32_OP;
 #endif
 
        CHECK_ERROR();
@@ -1257,76 +1289,108 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
        case SLJIT_BREAKPOINT:
        case SLJIT_NOP:
                return push_inst(compiler, NOP);
-       case SLJIT_LUMUL:
-       case SLJIT_LSMUL:
+       case SLJIT_LMUL_UW:
+       case SLJIT_LMUL_SW:
                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)
                FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
-               return push_inst(compiler, (op == SLJIT_LUMUL ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
+               return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
 #else
                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));
+               return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
 #endif
-       case SLJIT_UDIVMOD:
-       case SLJIT_SDIVMOD:
+       case SLJIT_DIVMOD_UW:
+       case SLJIT_DIVMOD_SW:
                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)
-               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 ? (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) : (op == SLJIT_DIVMOD_UW ? 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_UDIVMOD ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
+               FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? 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:
+       case SLJIT_DIV_UW:
+       case SLJIT_DIV_SW:
 #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));
+               return push_inst(compiler, (int_op ? (op == SLJIT_DIV_UW ? DIVWU : DIVW) : (op == SLJIT_DIV_UW ? 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));
+               return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
 #endif
        }
 
        return SLJIT_SUCCESS;
 }
 
+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
+        sljit_s32 src, sljit_sw srcw)
+{
+       if (!(src & OFFS_REG_MASK)) {
+               if (srcw == 0 && (src & REG_MASK) != SLJIT_UNUSED)
+                       return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
+
+               FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+               /* Works with SLJIT_MEM0() case as well. */
+               return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
+       }
+
+       srcw &= 0x3;
+
+       if (srcw == 0)
+               return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+       FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | (srcw << 11) | ((31 - srcw) << 1)));
+#else
+       FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1)));
+#endif
+       return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
+}
+
 #define EMIT_MOV(type, type_flags, type_cast) \
        emit_op(compiler, (src & SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? type_cast srcw : srcw)
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
-       sljit_si op_flags = GET_ALL_FLAGS(op);
+       sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
+       sljit_s32 op_flags = GET_ALL_FLAGS(op);
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
        ADJUST_LOCAL_OFFSET(src, srcw);
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+               if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+                       return emit_prefetch(compiler, src, srcw);
+
+               return SLJIT_SUCCESS;
+       }
+
        op = GET_OPCODE(op);
        if ((src & SLJIT_IMM) && srcw == 0)
                src = TMP_ZERO;
 
-       if (op_flags & SLJIT_SET_O)
+       if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
                FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
 
-       if (op_flags & SLJIT_INT_OP) {
+       if (op_flags & SLJIT_I32_OP) {
                if (op < SLJIT_NOT) {
                        if (FAST_IS_REG(src) && src == dst) {
                                if (!TYPE_CAST_NEEDED(op))
                                        return SLJIT_SUCCESS;
                        }
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-                       if (op == SLJIT_MOV_SI && (src & SLJIT_MEM))
-                               op = SLJIT_MOV_UI;
-                       if (op == SLJIT_MOVU_SI && (src & SLJIT_MEM))
-                               op = SLJIT_MOVU_UI;
-                       if (op == SLJIT_MOV_UI && (src & SLJIT_IMM))
-                               op = SLJIT_MOV_SI;
-                       if (op == SLJIT_MOVU_UI && (src & SLJIT_IMM))
-                               op = SLJIT_MOVU_SI;
+                       if (op == SLJIT_MOV_S32 && (src & SLJIT_MEM))
+                               op = SLJIT_MOV_U32;
+                       if (op == SLJIT_MOVU_S32 && (src & SLJIT_MEM))
+                               op = SLJIT_MOVU_U32;
+                       if (op == SLJIT_MOV_U32 && (src & SLJIT_IMM))
+                               op = SLJIT_MOV_S32;
+                       if (op == SLJIT_MOVU_U32 && (src & SLJIT_IMM))
+                               op = SLJIT_MOVU_S32;
 #endif
                }
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
@@ -1334,7 +1398,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
                        /* Most operations expect sign extended arguments. */
                        flags |= INT_DATA | SIGNED_DATA;
                        if (src & SLJIT_IMM)
-                               srcw = (sljit_si)srcw;
+                               srcw = (sljit_s32)srcw;
+                       if (HAS_FLAGS(op_flags))
+                               flags |= ALT_SIGN_EXT;
                }
 #endif
        }
@@ -1343,68 +1409,68 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        case SLJIT_MOV:
        case SLJIT_MOV_P:
 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
-       case SLJIT_MOV_UI:
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOV_S32:
 #endif
                return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-       case SLJIT_MOV_UI:
-               return EMIT_MOV(SLJIT_MOV_UI, INT_DATA, (sljit_ui));
+       case SLJIT_MOV_U32:
+               return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
 
-       case SLJIT_MOV_SI:
-               return EMIT_MOV(SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, (sljit_si));
+       case SLJIT_MOV_S32:
+               return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
 #endif
 
-       case SLJIT_MOV_UB:
-               return EMIT_MOV(SLJIT_MOV_UB, BYTE_DATA, (sljit_ub));
+       case SLJIT_MOV_U8:
+               return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
 
-       case SLJIT_MOV_SB:
-               return EMIT_MOV(SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA, (sljit_sb));
+       case SLJIT_MOV_S8:
+               return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
 
-       case SLJIT_MOV_UH:
-               return EMIT_MOV(SLJIT_MOV_UH, HALF_DATA, (sljit_uh));
+       case SLJIT_MOV_U16:
+               return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
 
-       case SLJIT_MOV_SH:
-               return EMIT_MOV(SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA, (sljit_sh));
+       case SLJIT_MOV_S16:
+               return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
 
        case SLJIT_MOVU:
        case SLJIT_MOVU_P:
 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
-       case SLJIT_MOVU_UI:
-       case SLJIT_MOVU_SI:
+       case SLJIT_MOVU_U32:
+       case SLJIT_MOVU_S32:
 #endif
                return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-       case SLJIT_MOVU_UI:
-               return EMIT_MOV(SLJIT_MOV_UI, INT_DATA | WRITE_BACK, (sljit_ui));
+       case SLJIT_MOVU_U32:
+               return EMIT_MOV(SLJIT_MOV_U32, INT_DATA | WRITE_BACK, (sljit_u32));
 
-       case SLJIT_MOVU_SI:
-               return EMIT_MOV(SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, (sljit_si));
+       case SLJIT_MOVU_S32:
+               return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s32));
 #endif
 
-       case SLJIT_MOVU_UB:
-               return EMIT_MOV(SLJIT_MOV_UB, BYTE_DATA | WRITE_BACK, (sljit_ub));
+       case SLJIT_MOVU_U8:
+               return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, (sljit_u8));
 
-       case SLJIT_MOVU_SB:
-               return EMIT_MOV(SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA | WRITE_BACK, (sljit_sb));
+       case SLJIT_MOVU_S8:
+               return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s8));
 
-       case SLJIT_MOVU_UH:
-               return EMIT_MOV(SLJIT_MOV_UH, HALF_DATA | WRITE_BACK, (sljit_uh));
+       case SLJIT_MOVU_U16:
+               return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, (sljit_u16));
 
-       case SLJIT_MOVU_SH:
-               return EMIT_MOV(SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA | WRITE_BACK, (sljit_sh));
+       case SLJIT_MOVU_S16:
+               return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s16));
 
        case SLJIT_NOT:
                return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
 
        case SLJIT_NEG:
-               return emit_op(compiler, SLJIT_NEG, flags, dst, dstw, TMP_REG1, 0, src, srcw);
+               return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw);
 
        case SLJIT_CLZ:
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-               return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_INT_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
+               return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_I32_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
 #else
                return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);
 #endif
@@ -1448,12 +1514,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        ((src) & SLJIT_IMM)
 #endif
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
+       sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1461,58 +1527,64 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        ADJUST_LOCAL_OFFSET(src1, src1w);
        ADJUST_LOCAL_OFFSET(src2, src2w);
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+               return SLJIT_SUCCESS;
+
        if ((src1 & SLJIT_IMM) && src1w == 0)
                src1 = TMP_ZERO;
        if ((src2 & SLJIT_IMM) && src2w == 0)
                src2 = TMP_ZERO;
 
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-       if (op & SLJIT_INT_OP) {
+       if (op & SLJIT_I32_OP) {
                /* Most operations expect sign extended arguments. */
                flags |= INT_DATA | SIGNED_DATA;
                if (src1 & SLJIT_IMM)
-                       src1w = (sljit_si)(src1w);
+                       src1w = (sljit_s32)(src1w);
                if (src2 & SLJIT_IMM)
-                       src2w = (sljit_si)(src2w);
-               if (GET_FLAGS(op))
+                       src2w = (sljit_s32)(src2w);
+               if (HAS_FLAGS(op))
                        flags |= ALT_SIGN_EXT;
        }
 #endif
-       if (op & SLJIT_SET_O)
+       if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
                FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
        if (src2 == TMP_REG2)
                flags |= ALT_KEEP_CACHE;
 
        switch (GET_OPCODE(op)) {
        case SLJIT_ADD:
-               if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
+               if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
+                       return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
+
+               if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
                        if (TEST_SL_IMM(src2, src2w)) {
                                compiler->imm = src2w & 0xffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
                        }
                        if (TEST_SL_IMM(src1, src1w)) {
                                compiler->imm = src1w & 0xffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
                        }
                        if (TEST_SH_IMM(src2, src2w)) {
                                compiler->imm = (src2w >> 16) & 0xffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
                        }
                        if (TEST_SH_IMM(src1, src1w)) {
                                compiler->imm = (src1w >> 16) & 0xffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
                        }
                        /* Range between -1 and -32768 is covered above. */
                        if (TEST_ADD_IMM(src2, src2w)) {
                                compiler->imm = src2w & 0xffffffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
                        }
                        if (TEST_ADD_IMM(src1, src1w)) {
                                compiler->imm = src1w & 0xffffffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
                        }
                }
-               if (!(GET_FLAGS(op) & (SLJIT_SET_E | SLJIT_SET_O))) {
+               if (HAS_FLAGS(op)) {
                        if (TEST_SL_IMM(src2, src2w)) {
                                compiler->imm = src2w & 0xffff;
                                return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
@@ -1522,75 +1594,75 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
                                return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
                        }
                }
-               return emit_op(compiler, SLJIT_ADD, flags, dst, dstw, src1, src1w, src2, src2w);
+               return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM4 : 0), dst, dstw, src1, src1w, src2, src2w);
 
        case SLJIT_ADDC:
-               return emit_op(compiler, SLJIT_ADDC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
+               return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
 
        case SLJIT_SUB:
-               if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
+               if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
+                       if (dst == SLJIT_UNUSED) {
+                               if (TEST_UL_IMM(src2, src2w)) {
+                                       compiler->imm = src2w & 0xffff;
+                                       return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+                               }
+                               return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
+                       }
+
+                       if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
+                               compiler->imm = src2w;
+                               return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
+               }
+
+               if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
+                       return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
+
+               if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
                        if (TEST_SL_IMM(src2, -src2w)) {
                                compiler->imm = (-src2w) & 0xffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
                        }
                        if (TEST_SL_IMM(src1, src1w)) {
                                compiler->imm = src1w & 0xffff;
-                               return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
                        }
                        if (TEST_SH_IMM(src2, -src2w)) {
                                compiler->imm = ((-src2w) >> 16) & 0xffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_ADD, flags |  ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
                        }
                        /* Range between -1 and -32768 is covered above. */
                        if (TEST_ADD_IMM(src2, -src2w)) {
                                compiler->imm = -src2w & 0xffffffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
                        }
                }
-               if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) {
-                       if (!(op & SLJIT_SET_U)) {
-                               /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
-                               if (TEST_SL_IMM(src2, src2w)) {
-                                       compiler->imm = src2w & 0xffff;
-                                       return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
-                               }
-                               if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) {
-                                       compiler->imm = src1w & 0xffff;
-                                       return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
-                               }
-                       }
-                       if (!(op & (SLJIT_SET_E | SLJIT_SET_S))) {
-                               /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
-                               if (TEST_UL_IMM(src2, src2w)) {
-                                       compiler->imm = src2w & 0xffff;
-                                       return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
-                               }
-                               return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
-                       }
-                       if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= 0x7fff) {
-                               compiler->imm = src2w;
-                               return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+
+               if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)) {
+                       if (TEST_SL_IMM(src2, src2w)) {
+                               compiler->imm = src2w & 0xffff;
+                               return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
                        }
-                       return emit_op(compiler, SLJIT_SUB, flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
+                       return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
                }
-               if (!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))) {
-                       if (TEST_SL_IMM(src2, -src2w)) {
-                               compiler->imm = (-src2w) & 0xffff;
-                               return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
-                       }
+
+               if (TEST_SL_IMM(src2, -src2w)) {
+                       compiler->imm = (-src2w) & 0xffff;
+                       return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
                }
-               /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
-               return emit_op(compiler, SLJIT_SUB, flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w);
+               /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
+               return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
 
        case SLJIT_SUBC:
-               return emit_op(compiler, SLJIT_SUBC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
+               return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
 
        case SLJIT_MUL:
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-               if (op & SLJIT_INT_OP)
+               if (op & SLJIT_I32_OP)
                        flags |= ALT_FORM2;
 #endif
-               if (!GET_FLAGS(op)) {
+               if (!HAS_FLAGS(op)) {
                        if (TEST_SL_IMM(src2, src2w)) {
                                compiler->imm = src2w & 0xffff;
                                return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
@@ -1600,13 +1672,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
                                return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
                        }
                }
+               else
+                       FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
                return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
 
        case SLJIT_AND:
        case SLJIT_OR:
        case SLJIT_XOR:
                /* Commutative unsigned operations. */
-               if (!GET_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
+               if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
                        if (TEST_UL_IMM(src2, src2w)) {
                                compiler->imm = src2w;
                                return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
@@ -1624,7 +1698,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
                                return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
                        }
                }
-               if (!GET_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
+               if (GET_OPCODE(op) != SLJIT_AND && GET_OPCODE(op) != SLJIT_AND) {
+                       /* Unlike or and xor, and resets unwanted bits as well. */
                        if (TEST_UI_IMM(src2, src2w)) {
                                compiler->imm = src2w;
                                return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
@@ -1636,14 +1711,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
                }
                return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
 
-       case SLJIT_ASHR:
-               if (op & SLJIT_KEEP_FLAGS)
-                       flags |= ALT_FORM3;
-               /* Fall through. */
        case SLJIT_SHL:
        case SLJIT_LSHR:
+       case SLJIT_ASHR:
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-               if (op & SLJIT_INT_OP)
+               if (op & SLJIT_I32_OP)
                        flags |= ALT_FORM2;
 #endif
                if (src2 & SLJIT_IMM) {
@@ -1656,20 +1728,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_register_index(reg));
        return reg_map[reg];
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
        return reg;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1681,18 +1753,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
 /*  Floating point operators                                             */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
-       return SLJIT_IS_FPU_AVAILABLE;
-#else
-       /* Available by default. */
-       return 1;
-#endif
-}
-
-#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 6))
-#define SELECT_FOP(op, single, double) ((op & SLJIT_SINGLE_OP) ? single : double)
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6))
+#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
 
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
 #define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
@@ -1709,9 +1771,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
 
 #endif /* SLJIT_CONFIG_PPC_64 */
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
        if (src & SLJIT_MEM) {
                /* We can ignore the temporary data store on the stack from caching point of view. */
@@ -1721,24 +1783,17 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
 
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
        op = GET_OPCODE(op);
-       FAIL_IF(push_inst(compiler, (op == SLJIT_CONVI_FROMD ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
-
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
+       FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
 
-       if (op == SLJIT_CONVW_FROMD) {
+       if (op == SLJIT_CONV_SW_FROM_F64) {
                if (FAST_IS_REG(dst)) {
                        FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0));
                        return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0);
                }
                return emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, 0, 0);
        }
-
 #else
        FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
-
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
 #endif
 
        if (FAST_IS_REG(dst)) {
@@ -1777,21 +1832,21 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
        return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
 
-       sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
 
        if (src & SLJIT_IMM) {
-               if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
-                       srcw = (sljit_si)srcw;
+               if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+                       srcw = (sljit_s32)srcw;
                FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
                src = TMP_REG1;
        }
-       else if (GET_OPCODE(op) == SLJIT_CONVD_FROMI) {
+       else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
                if (FAST_IS_REG(src))
                        FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
                else
@@ -1810,14 +1865,14 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
 
        if (dst & SLJIT_MEM)
                return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
-       if (op & SLJIT_SINGLE_OP)
+       if (op & SLJIT_F32_OP)
                return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
        return SLJIT_SUCCESS;
 
 #else
 
-       sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
-       sljit_si invert_sign = 1;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+       sljit_s32 invert_sign = 1;
 
        if (src & SLJIT_IMM) {
                FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000));
@@ -1848,16 +1903,16 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
 
        if (dst & SLJIT_MEM)
                return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
-       if (op & SLJIT_SINGLE_OP)
+       if (op & SLJIT_F32_OP)
                return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
        return SLJIT_SUCCESS;
 
 #endif
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        if (src1 & SLJIT_MEM) {
                FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
@@ -1872,21 +1927,21 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler
        return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR();
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
 
-       SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
+       SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
        SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
 
-       if (GET_OPCODE(op) == SLJIT_CONVD_FROMS)
-               op ^= SLJIT_SINGLE_OP;
+       if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
+               op ^= SLJIT_F32_OP;
 
        dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
 
@@ -1896,14 +1951,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
        }
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_CONVD_FROMS:
-               op ^= SLJIT_SINGLE_OP;
-               if (op & SLJIT_SINGLE_OP) {
+       case SLJIT_CONV_F64_FROM_F32:
+               op ^= SLJIT_F32_OP;
+               if (op & SLJIT_F32_OP) {
                        FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
                        break;
                }
                /* Fall through. */
-       case SLJIT_DMOV:
+       case SLJIT_MOV_F64:
                if (src != dst_r) {
                        if (dst_r != TMP_FREG1)
                                FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
@@ -1911,10 +1966,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
                                dst_r = src;
                }
                break;
-       case SLJIT_DNEG:
+       case SLJIT_NEG_F64:
                FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
                break;
-       case SLJIT_DABS:
+       case SLJIT_ABS_F64:
                FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
                break;
        }
@@ -1924,12 +1979,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si dst_r, flags = 0;
+       sljit_s32 dst_r, flags = 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1979,19 +2034,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
                src2 = TMP_FREG2;
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DADD:
+       case SLJIT_ADD_F64:
                FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
                break;
 
-       case SLJIT_DSUB:
+       case SLJIT_SUB_F64:
                FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
                break;
 
-       case SLJIT_DMUL:
+       case SLJIT_MUL_F64:
                FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
                break;
 
-       case SLJIT_DDIV:
+       case SLJIT_DIV_F64:
                FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
                break;
        }
@@ -2009,16 +2064,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
 /*  Other instructions                                                   */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       /* For UNUSED dst. Uncommon, but possible. */
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
-
        if (FAST_IS_REG(dst))
                return push_inst(compiler, MFLR | D(dst));
 
@@ -2027,7 +2078,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
        return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
@@ -2065,7 +2116,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
        return label;
 }
 
-static sljit_ins get_bo_bi_flags(sljit_si type)
+static sljit_ins get_bo_bi_flags(sljit_s32 type)
 {
        switch (type) {
        case SLJIT_EQUAL:
@@ -2075,33 +2126,33 @@ static sljit_ins get_bo_bi_flags(sljit_si type)
                return (4 << 21) | (2 << 16);
 
        case SLJIT_LESS:
-       case SLJIT_D_LESS:
-               return (12 << 21) | ((4 + 0) << 16);
-
-       case SLJIT_GREATER_EQUAL:
-       case SLJIT_D_GREATER_EQUAL:
-               return (4 << 21) | ((4 + 0) << 16);
-
-       case SLJIT_GREATER:
-       case SLJIT_D_GREATER:
-               return (12 << 21) | ((4 + 1) << 16);
-
-       case SLJIT_LESS_EQUAL:
-       case SLJIT_D_LESS_EQUAL:
-               return (4 << 21) | ((4 + 1) << 16);
-
        case SLJIT_SIG_LESS:
                return (12 << 21) | (0 << 16);
 
+       case SLJIT_GREATER_EQUAL:
        case SLJIT_SIG_GREATER_EQUAL:
                return (4 << 21) | (0 << 16);
 
+       case SLJIT_GREATER:
        case SLJIT_SIG_GREATER:
                return (12 << 21) | (1 << 16);
 
+       case SLJIT_LESS_EQUAL:
        case SLJIT_SIG_LESS_EQUAL:
                return (4 << 21) | (1 << 16);
 
+       case SLJIT_LESS_F64:
+               return (12 << 21) | ((4 + 0) << 16);
+
+       case SLJIT_GREATER_EQUAL_F64:
+               return (4 << 21) | ((4 + 0) << 16);
+
+       case SLJIT_GREATER_F64:
+               return (12 << 21) | ((4 + 1) << 16);
+
+       case SLJIT_LESS_EQUAL_F64:
+               return (4 << 21) | ((4 + 1) << 16);
+
        case SLJIT_OVERFLOW:
        case SLJIT_MUL_OVERFLOW:
                return (12 << 21) | (3 << 16);
@@ -2110,16 +2161,16 @@ static sljit_ins get_bo_bi_flags(sljit_si type)
        case SLJIT_MUL_NOT_OVERFLOW:
                return (4 << 21) | (3 << 16);
 
-       case SLJIT_D_EQUAL:
+       case SLJIT_EQUAL_F64:
                return (12 << 21) | ((4 + 2) << 16);
 
-       case SLJIT_D_NOT_EQUAL:
+       case SLJIT_NOT_EQUAL_F64:
                return (4 << 21) | ((4 + 2) << 16);
 
-       case SLJIT_D_UNORDERED:
+       case SLJIT_UNORDERED_F64:
                return (12 << 21) | ((4 + 3) << 16);
 
-       case SLJIT_D_ORDERED:
+       case SLJIT_ORDERED_F64:
                return (4 << 21) | ((4 + 3) << 16);
 
        default:
@@ -2128,7 +2179,7 @@ static sljit_ins get_bo_bi_flags(sljit_si type)
        }
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
        struct sljit_jump *jump;
        sljit_ins bo_bi_flags;
@@ -2160,10 +2211,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
        return jump;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
        struct sljit_jump *jump = NULL;
-       sljit_si src_r;
+       sljit_s32 src_r;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
@@ -2203,159 +2254,154 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
        return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
 }
 
-/* Get a bit from CR, all other bits are zeroed. */
-#define GET_CR_BIT(bit, dst) \
-       FAIL_IF(push_inst(compiler, MFCR | D(dst))); \
-       FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | ((1 + (bit)) << 11) | (31 << 6) | (31 << 1)));
-
-#define INVERT_BIT(dst) \
-       FAIL_IF(push_inst(compiler, XORI | S(dst) | A(dst) | 0x1));
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type)
 {
-       sljit_si reg, input_flags;
-       sljit_si flags = GET_ALL_FLAGS(op);
-       sljit_sw original_dstw = dstw;
+       sljit_s32 reg, input_flags, cr_bit, invert;
+       sljit_s32 saved_op = op;
+       sljit_sw saved_dstw = dstw;
 
        CHECK_ERROR();
-       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       input_flags = (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA;
+#else
+       input_flags = WORD_DATA;
+#endif
 
        op = GET_OPCODE(op);
        reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
 
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
-       if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
-               ADJUST_LOCAL_OFFSET(src, srcw);
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-               input_flags = (flags & SLJIT_INT_OP) ? INT_DATA : WORD_DATA;
-#else
-               input_flags = WORD_DATA;
-#endif
-               FAIL_IF(emit_op_mem2(compiler, input_flags | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
-               src = TMP_REG1;
-               srcw = 0;
-       }
 
-       switch (type & 0xff) {
-       case SLJIT_EQUAL:
-               GET_CR_BIT(2, reg);
-               break;
+       if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+               FAIL_IF(emit_op_mem2(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
 
-       case SLJIT_NOT_EQUAL:
-               GET_CR_BIT(2, reg);
-               INVERT_BIT(reg);
-               break;
+       invert = 0;
 
+       switch (type & 0xff) {
        case SLJIT_LESS:
-       case SLJIT_D_LESS:
-               GET_CR_BIT(4 + 0, reg);
+       case SLJIT_SIG_LESS:
+               cr_bit = 0;
                break;
 
        case SLJIT_GREATER_EQUAL:
-       case SLJIT_D_GREATER_EQUAL:
-               GET_CR_BIT(4 + 0, reg);
-               INVERT_BIT(reg);
+       case SLJIT_SIG_GREATER_EQUAL:
+               cr_bit = 0;
+               invert = 1;
                break;
 
        case SLJIT_GREATER:
-       case SLJIT_D_GREATER:
-               GET_CR_BIT(4 + 1, reg);
+       case SLJIT_SIG_GREATER:
+               cr_bit = 1;
                break;
 
        case SLJIT_LESS_EQUAL:
-       case SLJIT_D_LESS_EQUAL:
-               GET_CR_BIT(4 + 1, reg);
-               INVERT_BIT(reg);
-               break;
-
-       case SLJIT_SIG_LESS:
-               GET_CR_BIT(0, reg);
-               break;
-
-       case SLJIT_SIG_GREATER_EQUAL:
-               GET_CR_BIT(0, reg);
-               INVERT_BIT(reg);
+       case SLJIT_SIG_LESS_EQUAL:
+               cr_bit = 1;
+               invert = 1;
                break;
 
-       case SLJIT_SIG_GREATER:
-               GET_CR_BIT(1, reg);
+       case SLJIT_EQUAL:
+               cr_bit = 2;
                break;
 
-       case SLJIT_SIG_LESS_EQUAL:
-               GET_CR_BIT(1, reg);
-               INVERT_BIT(reg);
+       case SLJIT_NOT_EQUAL:
+               cr_bit = 2;
+               invert = 1;
                break;
 
        case SLJIT_OVERFLOW:
        case SLJIT_MUL_OVERFLOW:
-               GET_CR_BIT(3, reg);
+               cr_bit = 3;
                break;
 
        case SLJIT_NOT_OVERFLOW:
        case SLJIT_MUL_NOT_OVERFLOW:
-               GET_CR_BIT(3, reg);
-               INVERT_BIT(reg);
+               cr_bit = 3;
+               invert = 1;
+               break;
+
+       case SLJIT_LESS_F64:
+               cr_bit = 4 + 0;
                break;
 
-       case SLJIT_D_EQUAL:
-               GET_CR_BIT(4 + 2, reg);
+       case SLJIT_GREATER_EQUAL_F64:
+               cr_bit = 4 + 0;
+               invert = 1;
                break;
 
-       case SLJIT_D_NOT_EQUAL:
-               GET_CR_BIT(4 + 2, reg);
-               INVERT_BIT(reg);
+       case SLJIT_GREATER_F64:
+               cr_bit = 4 + 1;
                break;
 
-       case SLJIT_D_UNORDERED:
-               GET_CR_BIT(4 + 3, reg);
+       case SLJIT_LESS_EQUAL_F64:
+               cr_bit = 4 + 1;
+               invert = 1;
                break;
 
-       case SLJIT_D_ORDERED:
-               GET_CR_BIT(4 + 3, reg);
-               INVERT_BIT(reg);
+       case SLJIT_EQUAL_F64:
+               cr_bit = 4 + 2;
+               break;
+
+       case SLJIT_NOT_EQUAL_F64:
+               cr_bit = 4 + 2;
+               invert = 1;
+               break;
+
+       case SLJIT_UNORDERED_F64:
+               cr_bit = 4 + 3;
+               break;
+
+       case SLJIT_ORDERED_F64:
+               cr_bit = 4 + 3;
+               invert = 1;
                break;
 
        default:
-               SLJIT_ASSERT_STOP();
+               SLJIT_UNREACHABLE();
                break;
        }
 
+       FAIL_IF(push_inst(compiler, MFCR | D(reg)));
+       FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + (cr_bit)) << 11) | (31 << 6) | (31 << 1)));
+
+       if (invert)
+               FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
+
        if (op < SLJIT_ADD) {
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-               if (op == SLJIT_MOV)
-                       input_flags = WORD_DATA;
-               else {
-                       op = SLJIT_MOV_UI;
-                       input_flags = INT_DATA;
-               }
-#else
-               op = SLJIT_MOV;
-               input_flags = WORD_DATA;
-#endif
-               if (reg != TMP_REG2)
+               if (!(dst & SLJIT_MEM))
                        return SLJIT_SUCCESS;
-               return emit_op(compiler, op, input_flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+               return emit_op_mem2(compiler, input_flags, reg, dst, dstw, reg, 0);
        }
 
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
                || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        compiler->skip_checks = 1;
 #endif
-       return sljit_emit_op2(compiler, op | flags, dst, original_dstw, src, srcw, TMP_REG2, 0);
+       if (dst & SLJIT_MEM)
+               return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
+       return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+       CHECK_ERROR();
+       CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+       return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+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_si reg;
+       sljit_s32 reg;
 
        CHECK_ERROR_PTR();
        CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -2365,7 +2411,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
        PTR_FAIL_IF(!const_);
        set_const(const_, compiler);
 
-       reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+       reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
 
        PTR_FAIL_IF(emit_const(compiler, reg, init_value));
 
index 4a2e6293de57989b15246861b3f2d1fa43eca0de..ee42130e87e3b7d5070bb9c829da476fc4354814 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -24,7 +24,7 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sljit_sw imm)
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw imm)
 {
        if (imm <= SIMM_MAX && imm >= SIMM_MIN)
                return push_inst(compiler, OR | D(dst) | S1(0) | IMM(imm), DR(dst));
@@ -35,43 +35,43 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sl
 
 #define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2))
 
-static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
-       sljit_si dst, sljit_si src1, sljit_sw src2)
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+       sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
 {
        SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same);
 
        switch (op) {
        case SLJIT_MOV:
-       case SLJIT_MOV_UI:
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOV_S32:
        case SLJIT_MOV_P:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if (dst != src2)
                        return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst));
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UB:
-       case SLJIT_MOV_SB:
+       case SLJIT_MOV_U8:
+       case SLJIT_MOV_S8:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_UB)
+                       if (op == SLJIT_MOV_U8)
                                return push_inst(compiler, AND | D(dst) | S1(src2) | IMM(0xff), DR(dst));
                        FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst)));
                        return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst));
                }
                else if (dst != src2)
-                       SLJIT_ASSERT_STOP();
+                       SLJIT_UNREACHABLE();
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UH:
-       case SLJIT_MOV_SH:
+       case SLJIT_MOV_U16:
+       case SLJIT_MOV_S16:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
                        FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst)));
-                       return push_inst(compiler, (op == SLJIT_MOV_SH ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
+                       return push_inst(compiler, (op == SLJIT_MOV_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
                }
                else if (dst != src2)
-                       SLJIT_ASSERT_STOP();
+                       SLJIT_UNREACHABLE();
                return SLJIT_SUCCESS;
 
        case SLJIT_NOT:
@@ -80,18 +80,17 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
 
        case SLJIT_CLZ:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
-               /* sparc 32 does not support SLJIT_KEEP_FLAGS. Not sure I can fix this. */
                FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));
                FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));
                FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));
-               FAIL_IF(push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS | (flags & SET_FLAGS)));
+               FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS));
                FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));
 
                /* Loop. */
                FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
                FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
                FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));
-               return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS | (flags & SET_FLAGS));
+               return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS);
 
        case SLJIT_ADD:
                return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
@@ -135,30 +134,32 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
        }
 
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
 {
        FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst)));
        return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst));
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+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;
+       sljit_ins *inst = (sljit_ins *)addr;
 
-       inst[0] = (inst[0] & 0xffc00000) | ((new_addr >> 10) & 0x3fffff);
-       inst[1] = (inst[1] & 0xfffffc00) | (new_addr & 0x3ff);
+       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);
        SLJIT_CACHE_FLUSH(inst, inst + 2);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
-       sljit_ins *inst = (sljit_ins*)addr;
+       sljit_ins *inst = (sljit_ins *)addr;
 
        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);
        SLJIT_CACHE_FLUSH(inst, inst + 2);
 }
index 327c4267be439bcb7567567813df14605c45ce89..9831bd83d72a1fd9d8dedb2547c2105247af225f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
 {
        return "SPARC" SLJIT_CPUINFO;
 }
 
 /* Length of an instruction word
    Both for sparc-32 and sparc-64 */
-typedef sljit_ui sljit_ins;
+typedef sljit_u32 sljit_ins;
+
+#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)
 
 static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
 {
@@ -82,6 +84,8 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
 #endif
 }
 
+#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */
+
 /* TMP_REG2 is not used by getput_arg */
 #define TMP_REG1       (SLJIT_NUMBER_OF_REGISTERS + 2)
 #define TMP_REG2       (SLJIT_NUMBER_OF_REGISTERS + 3)
@@ -91,7 +95,7 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
 #define TMP_FREG1      (0)
 #define TMP_FREG2      ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1)
 
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
        0, 8, 9, 10, 13, 29, 28, 27, 23, 22, 21, 20, 19, 18, 17, 16, 26, 25, 24, 14, 1, 11, 12, 15
 };
 
@@ -181,7 +185,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
 
 /* dest_reg is the absolute name of the register
    Useful for reordering instructions in the delay slot. */
-static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_si delay_slot)
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)
 {
        sljit_ins *ptr;
        SLJIT_ASSERT((delay_slot & DST_INS_MASK) == UNMOVABLE_INS
@@ -195,7 +199,7 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+static SLJIT_INLINE sljit_ins* 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;
@@ -209,7 +213,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
                target_addr = jump->u.target;
        else {
                SLJIT_ASSERT(jump->flags & JUMP_LABEL);
-               target_addr = (sljit_uw)(code + jump->u.label->size);
+               target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
        }
        inst = (sljit_ins*)jump->addr;
 
@@ -235,8 +239,9 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
        if (jump->flags & IS_COND)
                inst--;
 
+       diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1) - executable_offset) >> 2;
+
        if (jump->flags & IS_MOVABLE) {
-               diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1)) >> 2;
                if (diff <= MAX_DISP && diff >= MIN_DISP) {
                        jump->flags |= PATCH_B;
                        inst--;
@@ -253,7 +258,8 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
                }
        }
 
-       diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
+       diff += sizeof(sljit_ins);
+
        if (diff <= MAX_DISP && diff >= MIN_DISP) {
                jump->flags |= PATCH_B;
                if (jump->flags & IS_COND)
@@ -276,6 +282,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        sljit_ins *buf_ptr;
        sljit_ins *buf_end;
        sljit_uw word_count;
+       sljit_sw executable_offset;
        sljit_uw addr;
 
        struct sljit_label *label;
@@ -292,9 +299,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
        code_ptr = code;
        word_count = 0;
+       executable_offset = SLJIT_EXEC_OFFSET(code);
+
        label = compiler->labels;
        jump = compiler->jumps;
        const_ = compiler->consts;
+
        do {
                buf_ptr = (sljit_ins*)buf->memory;
                buf_end = buf_ptr + (buf->used_size >> 2);
@@ -306,7 +316,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                        /* These structures are ordered by their address. */
                        if (label && label->size == word_count) {
                                /* Just recording the address. */
-                               label->addr = (sljit_uw)code_ptr;
+                               label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
                                label->size = code_ptr - code;
                                label = label->next;
                        }
@@ -316,7 +326,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 #else
                                jump->addr = (sljit_uw)(code_ptr - 6);
 #endif
-                               code_ptr = detect_jump_type(jump, code_ptr, code);
+                               code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
                                jump = jump->next;
                        }
                        if (const_ && const_->addr == word_count) {
@@ -332,7 +342,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        } while (buf);
 
        if (label && label->size == word_count) {
-               label->addr = (sljit_uw)code_ptr;
+               label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
                label->size = code_ptr - code;
                label = label->next;
        }
@@ -340,22 +350,22 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        SLJIT_ASSERT(!label);
        SLJIT_ASSERT(!jump);
        SLJIT_ASSERT(!const_);
-       SLJIT_ASSERT(code_ptr - code <= (sljit_si)compiler->size);
+       SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);
 
        jump = compiler->jumps;
        while (jump) {
                do {
                        addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
-                       buf_ptr = (sljit_ins*)jump->addr;
+                       buf_ptr = (sljit_ins *)jump->addr;
 
                        if (jump->flags & PATCH_CALL) {
-                               addr = (sljit_sw)(addr - jump->addr) >> 2;
+                               addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
                                SLJIT_ASSERT((sljit_sw)addr <= 0x1fffffff && (sljit_sw)addr >= -0x20000000);
                                buf_ptr[0] = CALL | (addr & 0x3fffffff);
                                break;
                        }
                        if (jump->flags & PATCH_B) {
-                               addr = (sljit_sw)(addr - jump->addr) >> 2;
+                               addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
                                SLJIT_ASSERT((sljit_sw)addr <= MAX_DISP && (sljit_sw)addr >= MIN_DISP);
                                buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | (addr & DISP_MASK);
                                break;
@@ -374,11 +384,37 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
 
        compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_offset = executable_offset;
        compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+
+       code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+       code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
        SLJIT_CACHE_FLUSH(code, code_ptr);
        return code;
 }
 
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+       switch (feature_type) {
+       case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+               return SLJIT_IS_FPU_AVAILABLE;
+#else
+               /* Available by default. */
+               return 1;
+#endif
+
+#if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)
+       case SLJIT_HAS_CMOV:
+               return 1;
+#endif
+
+       default:
+               return 0;
+       }
+}
+
 /* --------------------------------------------------------------------- */
 /*  Entry, exit                                                          */
 /* --------------------------------------------------------------------- */
@@ -418,9 +454,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 #include "sljitNativeSPARC_64.c"
 #endif
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -442,9 +478,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
        CHECK_ERROR();
        CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -454,7 +490,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_return(compiler, op, src, srcw));
@@ -478,7 +514,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
 #define ARCH_32_64(a, b)       b
 #endif
 
-static SLJIT_CONST sljit_ins data_transfer_insts[16 + 4] = {
+static const sljit_ins data_transfer_insts[16 + 4] = {
 /* u w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */),
 /* u w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */),
 /* u b s */ OPC1(3) | OPC3(0x05) /* stb */,
@@ -506,7 +542,7 @@ static SLJIT_CONST sljit_ins data_transfer_insts[16 + 4] = {
 #undef ARCH_32_64
 
 /* Can perform an operation using at most 1 instruction. */
-static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
 {
        SLJIT_ASSERT(arg & SLJIT_MEM);
 
@@ -529,7 +565,7 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
 /* See getput_arg below.
    Note: can_cache is called only for binary operators. Those
    operators always uses word arguments without write back. */
-static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
        SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
 
@@ -549,9 +585,9 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
 }
 
 /* Emit the necessary instructions. See can_cache above. */
-static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
-       sljit_si base, arg2, delay_slot;
+       sljit_s32 base, arg2, delay_slot;
        sljit_ins dest;
 
        SLJIT_ASSERT(arg & SLJIT_MEM);
@@ -563,7 +599,6 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
        base = arg & REG_MASK;
        if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
                argw &= 0x3;
-               SLJIT_ASSERT(argw != 0);
 
                /* Using the cache. */
                if (((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) && (argw == compiler->cache_argw))
@@ -613,7 +648,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
        return push_inst(compiler, ADD | D(base) | S1(base) | S2(arg2), DR(base));
 }
 
-static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
 {
        if (getput_arg_fast(compiler, flags, reg, arg, argw))
                return compiler->error;
@@ -622,44 +657,42 @@ static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_
        return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
 }
 
-static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
 {
        if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
                return compiler->error;
        return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
 }
 
-static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        /* arg1 goes to TMP_REG1 or src reg
           arg2 goes to TMP_REG2, imm or src reg
           TMP_REG3 can be used for caching
           result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
-       sljit_si dst_r = TMP_REG2;
-       sljit_si src1_r;
+       sljit_s32 dst_r = TMP_REG2;
+       sljit_s32 src1_r;
        sljit_sw src2_r = 0;
-       sljit_si sugg_src2_r = TMP_REG2;
+       sljit_s32 sugg_src2_r = TMP_REG2;
 
        if (!(flags & ALT_KEEP_CACHE)) {
                compiler->cache_arg = 0;
                compiler->cache_argw = 0;
        }
 
-       if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
-                       return SLJIT_SUCCESS;
-       }
-       else if (FAST_IS_REG(dst)) {
-               dst_r = dst;
-               flags |= REG_DEST;
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
-                       sugg_src2_r = dst_r;
+       if (dst != SLJIT_UNUSED) {
+               if (FAST_IS_REG(dst)) {
+                       dst_r = dst;
+                       flags |= REG_DEST;
+                       if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
+                               sugg_src2_r = dst_r;
+               }
+               else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
+                       flags |= SLOW_DEST;
        }
-       else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
-               flags |= SLOW_DEST;
 
        if (flags & IMM_OP) {
                if ((src2 & SLJIT_IMM) && src2w) {
@@ -705,7 +738,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
        if (FAST_IS_REG(src2)) {
                src2_r = src2;
                flags |= REG2_SOURCE;
-               if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+               if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
                        dst_r = src2_r;
        }
        else if (src2 & SLJIT_IMM) {
@@ -716,7 +749,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
                        }
                        else {
                                src2_r = 0;
-                               if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) && (dst & SLJIT_MEM))
+                               if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))
                                        dst_r = 0;
                        }
                }
@@ -758,7 +791,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op0(compiler, op));
@@ -769,30 +802,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
                return push_inst(compiler, TA, UNMOVABLE_INS);
        case SLJIT_NOP:
                return push_inst(compiler, NOP, UNMOVABLE_INS);
-       case SLJIT_LUMUL:
-       case SLJIT_LSMUL:
+       case SLJIT_LMUL_UW:
+       case SLJIT_LMUL_SW:
 #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
-               FAIL_IF(push_inst(compiler, (op == SLJIT_LUMUL ? UMUL : SMUL) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
+               FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? UMUL : SMUL) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
                return push_inst(compiler, RDY | D(SLJIT_R1), DR(SLJIT_R1));
 #else
 #error "Implementation required"
 #endif
-       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);
+       case SLJIT_DIVMOD_UW:
+       case SLJIT_DIVMOD_SW:
+       case SLJIT_DIV_UW:
+       case SLJIT_DIV_SW:
+               SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
 #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
-               if ((op | 0x2) == SLJIT_UDIVI)
+               if ((op | 0x2) == SLJIT_DIV_UW)
                        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));
                }
-               if (op <= SLJIT_SDIVMOD)
+               if (op <= SLJIT_DIVMOD_SW)
                        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)
+               FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
+               if (op >= SLJIT_DIV_UW)
                        return SLJIT_SUCCESS;
                FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1)));
                return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1));
@@ -804,62 +837,65 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+       sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
        ADJUST_LOCAL_OFFSET(src, srcw);
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+               return SLJIT_SUCCESS;
+
        op = GET_OPCODE(op);
        switch (op) {
        case SLJIT_MOV:
        case SLJIT_MOV_P:
                return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOV_UI:
-               return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+       case SLJIT_MOV_U32:
+               return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOV_SI:
-               return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+       case SLJIT_MOV_S32:
+               return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOV_UB:
-               return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+       case SLJIT_MOV_U8:
+               return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
 
-       case SLJIT_MOV_SB:
-               return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+       case SLJIT_MOV_S8:
+               return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
 
-       case SLJIT_MOV_UH:
-               return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+       case SLJIT_MOV_U16:
+               return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
 
-       case SLJIT_MOV_SH:
-               return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+       case SLJIT_MOV_S16:
+               return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
 
        case SLJIT_MOVU:
        case SLJIT_MOVU_P:
                return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOVU_UI:
-               return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+       case SLJIT_MOVU_U32:
+               return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOVU_SI:
-               return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+       case SLJIT_MOVU_S32:
+               return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOVU_UB:
-               return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
+       case SLJIT_MOVU_U8:
+               return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
 
-       case SLJIT_MOVU_SB:
-               return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
+       case SLJIT_MOVU_S8:
+               return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
 
-       case SLJIT_MOVU_UH:
-               return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
+       case SLJIT_MOVU_U16:
+               return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
 
-       case SLJIT_MOVU_SH:
-               return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
+       case SLJIT_MOVU_S16:
+               return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
 
        case SLJIT_NOT:
        case SLJIT_CLZ:
@@ -872,12 +908,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+       sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -885,6 +921,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        ADJUST_LOCAL_OFFSET(src1, src1w);
        ADJUST_LOCAL_OFFSET(src2, src2w);
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+               return SLJIT_SUCCESS;
+
        op = GET_OPCODE(op);
        switch (op) {
        case SLJIT_ADD:
@@ -906,7 +945,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
                if (src2 & SLJIT_IMM)
                        src2w &= 0x1f;
 #else
-               SLJIT_ASSERT_STOP();
+               SLJIT_UNREACHABLE();
 #endif
                return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
        }
@@ -914,20 +953,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_register_index(reg));
        return reg_map[reg];
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
        return reg << 1;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -939,23 +978,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
 /*  Floating point operators                                             */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
-       return SLJIT_IS_FPU_AVAILABLE;
-#else
-       /* Available by default. */
-       return 1;
-#endif
-}
-
-#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 7))
-#define SELECT_FOP(op, single, double) ((op & SLJIT_SINGLE_OP) ? single : double)
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
+#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
 #define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw))
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
        if (src & SLJIT_MEM) {
                FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
@@ -966,9 +995,6 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
 
        FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | DA(TMP_FREG1) | S2A(src), MOVABLE_INS));
 
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
-
        if (FAST_IS_REG(dst)) {
                FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
                return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET);
@@ -978,16 +1004,16 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *
        return emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, dst, dstw, 0, 0);
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
 
        if (src & SLJIT_IMM) {
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-               if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
-                       srcw = (sljit_si)srcw;
+               if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+                       srcw = (sljit_s32)srcw;
 #endif
                FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
                src = TMP_REG1;
@@ -1008,9 +1034,9 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        if (src1 & SLJIT_MEM) {
                FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
@@ -1029,21 +1055,21 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler
        return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | S1A(src1) | S2A(src2), FCC_IS_SET | MOVABLE_INS);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR();
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
 
-       SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
+       SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
        SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
 
-       if (GET_OPCODE(op) == SLJIT_CONVD_FROMS)
-               op ^= SLJIT_SINGLE_OP;
+       if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
+               op ^= SLJIT_F32_OP;
 
        dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
 
@@ -1055,30 +1081,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
                src <<= 1;
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DMOV:
+       case SLJIT_MOV_F64:
                if (src != dst_r) {
                        if (dst_r != TMP_FREG1) {
                                FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r) | S2A(src), MOVABLE_INS));
-                               if (!(op & SLJIT_SINGLE_OP))
+                               if (!(op & SLJIT_F32_OP))
                                        FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
                        }
                        else
                                dst_r = src;
                }
                break;
-       case SLJIT_DNEG:
+       case SLJIT_NEG_F64:
                FAIL_IF(push_inst(compiler, FNEGS | DA(dst_r) | S2A(src), MOVABLE_INS));
-               if (dst_r != src && !(op & SLJIT_SINGLE_OP))
+               if (dst_r != src && !(op & SLJIT_F32_OP))
                        FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
                break;
-       case SLJIT_DABS:
+       case SLJIT_ABS_F64:
                FAIL_IF(push_inst(compiler, FABSS | DA(dst_r) | S2A(src), MOVABLE_INS));
-               if (dst_r != src && !(op & SLJIT_SINGLE_OP))
+               if (dst_r != src && !(op & SLJIT_F32_OP))
                        FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
                break;
-       case SLJIT_CONVD_FROMS:
+       case SLJIT_CONV_F64_FROM_F32:
                FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | DA(dst_r) | S2A(src), MOVABLE_INS));
-               op ^= SLJIT_SINGLE_OP;
+               op ^= SLJIT_F32_OP;
                break;
        }
 
@@ -1087,12 +1113,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si dst_r, flags = 0;
+       sljit_s32 dst_r, flags = 0;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1146,19 +1172,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
                src2 = TMP_FREG2;
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DADD:
+       case SLJIT_ADD_F64:
                FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
                break;
 
-       case SLJIT_DSUB:
+       case SLJIT_SUB_F64:
                FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
                break;
 
-       case SLJIT_DMUL:
+       case SLJIT_MUL_F64:
                FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
                break;
 
-       case SLJIT_DDIV:
+       case SLJIT_DIV_F64:
                FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
                break;
        }
@@ -1176,16 +1202,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
 /*  Other instructions                                                   */
 /* --------------------------------------------------------------------- */
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       /* For UNUSED dst. Uncommon, but possible. */
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
-
        if (FAST_IS_REG(dst))
                return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst));
 
@@ -1193,7 +1215,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
        return emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
@@ -1231,33 +1253,33 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
        return label;
 }
 
-static sljit_ins get_cc(sljit_si type)
+static sljit_ins get_cc(sljit_s32 type)
 {
        switch (type) {
        case SLJIT_EQUAL:
        case SLJIT_MUL_NOT_OVERFLOW:
-       case SLJIT_D_NOT_EQUAL: /* Unordered. */
+       case SLJIT_NOT_EQUAL_F64: /* Unordered. */
                return DA(0x1);
 
        case SLJIT_NOT_EQUAL:
        case SLJIT_MUL_OVERFLOW:
-       case SLJIT_D_EQUAL:
+       case SLJIT_EQUAL_F64:
                return DA(0x9);
 
        case SLJIT_LESS:
-       case SLJIT_D_GREATER: /* Unordered. */
+       case SLJIT_GREATER_F64: /* Unordered. */
                return DA(0x5);
 
        case SLJIT_GREATER_EQUAL:
-       case SLJIT_D_LESS_EQUAL:
+       case SLJIT_LESS_EQUAL_F64:
                return DA(0xd);
 
        case SLJIT_GREATER:
-       case SLJIT_D_GREATER_EQUAL: /* Unordered. */
+       case SLJIT_GREATER_EQUAL_F64: /* Unordered. */
                return DA(0xc);
 
        case SLJIT_LESS_EQUAL:
-       case SLJIT_D_LESS:
+       case SLJIT_LESS_F64:
                return DA(0x4);
 
        case SLJIT_SIG_LESS:
@@ -1273,20 +1295,20 @@ static sljit_ins get_cc(sljit_si type)
                return DA(0x2);
 
        case SLJIT_OVERFLOW:
-       case SLJIT_D_UNORDERED:
+       case SLJIT_UNORDERED_F64:
                return DA(0x7);
 
        case SLJIT_NOT_OVERFLOW:
-       case SLJIT_D_ORDERED:
+       case SLJIT_ORDERED_F64:
                return DA(0xf);
 
        default:
-               SLJIT_ASSERT_STOP();
+               SLJIT_UNREACHABLE();
                return DA(0x8);
        }
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
        struct sljit_jump *jump;
 
@@ -1298,7 +1320,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
        set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
        type &= 0xff;
 
-       if (type < SLJIT_D_EQUAL) {
+       if (type < SLJIT_EQUAL_F64) {
                jump->flags |= IS_COND;
                if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & ICC_IS_SET))
                        jump->flags |= IS_MOVABLE;
@@ -1332,10 +1354,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
        return jump;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
        struct sljit_jump *jump = NULL;
-       sljit_si src_r;
+       sljit_s32 src_r;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
@@ -1367,35 +1389,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
        return push_inst(compiler, NOP, UNMOVABLE_INS);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type)
 {
-       sljit_si reg, flags = (GET_FLAGS(op) ? SET_FLAGS : 0);
+       sljit_s32 reg, flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
 
        CHECK_ERROR();
-       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
+       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
-
 #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
        op = GET_OPCODE(op);
        reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
 
        compiler->cache_arg = 0;
        compiler->cache_argw = 0;
-       if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
-               ADJUST_LOCAL_OFFSET(src, srcw);
-               FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
-               src = TMP_REG1;
-               srcw = 0;
-       }
+
+       if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+               FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
 
        type &= 0xff;
-       if (type < SLJIT_D_EQUAL)
+       if (type < SLJIT_EQUAL_F64)
                FAIL_IF(push_inst(compiler, BICC | get_cc(type) | 3, UNMOVABLE_INS));
        else
                FAIL_IF(push_inst(compiler, FBFCC | get_cc(type) | 3, UNMOVABLE_INS));
@@ -1403,18 +1418,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
        FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS));
        FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS));
 
-       if (op >= SLJIT_ADD)
-               return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
+       if (op >= SLJIT_ADD) {
+               flags |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;
+               if (dst & SLJIT_MEM)
+                       return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+               return emit_op(compiler, op, flags, dst, 0, dst, 0, TMP_REG2, 0);
+       }
+
+       if (!(dst & SLJIT_MEM))
+               return SLJIT_SUCCESS;
+
+       return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);
+#else
+#error "Implementation required"
+#endif
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+       CHECK_ERROR();
+       CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
 
-       return (reg == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+       return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
 #else
 #error "Implementation required"
 #endif
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+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_si reg;
+       sljit_s32 reg;
        struct sljit_const *const_;
 
        CHECK_ERROR_PTR();
@@ -1425,7 +1461,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
        PTR_FAIL_IF(!const_);
        set_const(const_, compiler);
 
-       reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+       reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
 
        PTR_FAIL_IF(emit_const(compiler, reg, init_value));
 
index 719632908c89f6102f9caad4675df2d767d8b1ff..dd82ebae6a9cd588f6612da0763473f51f6091d6 100644 (file)
@@ -2,7 +2,7 @@
  *    Stack-less Just-In-Time compiler
  *
  *    Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
index 4d40392fa82f005eed63ba3fb3fb5e73bb3484e3..003f43a79091dd7370953feb4e71aff3a13b8f0e 100644 (file)
@@ -2,7 +2,7 @@
  *    Stack-less Just-In-Time compiler
  *
  *    Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -49,7 +49,7 @@
 #define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5)
 #define PIC_ADDR_REG TMP_REG2
 
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
        63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7
 };
 
@@ -106,7 +106,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
  */
 #define CHECK_FLAGS(list) (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list))))
 
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char *sljit_get_platform_name(void)
+SLJIT_API_FUNC_ATTRIBUTE const char *sljit_get_platform_name(void)
 {
        return "TileGX" SLJIT_CPUINFO;
 }
@@ -307,7 +307,7 @@ struct jit_instr {
 #define JOFF_X1(x) create_JumpOff_X1(x)
 #define BOFF_X1(x) create_BrOff_X1(x)
 
-static SLJIT_CONST tilegx_mnemonic data_transfer_insts[16] = {
+static const tilegx_mnemonic data_transfer_insts[16] = {
        /* u w s */ TILEGX_OPC_ST   /* st */,
        /* u w l */ TILEGX_OPC_LD   /* ld */,
        /* u b s */ TILEGX_OPC_ST1  /* st1 */,
@@ -327,7 +327,7 @@ static SLJIT_CONST tilegx_mnemonic data_transfer_insts[16] = {
 };
 
 #ifdef TILEGX_JIT_DEBUG
-static sljit_si push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins, int line)
+static sljit_s32 push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins, int line)
 {
        sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
        FAIL_IF(!ptr);
@@ -338,7 +338,7 @@ static sljit_si push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins)
+static sljit_s32 push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins)
 {
        sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
        FAIL_IF(!ptr);
@@ -349,7 +349,7 @@ static sljit_si push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins
 
 #define push_inst(a, b) push_inst_debug(a, b, __LINE__)
 #else
-static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
 {
        sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
        FAIL_IF(!ptr);
@@ -557,7 +557,7 @@ const struct Format* compute_format()
        return match;
 }
 
-sljit_si assign_pipes()
+sljit_s32 assign_pipes()
 {
        unsigned long output_registers = 0;
        unsigned int i = 0;
@@ -621,7 +621,7 @@ tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst)
        return bits;
 }
 
-static sljit_si update_buffer(struct sljit_compiler *compiler)
+static sljit_s32 update_buffer(struct sljit_compiler *compiler)
 {
        int i;
        int orig_index = inst_buf_index;
@@ -687,7 +687,7 @@ static sljit_si update_buffer(struct sljit_compiler *compiler)
                        inst_buf[0] = inst1;
                        inst_buf_index = 1;
                } else
-                       SLJIT_ASSERT_STOP();
+                       SLJIT_UNREACHABLE();
 
 #ifdef TILEGX_JIT_DEBUG
                return push_inst_nodebug(compiler, bits);
@@ -727,13 +727,13 @@ static sljit_si update_buffer(struct sljit_compiler *compiler)
                        return push_inst(compiler, bits);
 #endif
                } else
-                       SLJIT_ASSERT_STOP();
+                       SLJIT_UNREACHABLE();
        }
 
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
 }
 
-static sljit_si flush_buffer(struct sljit_compiler *compiler)
+static sljit_s32 flush_buffer(struct sljit_compiler *compiler)
 {
        while (inst_buf_index != 0) {
                FAIL_IF(update_buffer(compiler));
@@ -741,7 +741,7 @@ static sljit_si flush_buffer(struct sljit_compiler *compiler)
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line)
+static sljit_s32 push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line)
 {
        if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
                FAIL_IF(update_buffer(compiler));
@@ -761,7 +761,7 @@ static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int line)
+static sljit_s32 push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int line)
 {
        if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
                FAIL_IF(update_buffer(compiler));
@@ -814,7 +814,7 @@ static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
                break;
        default:
                printf("unrecoginzed opc: %s\n", opcode->name);
-               SLJIT_ASSERT_STOP();
+               SLJIT_UNREACHABLE();
        }
 
        inst_buf_index++;
@@ -822,7 +822,7 @@ static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int line)
+static sljit_s32 push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int line)
 {
        if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
                FAIL_IF(update_buffer(compiler));
@@ -859,7 +859,7 @@ static sljit_si push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
                break;
        default:
                printf("unrecoginzed opc: %s\n", opcode->name);
-               SLJIT_ASSERT_STOP();
+               SLJIT_UNREACHABLE();
        }
 
        inst_buf_index++;
@@ -867,7 +867,7 @@ static sljit_si push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int line)
+static sljit_s32 push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int line)
 {
        if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
                FAIL_IF(update_buffer(compiler));
@@ -883,7 +883,7 @@ static sljit_si push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
        return SLJIT_SUCCESS;
 }
 
-static sljit_si push_jr_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int line)
+static sljit_s32 push_jr_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int line)
 {
        if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)
                FAIL_IF(update_buffer(compiler));
@@ -1117,7 +1117,7 @@ SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compi
        return code;
 }
 
-static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
 {
 
        if (imm <= SIMM_16BIT_MAX && imm >= SIMM_16BIT_MIN)
@@ -1140,7 +1140,7 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
        return SHL16INSLI(dst_ar, dst_ar, imm);
 }
 
-static sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm, int flush)
+static sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush)
 {
        /* Should *not* be optimized as load_immediate, as pcre relocation
           mechanism will match this fixed 4-instruction pattern. */
@@ -1155,7 +1155,7 @@ static sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst_ar, slj
        return SHL16INSLI(dst_ar, dst_ar, imm);
 }
 
-static sljit_si emit_const_64(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm, int flush)
+static sljit_s32 emit_const_64(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush)
 {
        /* Should *not* be optimized as load_immediate, as pcre relocation
           mechanism will match this fixed 4-instruction pattern. */
@@ -1172,12 +1172,12 @@ static sljit_si emit_const_64(struct sljit_compiler *compiler, sljit_si dst_ar,
        return SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
        sljit_ins base;
-       sljit_si i, tmp;
+       sljit_s32 i, tmp;
  
        CHECK_ERROR();
        CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -1222,9 +1222,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
        CHECK_ERROR();
        CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -1236,12 +1236,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si local_size;
+       sljit_s32 local_size;
        sljit_ins base;
-       sljit_si i, tmp;
-       sljit_si saveds;
+       sljit_s32 i, tmp;
+       sljit_s32 saveds;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_return(compiler, op, src, srcw));
@@ -1285,7 +1285,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
 /* reg_ar is an absoulute register! */
 
 /* Can perform an operation using at most 1 instruction. */
-static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
 {
        SLJIT_ASSERT(arg & SLJIT_MEM);
 
@@ -1311,7 +1311,7 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
 /* See getput_arg below.
    Note: can_cache is called only for binary operators. Those
    operators always uses word arguments without write back. */
-static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
        SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
 
@@ -1337,9 +1337,9 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
 }
 
 /* Emit the necessary instructions. See can_cache above. */
-static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
 {
-       sljit_si tmp_ar, base;
+       sljit_s32 tmp_ar, base;
 
        SLJIT_ASSERT(arg & SLJIT_MEM);
        if (!(next_arg & SLJIT_MEM)) {
@@ -1530,7 +1530,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
                return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);
 }
 
-static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg_ar, sljit_si arg, sljit_sw argw)
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
 {
        if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
                return compiler->error;
@@ -1540,14 +1540,14 @@ static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_
        return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0);
 }
 
-static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
 {
        if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
                return compiler->error;
        return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
@@ -1564,7 +1564,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
        return emit_op_mem(compiler, WORD_DATA, RA, dst, dstw);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
@@ -1582,9 +1582,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
        return JR(RA);
 }
 
-static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags, sljit_si dst, sljit_si src1, sljit_sw src2)
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
 {
-       sljit_si overflow_ra = 0;
+       sljit_s32 overflow_ra = 0;
 
        switch (GET_OPCODE(op)) {
        case SLJIT_MOV:
@@ -1594,11 +1594,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                        return ADD(reg_map[dst], reg_map[src2], ZERO);
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UI:
-       case SLJIT_MOV_SI:
+       case SLJIT_MOV_U32:
+       case SLJIT_MOV_S32:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SI)
+                       if (op == SLJIT_MOV_S32)
                                return BFEXTS(reg_map[dst], reg_map[src2], 0, 31);
 
                        return BFEXTU(reg_map[dst], reg_map[src2], 0, 31);
@@ -1609,11 +1609,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
 
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UB:
-       case SLJIT_MOV_SB:
+       case SLJIT_MOV_U8:
+       case SLJIT_MOV_S8:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SB)
+                       if (op == SLJIT_MOV_S8)
                                return BFEXTS(reg_map[dst], reg_map[src2], 0, 7);
 
                        return BFEXTU(reg_map[dst], reg_map[src2], 0, 7);
@@ -1624,11 +1624,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
 
                return SLJIT_SUCCESS;
 
-       case SLJIT_MOV_UH:
-       case SLJIT_MOV_SH:
+       case SLJIT_MOV_U16:
+       case SLJIT_MOV_S16:
                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
-                       if (op == SLJIT_MOV_SH)
+                       if (op == SLJIT_MOV_S16)
                                return BFEXTS(reg_map[dst], reg_map[src2], 0, 15);
 
                        return BFEXTU(reg_map[dst], reg_map[src2], 0, 15);
@@ -1952,20 +1952,20 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
                return SLJIT_SUCCESS;
        }
 
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)
 {
        /* arg1 goes to TMP_REG1 or src reg.
           arg2 goes to TMP_REG2, imm or src reg.
           TMP_REG3 can be used for caching.
           result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
-       sljit_si dst_r = TMP_REG2;
-       sljit_si src1_r;
+       sljit_s32 dst_r = TMP_REG2;
+       sljit_s32 src1_r;
        sljit_sw src2_r = 0;
-       sljit_si sugg_src2_r = TMP_REG2;
+       sljit_s32 sugg_src2_r = TMP_REG2;
 
        if (!(flags & ALT_KEEP_CACHE)) {
                compiler->cache_arg = 0;
@@ -1973,14 +1973,14 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
        }
 
        if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
+               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM))
                        return SLJIT_SUCCESS;
                if (GET_FLAGS(op))
                        flags |= UNUSED_DEST;
        } else if (FAST_IS_REG(dst)) {
                dst_r = dst;
                flags |= REG_DEST;
-               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
                        sugg_src2_r = dst_r;
        } else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1_mapped, dst, dstw))
                flags |= SLOW_DEST;
@@ -2033,7 +2033,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
        if (FAST_IS_REG(src2)) {
                src2_r = src2;
                flags |= REG2_SOURCE;
-               if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+               if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
                        dst_r = src2_r;
        } else if (src2 & SLJIT_IMM) {
                if (!(flags & SRC2_IMM)) {
@@ -2042,7 +2042,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
                                src2_r = sugg_src2_r;
                        } else {
                                src2_r = 0;
-                               if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) && (dst & SLJIT_MEM))
+                               if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))
                                        dst_r = 0;
                        }
                }
@@ -2082,21 +2082,18 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw, sljit_s32 type)
 {
-       sljit_si sugg_dst_ar, dst_ar;
-       sljit_si flags = GET_ALL_FLAGS(op);
-       sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
+       sljit_s32 sugg_dst_ar, dst_ar;
+       sljit_s32 flags = GET_ALL_FLAGS(op);
+       sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
        ADJUST_LOCAL_OFFSET(dst, dstw);
 
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
-
        op = GET_OPCODE(op);
-       if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI)
+       if (op == SLJIT_MOV_S32 || op == SLJIT_MOV_U32)
                mem_type = INT_DATA | SIGNED_DATA;
        sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2];
 
@@ -2143,7 +2140,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
                break;
 
        default:
-               SLJIT_ASSERT_STOP();
+               SLJIT_UNREACHABLE();
                dst_ar = sugg_dst_ar;
                break;
        }
@@ -2168,7 +2165,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) {
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op0(compiler, op));
 
@@ -2180,17 +2177,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
        case SLJIT_BREAKPOINT:
                return PI(BPT);
 
-       case SLJIT_LUMUL:
-       case SLJIT_LSMUL:
-       case SLJIT_UDIVI:
-       case SLJIT_SDIVI:
-               SLJIT_ASSERT_STOP();
+       case SLJIT_LMUL_UW:
+       case SLJIT_LMUL_SW:
+       case SLJIT_DIVMOD_UW:
+       case SLJIT_DIVMOD_SW:
+       case SLJIT_DIV_UW:
+       case SLJIT_DIV_SW:
+               SLJIT_UNREACHABLE();
        }
 
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
@@ -2202,45 +2201,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        case SLJIT_MOV_P:
                return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOV_UI:
-               return emit_op(compiler, SLJIT_MOV_UI, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+       case SLJIT_MOV_U32:
+               return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOV_SI:
-               return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+       case SLJIT_MOV_S32:
+               return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOV_UB:
-               return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub) srcw : srcw);
+       case SLJIT_MOV_U8:
+               return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw);
 
-       case SLJIT_MOV_SB:
-               return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb) srcw : srcw);
+       case SLJIT_MOV_S8:
+               return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw);
 
-       case SLJIT_MOV_UH:
-               return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh) srcw : srcw);
+       case SLJIT_MOV_U16:
+               return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw);
 
-       case SLJIT_MOV_SH:
-               return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh) srcw : srcw);
+       case SLJIT_MOV_S16:
+               return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw);
 
        case SLJIT_MOVU:
        case SLJIT_MOVU_P:
                return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOVU_UI:
-               return emit_op(compiler, SLJIT_MOV_UI, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+       case SLJIT_MOVU_U32:
+               return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOVU_SI:
-               return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+       case SLJIT_MOVU_S32:
+               return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
 
-       case SLJIT_MOVU_UB:
-               return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub) srcw : srcw);
+       case SLJIT_MOVU_U8:
+               return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw);
 
-       case SLJIT_MOVU_SB:
-               return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb) srcw : srcw);
+       case SLJIT_MOVU_S8:
+               return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw);
 
-       case SLJIT_MOVU_UH:
-               return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh) srcw : srcw);
+       case SLJIT_MOVU_U16:
+               return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw);
 
-       case SLJIT_MOVU_SH:
-               return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh) srcw : srcw);
+       case SLJIT_MOVU_S16:
+               return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw);
 
        case SLJIT_NOT:
                return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
@@ -2249,13 +2248,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
                return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
 
        case SLJIT_CLZ:
-               return emit_op(compiler, op, (op & SLJIT_INT_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+               return emit_op(compiler, op, (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
        }
 
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -2285,7 +2284,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        case SLJIT_ASHR:
                if (src2 & SLJIT_IMM)
                        src2w &= 0x3f;
-               if (op & SLJIT_INT_OP)
+               if (op & SLJIT_I32_OP)
                        src2w &= 0x1f;
 
                return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w);
@@ -2312,9 +2311,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_comp
        return label;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si src_r = TMP_REG2;
+       sljit_s32 src_r = TMP_REG2;
        struct sljit_jump *jump = NULL;
 
        flush_buffer(compiler);
@@ -2401,11 +2400,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
        inst = BNEZ_X1 | SRCA_X1(src); \
        flags = IS_COND;
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
        struct sljit_jump *jump;
        sljit_ins inst;
-       sljit_si flags = 0;
+       sljit_s32 flags = 0;
 
        flush_buffer(compiler);
 
@@ -2485,25 +2484,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
        return jump;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
-{
-       return 0;
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)
 {
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)
 {
-       SLJIT_ASSERT_STOP();
+       SLJIT_UNREACHABLE();
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+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_si reg;
+       sljit_s32 reg;
 
        flush_buffer(compiler);
 
@@ -2524,13 +2518,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp
        return const_;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target)
 {
        sljit_ins *inst = (sljit_ins *)addr;
 
-       inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_addr >> 32) & 0xffff) << 43);
-       inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_addr >> 16) & 0xffff) << 43);
-       inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_addr & 0xffff) << 43);
+       inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_target >> 32) & 0xffff) << 43);
+       inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_target >> 16) & 0xffff) << 43);
+       inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_target & 0xffff) << 43);
        SLJIT_CACHE_FLUSH(inst, inst + 3);
 }
 
@@ -2545,14 +2539,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
        SLJIT_CACHE_FLUSH(inst, inst + 4);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_register_index(reg));
        return reg_map[reg];
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
index d7129c8e26dfcdd853f0c2280f4e6fdaf3c69041..f5cf8834b08424d4c41a76612d4c0ea051e53397 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
 
 /* x86 32-bit arch dependent functions. */
 
-static sljit_si emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_sw imm)
+static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_sw imm)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));
        FAIL_IF(!inst);
        INC_SIZE(1 + sizeof(sljit_sw));
        *inst++ = opcode;
-       *(sljit_sw*)inst = imm;
+       sljit_unaligned_store_sw(inst, imm);
        return SLJIT_SUCCESS;
 }
 
-static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset)
 {
        if (type == SLJIT_JUMP) {
                *code_ptr++ = JMP_i32;
@@ -57,33 +57,54 @@ static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_
        if (jump->flags & JUMP_LABEL)
                jump->flags |= PATCH_MW;
        else
-               *(sljit_sw*)code_ptr = jump->u.target - (jump->addr + 4);
+               sljit_unaligned_store_sw(code_ptr, jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset);
        code_ptr += 4;
 
        return code_ptr;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
-       sljit_si size;
-       sljit_ub *inst;
+       sljit_s32 size;
+       sljit_u8 *inst;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
        set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
 
        compiler->args = args;
-       compiler->flags_saved = 0;
 
-       size = 1 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3);
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+       /* [esp+0] for saving temporaries and third argument for calls. */
+       compiler->saveds_offset = 1 * sizeof(sljit_sw);
+#else
+       /* [esp+0] for saving temporaries and space for maximum three arguments. */
+       if (scratches <= 1)
+               compiler->saveds_offset = 1 * sizeof(sljit_sw);
+       else
+               compiler->saveds_offset = ((scratches == 2) ? 2 : 3) * sizeof(sljit_sw);
+#endif
+
+       if (scratches > 3)
+               compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
+
+       compiler->locals_offset = compiler->saveds_offset;
+
+       if (saveds > 3)
+               compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);
+
+       if (options & SLJIT_F64_ALIGNMENT)
+               compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);
+
+       size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3);
 #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
        size += (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
 #else
        size += (args > 0 ? (2 + args * 3) : 0);
 #endif
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
        FAIL_IF(!inst);
 
        INC_SIZE(size);
@@ -94,11 +115,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
                *inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */;
        }
 #endif
-       if (saveds > 2 || scratches > 7)
+       if (saveds > 2 || scratches > 9)
                PUSH_REG(reg_map[SLJIT_S2]);
-       if (saveds > 1 || scratches > 8)
+       if (saveds > 1 || scratches > 10)
                PUSH_REG(reg_map[SLJIT_S1]);
-       if (saveds > 0 || scratches > 9)
+       if (saveds > 0 || scratches > 11)
                PUSH_REG(reg_map[SLJIT_S0]);
 
 #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
@@ -134,58 +155,71 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        }
 #endif
 
-       SLJIT_COMPILE_ASSERT(SLJIT_LOCALS_OFFSET >= (2 + 4) * sizeof(sljit_uw), require_at_least_two_words);
+       SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0);
+
 #if defined(__APPLE__)
        /* Ignore pushed registers and SLJIT_LOCALS_OFFSET when computing the aligned local size. */
-       saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
+       saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
        local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
 #else
-       if (options & SLJIT_DOUBLE_ALIGNMENT) {
-               local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7);
-
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 17);
-               FAIL_IF(!inst);
-
-               INC_SIZE(17);
-               inst[0] = MOV_r_rm;
-               inst[1] = MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[SLJIT_SP];
-               inst[2] = GROUP_F7;
-               inst[3] = MOD_REG | (0 << 3) | reg_map[SLJIT_SP];
-               *(sljit_sw*)(inst + 4) = 0x4;
-               inst[8] = JNE_i8;
-               inst[9] = 6;
-               inst[10] = GROUP_BINARY_81;
-               inst[11] = MOD_REG | (5 << 3) | reg_map[SLJIT_SP];
-               *(sljit_sw*)(inst + 12) = 0x4;
-               inst[16] = PUSH_r + reg_map[TMP_REG1];
-       }
+       if (options & SLJIT_F64_ALIGNMENT)
+               local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));
        else
-               local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3);
+               local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1));
 #endif
 
        compiler->local_size = local_size;
+
 #ifdef _WIN32
        if (local_size > 1024) {
 #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
                FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
 #else
-               local_size -= SLJIT_LOCALS_OFFSET;
+               /* Space for a single argument. This amount is excluded when the stack is allocated below. */
+               local_size -= sizeof(sljit_sw);
                FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
                FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
-                       SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, SLJIT_LOCALS_OFFSET));
+                       SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, sizeof(sljit_sw)));
 #endif
                FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
        }
 #endif
 
        SLJIT_ASSERT(local_size > 0);
+
+#if !defined(__APPLE__)
+       if (options & SLJIT_F64_ALIGNMENT) {
+               EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SP, 0);
+
+               /* Some space might allocated during sljit_grow_stack() above on WIN32. */
+               FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
+                       SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size + sizeof(sljit_sw)));
+
+#if defined _WIN32 && !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+               if (compiler->local_size > 1024)
+                       FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+                               TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)));
+#endif
+
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 6);
+               FAIL_IF(!inst);
+
+               INC_SIZE(6);
+               inst[0] = GROUP_BINARY_81;
+               inst[1] = MOD_REG | AND | reg_map[SLJIT_SP];
+               sljit_unaligned_store_sw(inst + 2, ~(sizeof(sljit_f64) - 1));
+
+               /* The real local size must be used. */
+               return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), compiler->local_size, TMP_REG1, 0);
+       }
+#endif
        return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
                SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
        CHECK_ERROR();
        CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
@@ -193,44 +227,62 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
 
        compiler->args = args;
 
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+       /* [esp+0] for saving temporaries and third argument for calls. */
+       compiler->saveds_offset = 1 * sizeof(sljit_sw);
+#else
+       /* [esp+0] for saving temporaries and space for maximum three arguments. */
+       if (scratches <= 1)
+               compiler->saveds_offset = 1 * sizeof(sljit_sw);
+       else
+               compiler->saveds_offset = ((scratches == 2) ? 2 : 3) * sizeof(sljit_sw);
+#endif
+
+       if (scratches > 3)
+               compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
+
+       compiler->locals_offset = compiler->saveds_offset;
+
+       if (saveds > 3)
+               compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);
+
+       if (options & SLJIT_F64_ALIGNMENT)
+               compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);
+
 #if defined(__APPLE__)
-       saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
+       saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
        compiler->local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
 #else
-       if (options & SLJIT_DOUBLE_ALIGNMENT)
-               compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7);
+       if (options & SLJIT_F64_ALIGNMENT)
+               compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));
        else
-               compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3);
+               compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1));
 #endif
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si size;
-       sljit_ub *inst;
+       sljit_s32 size;
+       sljit_u8 *inst;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_return(compiler, op, src, srcw));
        SLJIT_ASSERT(compiler->args >= 0);
 
-       compiler->flags_saved = 0;
        FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
 
        SLJIT_ASSERT(compiler->local_size > 0);
-       FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
-               SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
 
 #if !defined(__APPLE__)
-       if (compiler->options & SLJIT_DOUBLE_ALIGNMENT) {
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 3);
-               FAIL_IF(!inst);
-
-               INC_SIZE(3);
-               inst[0] = MOV_r_rm;
-               inst[1] = (reg_map[SLJIT_SP] << 3) | 0x4 /* SIB */;
-               inst[2] = (4 << 3) | reg_map[SLJIT_SP];
-       }
+       if (compiler->options & SLJIT_F64_ALIGNMENT)
+               EMIT_MOV(compiler, SLJIT_SP, 0, SLJIT_MEM1(SLJIT_SP), compiler->local_size)
+       else
+               FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+                       SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
+#else
+       FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+               SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
 #endif
 
        size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) +
@@ -242,16 +294,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
        if (compiler->args > 0)
                size += 2;
 #endif
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
        FAIL_IF(!inst);
 
        INC_SIZE(size);
 
-       if (compiler->saveds > 0 || compiler->scratches > 9)
+       if (compiler->saveds > 0 || compiler->scratches > 11)
                POP_REG(reg_map[SLJIT_S0]);
-       if (compiler->saveds > 1 || compiler->scratches > 8)
+       if (compiler->saveds > 1 || compiler->scratches > 10)
                POP_REG(reg_map[SLJIT_S1]);
-       if (compiler->saveds > 2 || compiler->scratches > 7)
+       if (compiler->saveds > 2 || compiler->scratches > 9)
                POP_REG(reg_map[SLJIT_S2]);
        POP_REG(reg_map[TMP_REG1]);
 #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
@@ -271,16 +323,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
 /* --------------------------------------------------------------------- */
 
 /* Size contains the flags as well. */
-static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
+static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size,
        /* The register or immediate operand. */
-       sljit_si a, sljit_sw imma,
+       sljit_s32 a, sljit_sw imma,
        /* The general operand (not immediate). */
-       sljit_si b, sljit_sw immb)
+       sljit_s32 b, sljit_sw immb)
 {
-       sljit_ub *inst;
-       sljit_ub *buf_ptr;
-       sljit_si flags = size & ~0xf;
-       sljit_si inst_size;
+       sljit_u8 *inst;
+       sljit_u8 *buf_ptr;
+       sljit_s32 flags = size & ~0xf;
+       sljit_s32 inst_size;
 
        /* Both cannot be switched on. */
        SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
@@ -310,7 +362,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
                else if (immb != 0 && !(b & OFFS_REG_MASK)) {
                        /* Immediate operand. */
                        if (immb <= 127 && immb >= -128)
-                               inst_size += sizeof(sljit_sb);
+                               inst_size += sizeof(sljit_s8);
                        else
                                inst_size += sizeof(sljit_sw);
                }
@@ -347,7 +399,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
        else
                SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
        PTR_FAIL_IF(!inst);
 
        /* Encoding the byte. */
@@ -406,7 +458,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
                                if (immb <= 127 && immb >= -128)
                                        *buf_ptr++ = immb; /* 8 bit displacement. */
                                else {
-                                       *(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
+                                       sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
                                        buf_ptr += sizeof(sljit_sw);
                                }
                        }
@@ -418,7 +470,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
        }
        else {
                *buf_ptr++ |= 0x05;
-               *(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
+               sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
                buf_ptr += sizeof(sljit_sw);
        }
 
@@ -426,9 +478,9 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
                if (flags & EX86_BYTE_ARG)
                        *buf_ptr = imma;
                else if (flags & EX86_HALF_ARG)
-                       *(short*)buf_ptr = imma;
+                       sljit_unaligned_store_s16(buf_ptr, imma);
                else if (!(flags & EX86_SHIFT_INS))
-                       *(sljit_sw*)buf_ptr = imma;
+                       sljit_unaligned_store_sw(buf_ptr, imma);
        }
 
        return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
@@ -438,12 +490,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
 /*  Call / return instructions                                           */
 /* --------------------------------------------------------------------- */
 
-static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
+static SLJIT_INLINE sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
 #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
-       inst = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
+       inst = (sljit_u8*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
        FAIL_IF(!inst);
        INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2);
 
@@ -452,7 +504,7 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
        *inst++ = MOV_r_rm;
        *inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0];
 #else
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
        FAIL_IF(!inst);
        INC_SIZE(4 * (type - SLJIT_CALL0));
 
@@ -476,9 +528,9 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
@@ -492,7 +544,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
 
        if (FAST_IS_REG(dst)) {
                /* Unused dest is possible here. */
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                FAIL_IF(!inst);
 
                INC_SIZE(1);
@@ -507,9 +559,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
@@ -518,7 +570,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
        CHECK_EXTRA_REGS(src, srcw, (void)0);
 
        if (FAST_IS_REG(src)) {
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);
                FAIL_IF(!inst);
 
                INC_SIZE(1 + 1);
@@ -530,18 +582,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
                *inst++ = GROUP_FF;
                *inst |= PUSH_rm;
 
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                FAIL_IF(!inst);
                INC_SIZE(1);
        }
        else {
                /* SLJIT_IMM. */
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1);
                FAIL_IF(!inst);
 
                INC_SIZE(5 + 1);
                *inst++ = PUSH_i32;
-               *(sljit_sw*)inst = srcw;
+               sljit_unaligned_store_sw(inst, srcw);
                inst += sizeof(sljit_sw);
        }
 
index 1790d8a4d0a606639302d0d5f8c65da29f6d9bce..039b68c45abd70fad44bd203b5c1f73eff0eaf4b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
 
 /* x86 64-bit arch dependent functions. */
 
-static sljit_si emit_load_imm64(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
+static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));
        FAIL_IF(!inst);
        INC_SIZE(2 + sizeof(sljit_sw));
        *inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
        *inst++ = MOV_r_i32 + (reg_map[reg] & 0x7);
-       *(sljit_sw*)inst = imm;
+       sljit_unaligned_store_sw(inst, imm);
        return SLJIT_SUCCESS;
 }
 
-static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type)
 {
        if (type < SLJIT_JUMP) {
                /* Invert type. */
@@ -47,58 +47,42 @@ static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_
                *code_ptr++ = 10 + 3;
        }
 
-       SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first);
-       *code_ptr++ = REX_W | REX_B;
-       *code_ptr++ = MOV_r_i32 + 1;
+       *code_ptr++ = REX_W | ((reg_map[TMP_REG2] <= 7) ? 0 : REX_B);
+       *code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2];
        jump->addr = (sljit_uw)code_ptr;
 
        if (jump->flags & JUMP_LABEL)
                jump->flags |= PATCH_MD;
        else
-               *(sljit_sw*)code_ptr = jump->u.target;
+               sljit_unaligned_store_sw(code_ptr, jump->u.target);
 
        code_ptr += sizeof(sljit_sw);
-       *code_ptr++ = REX_B;
-       *code_ptr++ = GROUP_FF;
-       *code_ptr++ = (type >= SLJIT_FAST_CALL) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
-
-       return code_ptr;
-}
-
-static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type)
-{
-       sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_si));
-
-       if (delta <= HALFWORD_MAX && delta >= HALFWORD_MIN) {
-               *code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
-               *(sljit_sw*)code_ptr = delta;
-       }
-       else {
-               SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
-               *code_ptr++ = REX_W | REX_B;
-               *code_ptr++ = MOV_r_i32 + 1;
-               *(sljit_sw*)code_ptr = addr;
-               code_ptr += sizeof(sljit_sw);
+       if (reg_map[TMP_REG2] >= 8)
                *code_ptr++ = REX_B;
-               *code_ptr++ = GROUP_FF;
-               *code_ptr++ = (type == 2) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
-       }
+       *code_ptr++ = GROUP_FF;
+       *code_ptr++ = MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2];
 
        return code_ptr;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_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)
 {
-       sljit_si i, tmp, size, saved_register_size;
-       sljit_ub *inst;
+       sljit_s32 i, tmp, size, saved_register_size;
+       sljit_u8 *inst;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
        set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
 
-       compiler->flags_saved = 0;
+#ifdef _WIN64
+       /* Two/four register slots for parameters plus space for xmm6 register if needed. */
+       if (fscratches >= 6 || fsaveds >= 1)
+               compiler->locals_offset = 6 * sizeof(sljit_sw);
+       else
+               compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);
+#endif
 
        /* Including the return address saved by the call instruction. */
        saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
@@ -106,7 +90,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
        for (i = SLJIT_S0; i >= tmp; i--) {
                size = reg_map[i] >= 8 ? 2 : 1;
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
                FAIL_IF(!inst);
                INC_SIZE(size);
                if (reg_map[i] >= 8)
@@ -116,7 +100,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
 
        for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
                size = reg_map[i] >= 8 ? 2 : 1;
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
                FAIL_IF(!inst);
                INC_SIZE(size);
                if (reg_map[i] >= 8)
@@ -126,7 +110,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
 
        if (args > 0) {
                size = args * 3;
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
                FAIL_IF(!inst);
 
                INC_SIZE(size);
@@ -172,12 +156,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
 #ifdef _WIN64
        if (local_size > 1024) {
                /* Allocate stack for the callback, which grows the stack. */
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_si)));
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_s32)));
                FAIL_IF(!inst);
-               INC_SIZE(4 + (3 + sizeof(sljit_si)));
+               INC_SIZE(4 + (3 + sizeof(sljit_s32)));
                *inst++ = REX_W;
                *inst++ = GROUP_BINARY_83;
-               *inst++ = MOD_REG | SUB | 4;
+               *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
                /* Allocated size for registers must be divisible by 8. */
                SLJIT_ASSERT(!(saved_register_size & 0x7));
                /* Aligned to 16 byte. */
@@ -189,11 +173,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
                        local_size -= 4 * sizeof(sljit_sw);
                }
                /* Second instruction */
-               SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] < 8, temporary_reg1_is_loreg);
+               SLJIT_ASSERT(reg_map[SLJIT_R0] < 8);
                *inst++ = REX_W;
                *inst++ = MOV_rm_i32;
                *inst++ = MOD_REG | reg_lmap[SLJIT_R0];
-               *(sljit_si*)inst = local_size;
+               sljit_unaligned_store_s32(inst, local_size);
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
                        || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
                compiler->skip_checks = 1;
@@ -202,103 +186,112 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
        }
 #endif
 
-       SLJIT_ASSERT(local_size > 0);
-       if (local_size <= 127) {
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
-               FAIL_IF(!inst);
-               INC_SIZE(4);
-               *inst++ = REX_W;
-               *inst++ = GROUP_BINARY_83;
-               *inst++ = MOD_REG | SUB | 4;
-               *inst++ = local_size;
-       }
-       else {
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
-               FAIL_IF(!inst);
-               INC_SIZE(7);
-               *inst++ = REX_W;
-               *inst++ = GROUP_BINARY_81;
-               *inst++ = MOD_REG | SUB | 4;
-               *(sljit_si*)inst = local_size;
-               inst += sizeof(sljit_si);
+       if (local_size > 0) {
+               if (local_size <= 127) {
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+                       FAIL_IF(!inst);
+                       INC_SIZE(4);
+                       *inst++ = REX_W;
+                       *inst++ = GROUP_BINARY_83;
+                       *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
+                       *inst++ = local_size;
+               }
+               else {
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
+                       FAIL_IF(!inst);
+                       INC_SIZE(7);
+                       *inst++ = REX_W;
+                       *inst++ = GROUP_BINARY_81;
+                       *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
+                       sljit_unaligned_store_s32(inst, local_size);
+                       inst += sizeof(sljit_s32);
+               }
        }
 
 #ifdef _WIN64
        /* Save xmm6 register: movaps [rsp + 0x20], xmm6 */
        if (fscratches >= 6 || fsaveds >= 1) {
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
                FAIL_IF(!inst);
                INC_SIZE(5);
                *inst++ = GROUP_0F;
-               *(sljit_si*)inst = 0x20247429;
+               sljit_unaligned_store_s32(inst, 0x20247429);
        }
 #endif
 
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
-       sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
-       sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(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)
 {
-       sljit_si saved_register_size;
+       sljit_s32 saved_register_size;
 
        CHECK_ERROR();
        CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
        set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
 
+#ifdef _WIN64
+       /* Two/four register slots for parameters plus space for xmm6 register if needed. */
+       if (fscratches >= 6 || fsaveds >= 1)
+               compiler->locals_offset = 6 * sizeof(sljit_sw);
+       else
+               compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);
+#endif
+
        /* Including the return address saved by the call instruction. */
        saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
        compiler->local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size;
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si i, tmp, size;
-       sljit_ub *inst;
+       sljit_s32 i, tmp, size;
+       sljit_u8 *inst;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_return(compiler, op, src, srcw));
 
-       compiler->flags_saved = 0;
        FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
 
 #ifdef _WIN64
        /* Restore xmm6 register: movaps xmm6, [rsp + 0x20] */
        if (compiler->fscratches >= 6 || compiler->fsaveds >= 1) {
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
                FAIL_IF(!inst);
                INC_SIZE(5);
                *inst++ = GROUP_0F;
-               *(sljit_si*)inst = 0x20247428;
+               sljit_unaligned_store_s32(inst, 0x20247428);
        }
 #endif
 
-       SLJIT_ASSERT(compiler->local_size > 0);
-       if (compiler->local_size <= 127) {
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
-               FAIL_IF(!inst);
-               INC_SIZE(4);
-               *inst++ = REX_W;
-               *inst++ = GROUP_BINARY_83;
-               *inst++ = MOD_REG | ADD | 4;
-               *inst = compiler->local_size;
-       }
-       else {
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
-               FAIL_IF(!inst);
-               INC_SIZE(7);
-               *inst++ = REX_W;
-               *inst++ = GROUP_BINARY_81;
-               *inst++ = MOD_REG | ADD | 4;
-               *(sljit_si*)inst = compiler->local_size;
+       if (compiler->local_size > 0) {
+               if (compiler->local_size <= 127) {
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+                       FAIL_IF(!inst);
+                       INC_SIZE(4);
+                       *inst++ = REX_W;
+                       *inst++ = GROUP_BINARY_83;
+                       *inst++ = MOD_REG | ADD | 4;
+                       *inst = compiler->local_size;
+               }
+               else {
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
+                       FAIL_IF(!inst);
+                       INC_SIZE(7);
+                       *inst++ = REX_W;
+                       *inst++ = GROUP_BINARY_81;
+                       *inst++ = MOD_REG | ADD | 4;
+                       sljit_unaligned_store_s32(inst, compiler->local_size);
+               }
        }
 
        tmp = compiler->scratches;
        for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
                size = reg_map[i] >= 8 ? 2 : 1;
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
                FAIL_IF(!inst);
                INC_SIZE(size);
                if (reg_map[i] >= 8)
@@ -309,7 +302,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
        tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
        for (i = tmp; i <= SLJIT_S0; i++) {
                size = reg_map[i] >= 8 ? 2 : 1;
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
                FAIL_IF(!inst);
                INC_SIZE(size);
                if (reg_map[i] >= 8)
@@ -317,7 +310,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
                POP_REG(reg_lmap[i]);
        }
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
        FAIL_IF(!inst);
        INC_SIZE(1);
        RET();
@@ -328,32 +321,32 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
 /*  Operators                                                            */
 /* --------------------------------------------------------------------- */
 
-static sljit_si emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_sw imm)
+static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sljit_u8 opcode, sljit_sw imm)
 {
-       sljit_ub *inst;
-       sljit_si length = 1 + (rex ? 1 : 0) + sizeof(sljit_si);
+       sljit_u8 *inst;
+       sljit_s32 length = 1 + (rex ? 1 : 0) + sizeof(sljit_s32);
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + length);
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + length);
        FAIL_IF(!inst);
        INC_SIZE(length);
        if (rex)
                *inst++ = rex;
        *inst++ = opcode;
-       *(sljit_si*)inst = imm;
+       sljit_unaligned_store_s32(inst, imm);
        return SLJIT_SUCCESS;
 }
 
-static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
+static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size,
        /* The register or immediate operand. */
-       sljit_si a, sljit_sw imma,
+       sljit_s32 a, sljit_sw imma,
        /* The general operand (not immediate). */
-       sljit_si b, sljit_sw immb)
+       sljit_s32 b, sljit_sw immb)
 {
-       sljit_ub *inst;
-       sljit_ub *buf_ptr;
-       sljit_ub rex = 0;
-       sljit_si flags = size & ~0xf;
-       sljit_si inst_size;
+       sljit_u8 *inst;
+       sljit_u8 *buf_ptr;
+       sljit_u8 rex = 0;
+       sljit_s32 flags = size & ~0xf;
+       sljit_s32 inst_size;
 
        /* The immediate operand must be 32 bit. */
        SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
@@ -387,20 +380,19 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
        if (b & SLJIT_MEM) {
                if (!(b & OFFS_REG_MASK)) {
                        if (NOT_HALFWORD(immb)) {
-                               if (emit_load_imm64(compiler, TMP_REG3, immb))
-                                       return NULL;
+                               PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
                                immb = 0;
                                if (b & REG_MASK)
-                                       b |= TO_OFFS_REG(TMP_REG3);
+                                       b |= TO_OFFS_REG(TMP_REG2);
                                else
-                                       b |= TMP_REG3;
+                                       b |= TMP_REG2;
                        }
                        else if (reg_lmap[b & REG_MASK] == 4)
                                b |= TO_OFFS_REG(SLJIT_SP);
                }
 
                if ((b & REG_MASK) == SLJIT_UNUSED)
-                       inst_size += 1 + sizeof(sljit_si); /* SIB byte required to avoid RIP based addressing. */
+                       inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */
                else {
                        if (reg_map[b & REG_MASK] >= 8)
                                rex |= REX_B;
@@ -408,12 +400,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
                        if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {
                                /* Immediate operand. */
                                if (immb <= 127 && immb >= -128)
-                                       inst_size += sizeof(sljit_sb);
+                                       inst_size += sizeof(sljit_s8);
                                else
-                                       inst_size += sizeof(sljit_si);
+                                       inst_size += sizeof(sljit_s32);
                        }
                        else if (reg_lmap[b & REG_MASK] == 5)
-                               inst_size += sizeof(sljit_sb);
+                               inst_size += sizeof(sljit_s8);
 
                        if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) {
                                inst_size += 1; /* SIB byte. */
@@ -444,7 +436,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
                else if (flags & EX86_HALF_ARG)
                        inst_size += sizeof(short);
                else
-                       inst_size += sizeof(sljit_si);
+                       inst_size += sizeof(sljit_s32);
        }
        else {
                SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
@@ -456,7 +448,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
        if (rex)
                inst_size++;
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
        PTR_FAIL_IF(!inst);
 
        /* Encoding the byte. */
@@ -516,8 +508,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
                                if (immb <= 127 && immb >= -128)
                                        *buf_ptr++ = immb; /* 8 bit displacement. */
                                else {
-                                       *(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
-                                       buf_ptr += sizeof(sljit_si);
+                                       sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */
+                                       buf_ptr += sizeof(sljit_s32);
                                }
                        }
                }
@@ -533,17 +525,17 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
        else {
                *buf_ptr++ |= 0x04;
                *buf_ptr++ = 0x25;
-               *(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
-               buf_ptr += sizeof(sljit_si);
+               sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */
+               buf_ptr += sizeof(sljit_s32);
        }
 
        if (a & SLJIT_IMM) {
                if (flags & EX86_BYTE_ARG)
                        *buf_ptr = imma;
                else if (flags & EX86_HALF_ARG)
-                       *(short*)buf_ptr = imma;
+                       sljit_unaligned_store_s16(buf_ptr, imma);
                else if (!(flags & EX86_SHIFT_INS))
-                       *(sljit_si*)buf_ptr = imma;
+                       sljit_unaligned_store_s32(buf_ptr, imma);
        }
 
        return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
@@ -553,17 +545,19 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
 /*  Call / return instructions                                           */
 /* --------------------------------------------------------------------- */
 
-static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
+       /* After any change update IS_REG_CHANGED_BY_CALL as well. */
 #ifndef _WIN64
-       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
+       SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8 && reg_map[TMP_REG1] == 2);
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
        FAIL_IF(!inst);
        INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
        if (type >= SLJIT_CALL3) {
+               /* Move third argument to TMP_REG1. */
                *inst++ = REX_W;
                *inst++ = MOV_r_rm;
                *inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_R2];
@@ -572,12 +566,13 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
        *inst++ = MOV_r_rm;
        *inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_R0];
 #else
-       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers);
+       SLJIT_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8 && reg_map[TMP_REG1] == 8);
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
        FAIL_IF(!inst);
        INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
        if (type >= SLJIT_CALL3) {
+               /* Move third argument to TMP_REG1. */
                *inst++ = REX_W | REX_R;
                *inst++ = MOV_r_rm;
                *inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_R2];
@@ -589,9 +584,9 @@ static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, slj
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
@@ -603,14 +598,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
 
        if (FAST_IS_REG(dst)) {
                if (reg_map[dst] < 8) {
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                        FAIL_IF(!inst);
                        INC_SIZE(1);
                        POP_REG(reg_lmap[dst]);
                        return SLJIT_SUCCESS;
                }
 
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
                FAIL_IF(!inst);
                INC_SIZE(2);
                *inst++ = REX_B;
@@ -626,9 +621,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
@@ -641,14 +636,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
 
        if (FAST_IS_REG(src)) {
                if (reg_map[src] < 8) {
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);
                        FAIL_IF(!inst);
 
                        INC_SIZE(1 + 1);
                        PUSH_REG(reg_lmap[src]);
                }
                else {
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 1);
                        FAIL_IF(!inst);
 
                        INC_SIZE(2 + 1);
@@ -664,20 +659,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
                *inst++ = GROUP_FF;
                *inst |= PUSH_rm;
 
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                FAIL_IF(!inst);
                INC_SIZE(1);
        }
        else {
                SLJIT_ASSERT(IS_HALFWORD(srcw));
                /* SLJIT_IMM. */
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1);
                FAIL_IF(!inst);
 
                INC_SIZE(5 + 1);
                *inst++ = PUSH_i32;
-               *(sljit_si*)inst = srcw;
-               inst += sizeof(sljit_si);
+               sljit_unaligned_store_s32(inst, srcw);
+               inst += sizeof(sljit_s32);
        }
 
        RET();
@@ -689,12 +684,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
 /*  Extend input                                                         */
 /* --------------------------------------------------------------------- */
 
-static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub* inst;
-       sljit_si dst_r;
+       sljit_u8* inst;
+       sljit_s32 dst_r;
 
        compiler->mode32 = 0;
 
@@ -704,7 +699,7 @@ static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
        if (src & SLJIT_IMM) {
                if (FAST_IS_REG(dst)) {
                        if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
-                               inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
+                               inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);
                                FAIL_IF(!inst);
                                *inst = MOV_rm_i32;
                                return SLJIT_SUCCESS;
@@ -712,7 +707,7 @@ static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
                        return emit_load_imm64(compiler, dst, srcw);
                }
                compiler->mode32 = 1;
-               inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
+               inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);
                FAIL_IF(!inst);
                *inst = MOV_rm_i32;
                compiler->mode32 = 0;
index 416c15afafa6a6180a1fc51296c3208d9fcb477b..eb0886d67151488661c865f0f1f880c54e5dd558 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -24,7 +24,7 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
 {
        return "x86" SLJIT_CPUINFO;
 }
@@ -66,13 +66,16 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
 /* Last register + 1. */
 #define TMP_REG1       (SLJIT_NUMBER_OF_REGISTERS + 2)
 
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
-       0, 0, 2, 1, 0, 0, 0, 0, 7, 6, 3, 4, 5
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
+       0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 7, 6, 3, 4, 5
 };
 
 #define CHECK_EXTRA_REGS(p, w, do) \
-       if (p >= SLJIT_R3 && p <= SLJIT_R6) { \
-               w = SLJIT_LOCALS_OFFSET + ((p) - (SLJIT_R3 + 4)) * sizeof(sljit_sw); \
+       if (p >= SLJIT_R3 && p <= SLJIT_S3) { \
+               if (p <= compiler->scratches) \
+                       w = compiler->saveds_offset - ((p) - SLJIT_R2) * (sljit_sw)sizeof(sljit_sw); \
+               else \
+                       w = compiler->locals_offset + ((p) - SLJIT_S2) * (sljit_sw)sizeof(sljit_sw); \
                p = SLJIT_MEM1(SLJIT_SP); \
                do; \
        }
@@ -82,28 +85,27 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
 /* Last register + 1. */
 #define TMP_REG1       (SLJIT_NUMBER_OF_REGISTERS + 2)
 #define TMP_REG2       (SLJIT_NUMBER_OF_REGISTERS + 3)
-#define TMP_REG3       (SLJIT_NUMBER_OF_REGISTERS + 4)
 
 /* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present
    Note: avoid to use r12 and r13 for memory addessing
-   therefore r12 is better for SAVED_EREG than SAVED_REG. */
+   therefore r12 is better to be a higher saved register. */
 #ifndef _WIN64
-/* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
-       0, 0, 6, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 7, 9
+/* Args: rdi(=7), rsi(=6), rdx(=2), rcx(=1), r8, r9. Scratches: rax(=0), r10, r11 */
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+       0, 0, 6, 1, 7, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9
 };
 /* low-map. reg_map & 0x7. */
-static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
-       0, 0, 6, 1, 0, 3,  2,  4,  5,  5,  6,  7, 3, 4, 2, 7, 1
+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+       0, 0, 6, 1, 7, 0, 3,  2,  4,  5,  5,  6,  7, 3, 4, 2, 1
 };
 #else
-/* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
-       0, 0, 2, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 10, 8, 9
+/* Args: rcx(=1), rdx(=2), r8, r9. Scratches: rax(=0), r10, r11 */
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+       0, 0, 2, 1, 10, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 8, 9
 };
 /* low-map. reg_map & 0x7. */
-static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
-       0, 0, 2, 1, 3,  4,  5,  5, 6,  7,  7, 6, 3, 4, 2,  0, 1
+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+       0, 0, 2, 1, 2,  3,  4,  5,  5, 6,  7,  7, 6, 3, 4, 0, 1
 };
 #endif
 
@@ -166,7 +168,7 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
 #define CALL_i32       0xe8
 #define CALL_rm                (/* GROUP_FF */ 2 << 3)
 #define CDQ            0x99
-#define CMOVNE_r_rm    (/* GROUP_0F */ 0x45)
+#define CMOVE_r_rm     (/* GROUP_0F */ 0x44)
 #define CMP            (/* BINARY */ 7 << 3)
 #define CMP_EAX_i32    0x3d
 #define CMP_r_rm       0x3b
@@ -214,6 +216,7 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
 #define POP_r          0x58
 #define POP_rm         0x8f
 #define POPF           0x9d
+#define PREFETCH       0x18
 #define PUSH_i32       0x68
 #define PUSH_r         0x50
 #define PUSH_rm                (/* GROUP_FF */ 6 << 3)
@@ -269,9 +272,9 @@ static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = {
    built-in CPU features. Therefore they can be overwritten by different threads
    if they detect the CPU features in the same time. */
 #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
-static sljit_si cpu_has_sse2 = -1;
+static sljit_s32 cpu_has_sse2 = -1;
 #endif
-static sljit_si cpu_has_cmov = -1;
+static sljit_s32 cpu_has_cmov = -1;
 
 #ifdef _WIN32_WCE
 #include <cmnintrin.h>
@@ -279,15 +282,38 @@ static sljit_si cpu_has_cmov = -1;
 #include <intrin.h>
 #endif
 
+/******************************************************/
+/*    Unaligned-store functions                       */
+/******************************************************/
+
+static SLJIT_INLINE void sljit_unaligned_store_s16(void *addr, sljit_s16 value)
+{
+       SLJIT_MEMCPY(addr, &value, sizeof(value));
+}
+
+static SLJIT_INLINE void sljit_unaligned_store_s32(void *addr, sljit_s32 value)
+{
+       SLJIT_MEMCPY(addr, &value, sizeof(value));
+}
+
+static SLJIT_INLINE void sljit_unaligned_store_sw(void *addr, sljit_sw value)
+{
+       SLJIT_MEMCPY(addr, &value, sizeof(value));
+}
+
+/******************************************************/
+/*    Utility functions                               */
+/******************************************************/
+
 static void get_cpu_features(void)
 {
-       sljit_ui features;
+       sljit_u32 features;
 
 #if defined(_MSC_VER) && _MSC_VER >= 1400
 
        int CPUInfo[4];
        __cpuid(CPUInfo, 1);
-       features = (sljit_ui)CPUInfo[3];
+       features = (sljit_u32)CPUInfo[3];
 
 #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C)
 
@@ -330,31 +356,31 @@ static void get_cpu_features(void)
        cpu_has_cmov = (features >> 15) & 0x1;
 }
 
-static sljit_ub get_jump_code(sljit_si type)
+static sljit_u8 get_jump_code(sljit_s32 type)
 {
        switch (type) {
        case SLJIT_EQUAL:
-       case SLJIT_D_EQUAL:
+       case SLJIT_EQUAL_F64:
                return 0x84 /* je */;
 
        case SLJIT_NOT_EQUAL:
-       case SLJIT_D_NOT_EQUAL:
+       case SLJIT_NOT_EQUAL_F64:
                return 0x85 /* jne */;
 
        case SLJIT_LESS:
-       case SLJIT_D_LESS:
+       case SLJIT_LESS_F64:
                return 0x82 /* jc */;
 
        case SLJIT_GREATER_EQUAL:
-       case SLJIT_D_GREATER_EQUAL:
+       case SLJIT_GREATER_EQUAL_F64:
                return 0x83 /* jae */;
 
        case SLJIT_GREATER:
-       case SLJIT_D_GREATER:
+       case SLJIT_GREATER_F64:
                return 0x87 /* jnbe */;
 
        case SLJIT_LESS_EQUAL:
-       case SLJIT_D_LESS_EQUAL:
+       case SLJIT_LESS_EQUAL_F64:
                return 0x86 /* jbe */;
 
        case SLJIT_SIG_LESS:
@@ -377,30 +403,31 @@ static sljit_ub get_jump_code(sljit_si type)
        case SLJIT_MUL_NOT_OVERFLOW:
                return 0x81 /* jno */;
 
-       case SLJIT_D_UNORDERED:
+       case SLJIT_UNORDERED_F64:
                return 0x8a /* jp */;
 
-       case SLJIT_D_ORDERED:
+       case SLJIT_ORDERED_F64:
                return 0x8b /* jpo */;
        }
        return 0;
 }
 
-static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type);
-
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type);
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset);
+#else
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type);
 #endif
 
-static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_ub *code, sljit_si type)
+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)
 {
-       sljit_si short_jump;
+       sljit_s32 short_jump;
        sljit_uw label_addr;
 
        if (jump->flags & JUMP_LABEL)
                label_addr = (sljit_uw)(code + jump->u.label->size);
        else
-               label_addr = jump->u.target;
+               label_addr = jump->u.target - executable_offset;
+
        short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127;
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -432,13 +459,13 @@ static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code
 
        if (short_jump) {
                jump->flags |= PATCH_MB;
-               code_ptr += sizeof(sljit_sb);
+               code_ptr += sizeof(sljit_s8);
        } else {
                jump->flags |= PATCH_MW;
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                code_ptr += sizeof(sljit_sw);
 #else
-               code_ptr += sizeof(sljit_si);
+               code_ptr += sizeof(sljit_s32);
 #endif
        }
 
@@ -448,11 +475,13 @@ static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code
 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
 {
        struct sljit_memory_fragment *buf;
-       sljit_ub *code;
-       sljit_ub *code_ptr;
-       sljit_ub *buf_ptr;
-       sljit_ub *buf_end;
-       sljit_ub len;
+       sljit_u8 *code;
+       sljit_u8 *code_ptr;
+       sljit_u8 *buf_ptr;
+       sljit_u8 *buf_end;
+       sljit_u8 len;
+       sljit_sw executable_offset;
+       sljit_sw jump_addr;
 
        struct sljit_label *label;
        struct sljit_jump *jump;
@@ -463,7 +492,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        reverse_buf(compiler);
 
        /* Second code generation pass. */
-       code = (sljit_ub*)SLJIT_MALLOC_EXEC(compiler->size);
+       code = (sljit_u8*)SLJIT_MALLOC_EXEC(compiler->size);
        PTR_FAIL_WITH_EXEC_IF(code);
        buf = compiler->buf;
 
@@ -471,6 +500,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
        label = compiler->labels;
        jump = compiler->jumps;
        const_ = compiler->consts;
+       executable_offset = SLJIT_EXEC_OFFSET(code);
+
        do {
                buf_ptr = buf->memory;
                buf_end = buf_ptr + buf->used_size;
@@ -478,40 +509,33 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
                        len = *buf_ptr++;
                        if (len > 0) {
                                /* The code is already generated. */
-                               SLJIT_MEMMOVE(code_ptr, buf_ptr, len);
+                               SLJIT_MEMCPY(code_ptr, buf_ptr, len);
                                code_ptr += len;
                                buf_ptr += len;
                        }
                        else {
-                               if (*buf_ptr >= 4) {
+                               if (*buf_ptr >= 2) {
                                        jump->addr = (sljit_uw)code_ptr;
                                        if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
-                                               code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 4);
-                                       else
-                                               code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 4);
+                                               code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 2, 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);
+#else
+                                               code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2);
+#endif
+                                       }
                                        jump = jump->next;
                                }
                                else if (*buf_ptr == 0) {
-                                       label->addr = (sljit_uw)code_ptr;
+                                       label->addr = ((sljit_uw)code_ptr) + executable_offset;
                                        label->size = code_ptr - code;
                                        label = label->next;
                                }
-                               else if (*buf_ptr == 1) {
+                               else { /* *buf_ptr is 1 */
                                        const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);
                                        const_ = const_->next;
                                }
-                               else {
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-                                       *code_ptr++ = (*buf_ptr == 2) ? CALL_i32 : JMP_i32;
-                                       buf_ptr++;
-                                       *(sljit_sw*)code_ptr = *(sljit_sw*)buf_ptr - ((sljit_sw)code_ptr + sizeof(sljit_sw));
-                                       code_ptr += sizeof(sljit_sw);
-                                       buf_ptr += sizeof(sljit_sw) - 1;
-#else
-                                       code_ptr = generate_fixed_jump(code_ptr, *(sljit_sw*)(buf_ptr + 1), *buf_ptr);
-                                       buf_ptr += sizeof(sljit_sw);
-#endif
-                               }
                                buf_ptr++;
                        }
                } while (buf_ptr < buf_end);
@@ -525,108 +549,109 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
 
        jump = compiler->jumps;
        while (jump) {
+               jump_addr = jump->addr + executable_offset;
+
                if (jump->flags & PATCH_MB) {
-                       SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sb))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sb))) <= 127);
-                       *(sljit_ub*)jump->addr = (sljit_ub)(jump->u.label->addr - (jump->addr + sizeof(sljit_sb)));
+                       SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) <= 127);
+                       *(sljit_u8*)jump->addr = (sljit_u8)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8)));
                } else if (jump->flags & PATCH_MW) {
                        if (jump->flags & JUMP_LABEL) {
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-                               *(sljit_sw*)jump->addr = (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sw)));
+                               sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_sw))));
 #else
-                               SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) <= HALFWORD_MAX);
-                               *(sljit_si*)jump->addr = (sljit_si)(jump->u.label->addr - (jump->addr + sizeof(sljit_si)));
+                               SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX);
+                               sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))));
 #endif
                        }
                        else {
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-                               *(sljit_sw*)jump->addr = (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_sw)));
+                               sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_sw))));
 #else
-                               SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) <= HALFWORD_MAX);
-                               *(sljit_si*)jump->addr = (sljit_si)(jump->u.target - (jump->addr + sizeof(sljit_si)));
+                               SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX);
+                               sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.target - (jump_addr + sizeof(sljit_s32))));
 #endif
                        }
                }
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                else if (jump->flags & PATCH_MD)
-                       *(sljit_sw*)jump->addr = jump->u.label->addr;
+                       sljit_unaligned_store_sw((void*)jump->addr, jump->u.label->addr);
 #endif
 
                jump = jump->next;
        }
 
-       /* Maybe we waste some space because of short jumps. */
+       /* Some space may be wasted because of short jumps. */
        SLJIT_ASSERT(code_ptr <= code + compiler->size);
        compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_offset = executable_offset;
        compiler->executable_size = code_ptr - code;
-       return (void*)code;
+       return (void*)(code + executable_offset);
 }
 
-/* --------------------------------------------------------------------- */
-/*  Operators                                                            */
-/* --------------------------------------------------------------------- */
-
-static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
-       sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+       switch (feature_type) {
+       case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+               return SLJIT_IS_FPU_AVAILABLE;
+#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+               if (cpu_has_sse2 == -1)
+                       get_cpu_features();
+               return cpu_has_sse2;
+#else /* SLJIT_DETECT_SSE2 */
+               return 1;
+#endif /* SLJIT_DETECT_SSE2 */
 
-static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
-       sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w);
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       case SLJIT_HAS_VIRTUAL_REGISTERS:
+               return 1;
+#endif
 
-static sljit_si emit_mov(struct sljit_compiler *compiler,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw);
+       case SLJIT_HAS_CLZ:
+       case SLJIT_HAS_CMOV:
+               if (cpu_has_cmov == -1)
+                       get_cpu_features();
+               return cpu_has_cmov;
 
-static SLJIT_INLINE sljit_si emit_save_flags(struct sljit_compiler *compiler)
-{
-       sljit_ub *inst;
+       case SLJIT_HAS_PREF_SHIFT_REG:
+               return 1;
 
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
-       FAIL_IF(!inst);
-       INC_SIZE(5);
+       case SLJIT_HAS_SSE2:
+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+               if (cpu_has_sse2 == -1)
+                       get_cpu_features();
+               return cpu_has_sse2;
 #else
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 6);
-       FAIL_IF(!inst);
-       INC_SIZE(6);
-       *inst++ = REX_W;
-#endif
-       *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp + sizeof(sljit_sw)] */
-       *inst++ = 0x64;
-       *inst++ = 0x24;
-       *inst++ = (sljit_ub)sizeof(sljit_sw);
-       *inst++ = PUSHF;
-       compiler->flags_saved = 1;
-       return SLJIT_SUCCESS;
+               return 1;
+#endif
+
+       default:
+               return 0;
+       }
 }
 
-static SLJIT_INLINE sljit_si emit_restore_flags(struct sljit_compiler *compiler, sljit_si keep_flags)
-{
-       sljit_ub *inst;
+/* --------------------------------------------------------------------- */
+/*  Operators                                                            */
+/* --------------------------------------------------------------------- */
 
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
-       FAIL_IF(!inst);
-       INC_SIZE(5);
-       *inst++ = POPF;
-#else
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 6);
-       FAIL_IF(!inst);
-       INC_SIZE(6);
-       *inst++ = POPF;
-       *inst++ = REX_W;
-#endif
-       *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp - sizeof(sljit_sw)] */
-       *inst++ = 0x64;
-       *inst++ = 0x24;
-       *inst++ = (sljit_ub)-(sljit_sb)sizeof(sljit_sw);
-       compiler->flags_saved = keep_flags;
-       return SLJIT_SUCCESS;
-}
+static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,
+       sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w);
+
+static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,
+       sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w);
+
+static sljit_s32 emit_mov(struct sljit_compiler *compiler,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw);
+
+#define EMIT_MOV(compiler, dst, dstw, src, srcw) \
+       FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
 
 #ifdef _WIN32
 #include <malloc.h>
@@ -640,7 +665,7 @@ static void SLJIT_CALL sljit_grow_stack(sljit_sw local_size)
        CPU cycles if the stack is large enough. However, you don't know it in
        advance, so it must always be called. I think this is a bad design in
        general even if it has some reasons. */
-       *(volatile sljit_si*)alloca(local_size) = 0;
+       *(volatile sljit_s32*)alloca(local_size) = 0;
 }
 
 #endif
@@ -651,21 +676,14 @@ static void SLJIT_CALL sljit_grow_stack(sljit_sw local_size)
 #include "sljitNativeX86_64.c"
 #endif
 
-static sljit_si emit_mov(struct sljit_compiler *compiler,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static sljit_s32 emit_mov(struct sljit_compiler *compiler,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub* inst;
+       sljit_u8* inst;
+
+       SLJIT_ASSERT(dst != SLJIT_UNUSED);
 
-       if (dst == SLJIT_UNUSED) {
-               /* No destination, doesn't need to setup flags. */
-               if (src & SLJIT_MEM) {
-                       inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw);
-                       FAIL_IF(!inst);
-                       *inst = MOV_r_rm;
-               }
-               return SLJIT_SUCCESS;
-       }
        if (FAST_IS_REG(src)) {
                inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);
                FAIL_IF(!inst);
@@ -687,8 +705,10 @@ static sljit_si emit_mov(struct sljit_compiler *compiler,
                }
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                if (!compiler->mode32 && NOT_HALFWORD(srcw)) {
-                       FAIL_IF(emit_load_imm64(compiler, TMP_REG2, srcw));
-                       inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, dst, dstw);
+                       /* Immediate to memory move. Only SLJIT_MOV operation copies
+                          an immediate directly into memory so TMP_REG1 can be used. */
+                       FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));
+                       inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
                        FAIL_IF(!inst);
                        *inst = MOV_rm_r;
                        return SLJIT_SUCCESS;
@@ -706,7 +726,8 @@ static sljit_si emit_mov(struct sljit_compiler *compiler,
                return SLJIT_SUCCESS;
        }
 
-       /* Memory to memory move. Requires two instruction. */
+       /* Memory to memory move. Only SLJIT_MOV operation copies
+          data from memory to memory so TMP_REG1 can be used. */
        inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw);
        FAIL_IF(!inst);
        *inst = MOV_r_rm;
@@ -716,14 +737,11 @@ static sljit_si emit_mov(struct sljit_compiler *compiler,
        return SLJIT_SUCCESS;
 }
 
-#define EMIT_MOV(compiler, dst, dstw, src, srcw) \
-       FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       sljit_si size;
+       sljit_s32 size;
 #endif
 
        CHECK_ERROR();
@@ -731,44 +749,41 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
 
        switch (GET_OPCODE(op)) {
        case SLJIT_BREAKPOINT:
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                FAIL_IF(!inst);
                INC_SIZE(1);
                *inst = INT3;
                break;
        case SLJIT_NOP:
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                FAIL_IF(!inst);
                INC_SIZE(1);
                *inst = NOP;
                break;
-       case SLJIT_LUMUL:
-       case SLJIT_LSMUL:
-       case SLJIT_UDIVMOD:
-       case SLJIT_SDIVMOD:
-       case SLJIT_UDIVI:
-       case SLJIT_SDIVI:
-               compiler->flags_saved = 0;
+       case SLJIT_LMUL_UW:
+       case SLJIT_LMUL_SW:
+       case SLJIT_DIVMOD_UW:
+       case SLJIT_DIVMOD_SW:
+       case SLJIT_DIV_UW:
+       case SLJIT_DIV_SW:
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
 #ifdef _WIN64
-               SLJIT_COMPILE_ASSERT(
+               SLJIT_ASSERT(
                        reg_map[SLJIT_R0] == 0
                        && reg_map[SLJIT_R1] == 2
-                       && reg_map[TMP_REG1] > 7,
-                       invalid_register_assignment_for_div_mul);
+                       && reg_map[TMP_REG1] > 7);
 #else
-               SLJIT_COMPILE_ASSERT(
+               SLJIT_ASSERT(
                        reg_map[SLJIT_R0] == 0
                        && reg_map[SLJIT_R1] < 7
-                       && reg_map[TMP_REG1] == 2,
-                       invalid_register_assignment_for_div_mul);
+                       && reg_map[TMP_REG1] == 2);
 #endif
-               compiler->mode32 = op & SLJIT_INT_OP;
+               compiler->mode32 = op & SLJIT_I32_OP;
 #endif
-               SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
+               SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
 
                op = GET_OPCODE(op);
-               if ((op | 0x2) == SLJIT_UDIVI) {
+               if ((op | 0x2) == SLJIT_DIV_UW) {
 #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);
@@ -779,24 +794,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
                        *inst = XOR_r_rm;
                }
 
-               if ((op | 0x2) == SLJIT_SDIVI) {
+               if ((op | 0x2) == SLJIT_DIV_SW) {
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
                        EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
 #endif
 
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                        FAIL_IF(!inst);
                        INC_SIZE(1);
                        *inst = CDQ;
 #else
                        if (compiler->mode32) {
-                               inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                               inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                                FAIL_IF(!inst);
                                INC_SIZE(1);
                                *inst = CDQ;
                        } else {
-                               inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+                               inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
                                FAIL_IF(!inst);
                                INC_SIZE(2);
                                *inst++ = REX_W;
@@ -806,27 +821,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
                }
 
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
                FAIL_IF(!inst);
                INC_SIZE(2);
                *inst++ = GROUP_F7;
-               *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
+               *inst = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
 #else
 #ifdef _WIN64
-               size = (!compiler->mode32 || op >= SLJIT_UDIVMOD) ? 3 : 2;
+               size = (!compiler->mode32 || op >= SLJIT_DIVMOD_UW) ? 3 : 2;
 #else
                size = (!compiler->mode32) ? 3 : 2;
 #endif
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
                FAIL_IF(!inst);
                INC_SIZE(size);
 #ifdef _WIN64
                if (!compiler->mode32)
-                       *inst++ = REX_W | ((op >= SLJIT_UDIVMOD) ? REX_B : 0);
-               else if (op >= SLJIT_UDIVMOD)
+                       *inst++ = REX_W | ((op >= SLJIT_DIVMOD_UW) ? REX_B : 0);
+               else if (op >= SLJIT_DIVMOD_UW)
                        *inst++ = REX_B;
                *inst++ = GROUP_F7;
-               *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
+               *inst = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
 #else
                if (!compiler->mode32)
                        *inst++ = REX_W;
@@ -835,26 +850,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
 #endif
 #endif
                switch (op) {
-               case SLJIT_LUMUL:
+               case SLJIT_LMUL_UW:
                        *inst |= MUL;
                        break;
-               case SLJIT_LSMUL:
+               case SLJIT_LMUL_SW:
                        *inst |= IMUL;
                        break;
-               case SLJIT_UDIVMOD:
-               case SLJIT_UDIVI:
+               case SLJIT_DIVMOD_UW:
+               case SLJIT_DIV_UW:
                        *inst |= DIV;
                        break;
-               case SLJIT_SDIVMOD:
-               case SLJIT_SDIVI:
+               case SLJIT_DIVMOD_SW:
+               case SLJIT_DIV_SW:
                        *inst |= IDIV;
                        break;
                }
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
-               if (op <= SLJIT_SDIVMOD)
+               if (op <= SLJIT_DIVMOD_SW)
                        EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
 #else
-               if (op >= SLJIT_UDIVI)
+               if (op >= SLJIT_DIV_UW)
                        EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
 #endif
                break;
@@ -865,29 +880,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
 
 #define ENCODE_PREFIX(prefix) \
        do { \
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 1); \
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); \
                FAIL_IF(!inst); \
                INC_SIZE(1); \
                *inst = (prefix); \
        } while (0)
 
-static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub* inst;
-       sljit_si dst_r;
+       sljit_u8* inst;
+       sljit_s32 dst_r;
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       sljit_si work_r;
+       sljit_s32 work_r;
 #endif
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
        compiler->mode32 = 0;
 #endif
 
-       if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
-               return SLJIT_SUCCESS; /* Empty instruction. */
-
        if (src & SLJIT_IMM) {
                if (FAST_IS_REG(dst)) {
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -1016,19 +1028,40 @@ static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_mov_half(struct sljit_compiler *compiler, sljit_si sign,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub* inst;
-       sljit_si dst_r;
+       sljit_u8* inst;
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       compiler->mode32 = 0;
+       compiler->mode32 = 1;
 #endif
 
-       if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
-               return SLJIT_SUCCESS; /* Empty instruction. */
+       inst = emit_x86_instruction(compiler, 2, 0, 0, src, srcw);
+       FAIL_IF(!inst);
+       *inst++ = GROUP_0F;
+       *inst++ = PREFETCH;
+
+       if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8)
+               *inst |= (3 << 3);
+       else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16)
+               *inst |= (2 << 3);
+       else
+               *inst |= (1 << 3);
+
+       return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
+{
+       sljit_u8* inst;
+       sljit_s32 dst_r;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = 0;
+#endif
 
        if (src & SLJIT_IMM) {
                if (FAST_IS_REG(dst)) {
@@ -1067,20 +1100,12 @@ static sljit_si emit_mov_half(struct sljit_compiler *compiler, sljit_si sign,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_unary(struct sljit_compiler *compiler, sljit_ub opcode,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub* inst;
+       sljit_u8* inst;
 
-       if (dst == SLJIT_UNUSED) {
-               EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
-               inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
-               FAIL_IF(!inst);
-               *inst++ = GROUP_F7;
-               *inst |= opcode;
-               return SLJIT_SUCCESS;
-       }
        if (dst == src && dstw == srcw) {
                /* Same input and output */
                inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
@@ -1089,14 +1114,19 @@ static sljit_si emit_unary(struct sljit_compiler *compiler, sljit_ub opcode,
                *inst |= opcode;
                return SLJIT_SUCCESS;
        }
+
+       if (dst == SLJIT_UNUSED)
+               dst = TMP_REG1;
+
        if (FAST_IS_REG(dst)) {
                EMIT_MOV(compiler, dst, 0, src, srcw);
-               inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+               inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);
                FAIL_IF(!inst);
                *inst++ = GROUP_F7;
                *inst |= opcode;
                return SLJIT_SUCCESS;
        }
+
        EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
        inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
        FAIL_IF(!inst);
@@ -1106,26 +1136,18 @@ static sljit_si emit_unary(struct sljit_compiler *compiler, sljit_ub opcode,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_not_with_flags(struct sljit_compiler *compiler,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub* inst;
+       sljit_u8* inst;
+
+       if (dst == SLJIT_UNUSED)
+               dst = TMP_REG1;
 
-       if (dst == SLJIT_UNUSED) {
-               EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
-               inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
-               FAIL_IF(!inst);
-               *inst++ = GROUP_F7;
-               *inst |= NOT_rm;
-               inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);
-               FAIL_IF(!inst);
-               *inst = OR_r_rm;
-               return SLJIT_SUCCESS;
-       }
        if (FAST_IS_REG(dst)) {
                EMIT_MOV(compiler, dst, 0, src, srcw);
-               inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+               inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);
                FAIL_IF(!inst);
                *inst++ = GROUP_F7;
                *inst |= NOT_rm;
@@ -1134,6 +1156,7 @@ static sljit_si emit_not_with_flags(struct sljit_compiler *compiler,
                *inst = OR_r_rm;
                return SLJIT_SUCCESS;
        }
+
        EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
        inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
        FAIL_IF(!inst);
@@ -1146,30 +1169,18 @@ static sljit_si emit_not_with_flags(struct sljit_compiler *compiler,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+static const sljit_sw emit_clz_arg = 32 + 31;
+#endif
+
+static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub* inst;
-       sljit_si dst_r;
+       sljit_u8* inst;
+       sljit_s32 dst_r;
 
        SLJIT_UNUSED_ARG(op_flags);
-       if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
-               /* Just set the zero flag. */
-               EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
-               inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
-               FAIL_IF(!inst);
-               *inst++ = GROUP_F7;
-               *inst |= NOT_rm;
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-               inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REG1, 0);
-#else
-               inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 63 : 31, TMP_REG1, 0);
-#endif
-               FAIL_IF(!inst);
-               *inst |= SHR;
-               return SLJIT_SUCCESS;
-       }
 
        if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
                EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
@@ -1177,94 +1188,65 @@ static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
                srcw = 0;
        }
 
-       inst = emit_x86_instruction(compiler, 2, TMP_REG1, 0, src, srcw);
+       if (cpu_has_cmov == -1)
+               get_cpu_features();
+
+       dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+       inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
        FAIL_IF(!inst);
        *inst++ = GROUP_0F;
        *inst = BSR_r_rm;
 
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       if (FAST_IS_REG(dst))
-               dst_r = dst;
-       else {
-               /* Find an unused temporary register. */
-               if ((dst & REG_MASK) != SLJIT_R0 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R0))
-                       dst_r = SLJIT_R0;
-               else if ((dst & REG_MASK) != SLJIT_R1 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R1))
-                       dst_r = SLJIT_R1;
+       if (cpu_has_cmov) {
+               if (dst_r != TMP_REG1) {
+                       EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 32 + 31);
+                       inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0);
+               }
                else
-                       dst_r = SLJIT_R2;
-               EMIT_MOV(compiler, dst, dstw, dst_r, 0);
-       }
-       EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, 32 + 31);
-#else
-       dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
-       compiler->mode32 = 0;
-       EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 64 + 63 : 32 + 31);
-       compiler->mode32 = op_flags & SLJIT_INT_OP;
-#endif
-
-       if (cpu_has_cmov == -1)
-               get_cpu_features();
+                       inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), (sljit_sw)&emit_clz_arg);
 
-       if (cpu_has_cmov) {
-               inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0);
                FAIL_IF(!inst);
                *inst++ = GROUP_0F;
-               *inst = CMOVNE_r_rm;
-       } else {
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
-               FAIL_IF(!inst);
-               INC_SIZE(4);
+               *inst = CMOVE_r_rm;
+       }
+       else
+               FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, 32 + 31));
 
-               *inst++ = JE_i8;
-               *inst++ = 2;
-               *inst++ = MOV_r_rm;
-               *inst++ = MOD_REG | (reg_map[dst_r] << 3) | reg_map[TMP_REG1];
+       inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);
 #else
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
-               FAIL_IF(!inst);
-               INC_SIZE(5);
+       if (cpu_has_cmov) {
+               EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31));
 
-               *inst++ = JE_i8;
-               *inst++ = 3;
-               *inst++ = REX_W | (reg_map[dst_r] >= 8 ? REX_R : 0) | (reg_map[TMP_REG1] >= 8 ? REX_B : 0);
-               *inst++ = MOV_r_rm;
-               *inst++ = MOD_REG | (reg_lmap[dst_r] << 3) | reg_lmap[TMP_REG1];
-#endif
+               inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
+               FAIL_IF(!inst);
+               *inst++ = GROUP_0F;
+               *inst = CMOVE_r_rm;
        }
+       else
+               FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31)));
 
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);
-#else
-       inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 63 : 31, dst_r, 0);
+       inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 63 : 31, dst_r, 0);
 #endif
+
        FAIL_IF(!inst);
        *(inst + 1) |= XOR;
 
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       if (dst & SLJIT_MEM) {
-               inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
-               FAIL_IF(!inst);
-               *inst = XCHG_r_rm;
-       }
-#else
        if (dst & SLJIT_MEM)
-               EMIT_MOV(compiler, dst, dstw, TMP_REG2, 0);
-#endif
+               EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub* inst;
-       sljit_si update = 0;
-       sljit_si op_flags = GET_ALL_FLAGS(op);
+       sljit_s32 update = 0;
+       sljit_s32 op_flags = GET_ALL_FLAGS(op);
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       sljit_si dst_is_ereg = 0;
-       sljit_si src_is_ereg = 0;
+       sljit_s32 dst_is_ereg = 0;
+       sljit_s32 src_is_ereg = 0;
 #else
 #      define src_is_ereg 0
 #endif
@@ -1277,29 +1259,36 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
        CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
        CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1);
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       compiler->mode32 = op_flags & SLJIT_INT_OP;
+       compiler->mode32 = op_flags & SLJIT_I32_OP;
 #endif
 
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
+               if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
+                       return emit_prefetch(compiler, op, src, srcw);
+               return SLJIT_SUCCESS;
+       }
+
        op = GET_OPCODE(op);
+
        if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                compiler->mode32 = 0;
 #endif
 
-               if (op_flags & SLJIT_INT_OP) {
+               if (op_flags & SLJIT_I32_OP) {
                        if (FAST_IS_REG(src) && src == dst) {
                                if (!TYPE_CAST_NEEDED(op))
                                        return SLJIT_SUCCESS;
                        }
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-                       if (op == SLJIT_MOV_SI && (src & SLJIT_MEM))
-                               op = SLJIT_MOV_UI;
-                       if (op == SLJIT_MOVU_SI && (src & SLJIT_MEM))
-                               op = SLJIT_MOVU_UI;
-                       if (op == SLJIT_MOV_UI && (src & SLJIT_IMM))
-                               op = SLJIT_MOV_SI;
-                       if (op == SLJIT_MOVU_UI && (src & SLJIT_IMM))
-                               op = SLJIT_MOVU_SI;
+                       if (op == SLJIT_MOV_S32 && (src & SLJIT_MEM))
+                               op = SLJIT_MOV_U32;
+                       if (op == SLJIT_MOVU_S32 && (src & SLJIT_MEM))
+                               op = SLJIT_MOVU_U32;
+                       if (op == SLJIT_MOV_U32 && (src & SLJIT_IMM))
+                               op = SLJIT_MOV_S32;
+                       if (op == SLJIT_MOVU_U32 && (src & SLJIT_IMM))
+                               op = SLJIT_MOVU_S32;
 #endif
                }
 
@@ -1311,24 +1300,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
 
                if (src & SLJIT_IMM) {
                        switch (op) {
-                       case SLJIT_MOV_UB:
-                               srcw = (sljit_ub)srcw;
+                       case SLJIT_MOV_U8:
+                               srcw = (sljit_u8)srcw;
                                break;
-                       case SLJIT_MOV_SB:
-                               srcw = (sljit_sb)srcw;
+                       case SLJIT_MOV_S8:
+                               srcw = (sljit_s8)srcw;
                                break;
-                       case SLJIT_MOV_UH:
-                               srcw = (sljit_uh)srcw;
+                       case SLJIT_MOV_U16:
+                               srcw = (sljit_u16)srcw;
                                break;
-                       case SLJIT_MOV_SH:
-                               srcw = (sljit_sh)srcw;
+                       case SLJIT_MOV_S16:
+                               srcw = (sljit_s16)srcw;
                                break;
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-                       case SLJIT_MOV_UI:
-                               srcw = (sljit_ui)srcw;
+                       case SLJIT_MOV_U32:
+                               srcw = (sljit_u32)srcw;
                                break;
-                       case SLJIT_MOV_SI:
-                               srcw = (sljit_si)srcw;
+                       case SLJIT_MOV_S32:
+                               srcw = (sljit_s32)srcw;
                                break;
 #endif
                        }
@@ -1338,16 +1327,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
 #endif
                }
 
-               if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & REG_MASK) && (srcw != 0 || (src & OFFS_REG_MASK) != 0)) {
-                       inst = emit_x86_instruction(compiler, 1, src & REG_MASK, 0, src, srcw);
-                       FAIL_IF(!inst);
-                       *inst = LEA_r_m;
-                       src &= SLJIT_MEM | 0xf;
-                       srcw = 0;
-               }
-
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-               if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) {
+               if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) {
                        SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_SP));
                        dst = TMP_REG1;
                }
@@ -1357,28 +1338,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
                case SLJIT_MOV:
                case SLJIT_MOV_P:
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-               case SLJIT_MOV_UI:
-               case SLJIT_MOV_SI:
+               case SLJIT_MOV_U32:
+               case SLJIT_MOV_S32:
 #endif
                        FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
                        break;
-               case SLJIT_MOV_UB:
+               case SLJIT_MOV_U8:
                        FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, srcw));
                        break;
-               case SLJIT_MOV_SB:
+               case SLJIT_MOV_S8:
                        FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, srcw));
                        break;
-               case SLJIT_MOV_UH:
+               case SLJIT_MOV_U16:
                        FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, srcw));
                        break;
-               case SLJIT_MOV_SH:
+               case SLJIT_MOV_S16:
                        FAIL_IF(emit_mov_half(compiler, 1, dst, dstw, src, srcw));
                        break;
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-               case SLJIT_MOV_UI:
+               case SLJIT_MOV_U32:
                        FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, srcw));
                        break;
-               case SLJIT_MOV_SI:
+               case SLJIT_MOV_S32:
                        FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, srcw));
                        break;
 #endif
@@ -1389,31 +1370,40 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
                        return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0);
 #endif
 
-               if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & REG_MASK) && (dstw != 0 || (dst & OFFS_REG_MASK) != 0)) {
-                       inst = emit_x86_instruction(compiler, 1, dst & REG_MASK, 0, dst, dstw);
-                       FAIL_IF(!inst);
-                       *inst = LEA_r_m;
+               if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & REG_MASK)) {
+                       if ((src & OFFS_REG_MASK) != 0) {
+                               FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+                                               (src & REG_MASK), 0, (src & REG_MASK), 0, OFFS_REG(dst), 0));
+                       }
+                       else if (srcw != 0) {
+                               FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+                                               (src & REG_MASK), 0, (src & REG_MASK), 0, SLJIT_IMM, srcw));
+                       }
+               }
+
+               if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & REG_MASK)) {
+                       if ((dst & OFFS_REG_MASK) != 0) {
+                               FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+                                               (dst & REG_MASK), 0, (dst & REG_MASK), 0, OFFS_REG(dst), 0));
+                       }
+                       else if (dstw != 0) {
+                               FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
+                                               (dst & REG_MASK), 0, (dst & REG_MASK), 0, SLJIT_IMM, dstw));
+                       }
                }
                return SLJIT_SUCCESS;
        }
 
-       if (SLJIT_UNLIKELY(GET_FLAGS(op_flags)))
-               compiler->flags_saved = 0;
-
        switch (op) {
        case SLJIT_NOT:
-               if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_E))
+               if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_Z))
                        return emit_not_with_flags(compiler, dst, dstw, src, srcw);
                return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw);
 
        case SLJIT_NEG:
-               if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
-                       FAIL_IF(emit_save_flags(compiler));
                return emit_unary(compiler, NEG_rm, dst, dstw, src, srcw);
 
        case SLJIT_CLZ:
-               if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
-                       FAIL_IF(emit_save_flags(compiler));
                return emit_clz(compiler, op_flags, dst, dstw, src, srcw);
        }
 
@@ -1433,8 +1423,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
                *(inst + 1) |= (op_imm); \
        } \
        else { \
-               FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immw)); \
-               inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, arg, argw); \
+               FAIL_IF(emit_load_imm64(compiler, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, immw)); \
+               inst = emit_x86_instruction(compiler, 1, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \
                FAIL_IF(!inst); \
                *inst = (op_mr); \
        }
@@ -1454,13 +1444,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
 
 #endif
 
-static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
-       sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,
+       sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_ub* inst;
+       sljit_u8* inst;
 
        if (dst == SLJIT_UNUSED) {
                EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
@@ -1570,13 +1560,13 @@ static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
-       sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,
+       sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_ub* inst;
+       sljit_u8* inst;
 
        if (dst == SLJIT_UNUSED) {
                EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
@@ -1652,15 +1642,15 @@ static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_mul(struct sljit_compiler *compiler,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_mul(struct sljit_compiler *compiler,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_ub* inst;
-       sljit_si dst_r;
+       sljit_u8* inst;
+       sljit_s32 dst_r;
 
-       dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+       dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
 
        /* Register destination. */
        if (dst_r == src1 && !(src2 & SLJIT_IMM)) {
@@ -1686,35 +1676,35 @@ static sljit_si emit_mul(struct sljit_compiler *compiler,
                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
                        FAIL_IF(!inst);
                        *inst = IMUL_r_rm_i8;
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                        FAIL_IF(!inst);
                        INC_SIZE(1);
-                       *inst = (sljit_sb)src1w;
+                       *inst = (sljit_s8)src1w;
                }
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                else {
                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
                        FAIL_IF(!inst);
                        *inst = IMUL_r_rm_i32;
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
                        FAIL_IF(!inst);
                        INC_SIZE(4);
-                       *(sljit_sw*)inst = src1w;
+                       sljit_unaligned_store_sw(inst, src1w);
                }
 #else
                else if (IS_HALFWORD(src1w)) {
                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
                        FAIL_IF(!inst);
                        *inst = IMUL_r_rm_i32;
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
                        FAIL_IF(!inst);
                        INC_SIZE(4);
-                       *(sljit_si*)inst = (sljit_si)src1w;
+                       sljit_unaligned_store_s32(inst, (sljit_s32)src1w);
                }
                else {
-                       EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w);
                        if (dst_r != src2)
                                EMIT_MOV(compiler, dst_r, 0, src2, src2w);
+                       FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
                        inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
                        FAIL_IF(!inst);
                        *inst++ = GROUP_0F;
@@ -1729,35 +1719,35 @@ static sljit_si emit_mul(struct sljit_compiler *compiler,
                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
                        FAIL_IF(!inst);
                        *inst = IMUL_r_rm_i8;
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
                        FAIL_IF(!inst);
                        INC_SIZE(1);
-                       *inst = (sljit_sb)src2w;
+                       *inst = (sljit_s8)src2w;
                }
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                else {
                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
                        FAIL_IF(!inst);
                        *inst = IMUL_r_rm_i32;
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
                        FAIL_IF(!inst);
                        INC_SIZE(4);
-                       *(sljit_sw*)inst = src2w;
+                       sljit_unaligned_store_sw(inst, src2w);
                }
 #else
                else if (IS_HALFWORD(src2w)) {
                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
                        FAIL_IF(!inst);
                        *inst = IMUL_r_rm_i32;
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
                        FAIL_IF(!inst);
                        INC_SIZE(4);
-                       *(sljit_si*)inst = (sljit_si)src2w;
+                       sljit_unaligned_store_s32(inst, (sljit_s32)src2w);
                }
                else {
-                       EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src2w);
                        if (dst_r != src1)
                                EMIT_MOV(compiler, dst_r, 0, src1, src1w);
+                       FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
                        inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
                        FAIL_IF(!inst);
                        *inst++ = GROUP_0F;
@@ -1776,27 +1766,25 @@ static sljit_si emit_mul(struct sljit_compiler *compiler,
                *inst = IMUL_r_rm;
        }
 
-       if (dst_r == TMP_REG1)
+       if (dst & SLJIT_MEM)
                EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
 
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si keep_flags,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_ub* inst;
-       sljit_si dst_r, done = 0;
+       sljit_u8* inst;
+       sljit_s32 dst_r, done = 0;
 
        /* These cases better be left to handled by normal way. */
-       if (!keep_flags) {
-               if (dst == src1 && dstw == src1w)
-                       return SLJIT_ERR_UNSUPPORTED;
-               if (dst == src2 && dstw == src2w)
-                       return SLJIT_ERR_UNSUPPORTED;
-       }
+       if (dst == src1 && dstw == src1w)
+               return SLJIT_ERR_UNSUPPORTED;
+       if (dst == src2 && dstw == src2w)
+               return SLJIT_ERR_UNSUPPORTED;
 
        dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
 
@@ -1809,7 +1797,7 @@ static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si keep_f
                }
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) {
-                       inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (sljit_si)src2w);
+                       inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (sljit_s32)src2w);
 #else
                if (src2 & SLJIT_IMM) {
                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w);
@@ -1822,7 +1810,7 @@ static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si keep_f
        else if (FAST_IS_REG(src2)) {
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                if ((src1 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src1w))) {
-                       inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (sljit_si)src1w);
+                       inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (sljit_s32)src1w);
 #else
                if (src1 & SLJIT_IMM) {
                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w);
@@ -1841,11 +1829,11 @@ static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si keep_f
        return SLJIT_ERR_UNSUPPORTED;
 }
 
-static sljit_si emit_cmp_binary(struct sljit_compiler *compiler,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_ub* inst;
+       sljit_u8* inst;
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
        if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
@@ -1892,11 +1880,11 @@ static sljit_si emit_cmp_binary(struct sljit_compiler *compiler,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_test_binary(struct sljit_compiler *compiler,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_test_binary(struct sljit_compiler *compiler,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_ub* inst;
+       sljit_u8* inst;
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
        if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
@@ -1908,7 +1896,7 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
        }
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       if (src2 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
+       if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
 #else
        if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) {
 #endif
@@ -1925,8 +1913,8 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
                                *inst = GROUP_F7;
                        }
                        else {
-                               FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
-                               inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w);
+                               FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src2w));
+                               inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src1, src1w);
                                FAIL_IF(!inst);
                                *inst = TEST_rm_r;
                        }
@@ -1954,8 +1942,8 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
                                *inst = GROUP_F7;
                        }
                        else {
-                               FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
-                               inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w);
+                               FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src1w));
+                               inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
                                FAIL_IF(!inst);
                                *inst = TEST_rm_r;
                        }
@@ -2002,13 +1990,13 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_shift(struct sljit_compiler *compiler,
-       sljit_ub mode,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_shift(struct sljit_compiler *compiler,
+       sljit_u8 mode,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_ub* inst;
+       sljit_u8* inst;
 
        if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) {
                if (dst == src1 && dstw == src1w) {
@@ -2067,35 +2055,39 @@ static sljit_si emit_shift(struct sljit_compiler *compiler,
                EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
        }
        else {
-               /* This case is really difficult, since ecx itself may used for
-                  addressing, and we must ensure to work even in that case. */
+               /* This case is complex since ecx itself may be used for
+                  addressing, and this case must be supported as well. */
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-               EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
-#else
-               /* [esp+0] contains the flags. */
-               EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_PREF_SHIFT_REG, 0);
-#endif
+               EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0);
                EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
                inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
                FAIL_IF(!inst);
                *inst |= mode;
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
+               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0);
+               EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
 #else
-               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));
-#endif
+               EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+               EMIT_MOV(compiler, TMP_REG2, 0, src2, src2w);
+               inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
+               FAIL_IF(!inst);
+               *inst = XCHG_r_rm;
+               inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
+               FAIL_IF(!inst);
+               *inst |= mode;
+               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
                EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+#endif
        }
 
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_shift_with_flags(struct sljit_compiler *compiler,
-       sljit_ub mode, sljit_si set_flags,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler,
+       sljit_u8 mode, sljit_s32 set_flags,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        /* The CPU does not set flags if the shift count is 0. */
        if (src2 & SLJIT_IMM) {
@@ -2126,10 +2118,10 @@ static sljit_si emit_shift_with_flags(struct sljit_compiler *compiler,
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
        CHECK_ERROR();
        CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -2141,57 +2133,34 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
        CHECK_EXTRA_REGS(src1, src1w, (void)0);
        CHECK_EXTRA_REGS(src2, src2w, (void)0);
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       compiler->mode32 = op & SLJIT_INT_OP;
+       compiler->mode32 = op & SLJIT_I32_OP;
 #endif
 
-       if (GET_OPCODE(op) >= SLJIT_MUL) {
-               if (SLJIT_UNLIKELY(GET_FLAGS(op)))
-                       compiler->flags_saved = 0;
-               else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
-                       FAIL_IF(emit_save_flags(compiler));
-       }
+       if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
+               return SLJIT_SUCCESS;
 
        switch (GET_OPCODE(op)) {
        case SLJIT_ADD:
-               if (!GET_FLAGS(op)) {
-                       if (emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)
+               if (!HAS_FLAGS(op)) {
+                       if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)
                                return compiler->error;
                }
-               else
-                       compiler->flags_saved = 0;
-               if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
-                       FAIL_IF(emit_save_flags(compiler));
                return emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
                        dst, dstw, src1, src1w, src2, src2w);
        case SLJIT_ADDC:
-               if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
-                       FAIL_IF(emit_restore_flags(compiler, 1));
-               else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS))
-                       FAIL_IF(emit_save_flags(compiler));
-               if (SLJIT_UNLIKELY(GET_FLAGS(op)))
-                       compiler->flags_saved = 0;
                return emit_cum_binary(compiler, ADC_r_rm, ADC_rm_r, ADC, ADC_EAX_i32,
                        dst, dstw, src1, src1w, src2, src2w);
        case SLJIT_SUB:
-               if (!GET_FLAGS(op)) {
-                       if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)
+               if (!HAS_FLAGS(op)) {
+                       if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)
                                return compiler->error;
                }
-               else
-                       compiler->flags_saved = 0;
-               if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
-                       FAIL_IF(emit_save_flags(compiler));
+
                if (dst == SLJIT_UNUSED)
                        return emit_cmp_binary(compiler, src1, src1w, src2, src2w);
                return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
                        dst, dstw, src1, src1w, src2, src2w);
        case SLJIT_SUBC:
-               if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
-                       FAIL_IF(emit_restore_flags(compiler, 1));
-               else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS))
-                       FAIL_IF(emit_save_flags(compiler));
-               if (SLJIT_UNLIKELY(GET_FLAGS(op)))
-                       compiler->flags_saved = 0;
                return emit_non_cum_binary(compiler, SBB_r_rm, SBB_rm_r, SBB, SBB_EAX_i32,
                        dst, dstw, src1, src1w, src2, src2w);
        case SLJIT_MUL:
@@ -2208,47 +2177,47 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
                return emit_cum_binary(compiler, XOR_r_rm, XOR_rm_r, XOR, XOR_EAX_i32,
                        dst, dstw, src1, src1w, src2, src2w);
        case SLJIT_SHL:
-               return emit_shift_with_flags(compiler, SHL, GET_FLAGS(op),
+               return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op),
                        dst, dstw, src1, src1w, src2, src2w);
        case SLJIT_LSHR:
-               return emit_shift_with_flags(compiler, SHR, GET_FLAGS(op),
+               return emit_shift_with_flags(compiler, SHR, HAS_FLAGS(op),
                        dst, dstw, src1, src1w, src2, src2w);
        case SLJIT_ASHR:
-               return emit_shift_with_flags(compiler, SAR, GET_FLAGS(op),
+               return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op),
                        dst, dstw, src1, src1w, src2, src2w);
        }
 
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_register_index(reg));
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       if (reg >= SLJIT_R3 && reg <= SLJIT_R6)
+       if (reg >= SLJIT_R3 && reg <= SLJIT_R8)
                return -1;
 #endif
        return reg_map[reg];
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
 {
        CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
        return reg;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
-       void *instruction, sljit_si size)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, sljit_s32 size)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
        FAIL_IF(!inst);
        INC_SIZE(size);
-       SLJIT_MEMMOVE(inst, instruction, size);
+       SLJIT_MEMCPY(inst, instruction, size);
        return SLJIT_SUCCESS;
 }
 
@@ -2256,40 +2225,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
 /*  Floating point operators                                             */
 /* --------------------------------------------------------------------- */
 
-/* Alignment + 2 * 16 bytes. */
-static sljit_si sse2_data[3 + (4 + 4) * 2];
-static sljit_si *sse2_buffer;
+/* Alignment(3) + 4 * 16 bytes. */
+static sljit_s32 sse2_data[3 + (4 * 4)];
+static sljit_s32 *sse2_buffer;
 
 static void init_compiler(void)
 {
-       sse2_buffer = (sljit_si*)(((sljit_uw)sse2_data + 15) & ~0xf);
-       /* Single precision constants. */
+       /* Align to 16 bytes. */
+       sse2_buffer = (sljit_s32*)(((sljit_uw)sse2_data + 15) & ~0xf);
+
+       /* Single precision constants (each constant is 16 byte long). */
        sse2_buffer[0] = 0x80000000;
        sse2_buffer[4] = 0x7fffffff;
-       /* Double precision constants. */
+       /* Double precision constants (each constant is 16 byte long). */
        sse2_buffer[8] = 0;
        sse2_buffer[9] = 0x80000000;
        sse2_buffer[12] = 0xffffffff;
        sse2_buffer[13] = 0x7fffffff;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
-{
-#ifdef SLJIT_IS_FPU_AVAILABLE
-       return SLJIT_IS_FPU_AVAILABLE;
-#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
-       if (cpu_has_sse2 == -1)
-               get_cpu_features();
-       return cpu_has_sse2;
-#else /* SLJIT_DETECT_SSE2 */
-       return 1;
-#endif /* SLJIT_DETECT_SSE2 */
-}
-
-static sljit_si emit_sse2(struct sljit_compiler *compiler, sljit_ub opcode,
-       sljit_si single, sljit_si xmm1, sljit_si xmm2, sljit_sw xmm2w)
+static sljit_s32 emit_sse2(struct sljit_compiler *compiler, sljit_u8 opcode,
+       sljit_s32 single, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
        inst = emit_x86_instruction(compiler, 2 | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
        FAIL_IF(!inst);
@@ -2298,10 +2256,10 @@ static sljit_si emit_sse2(struct sljit_compiler *compiler, sljit_ub opcode,
        return SLJIT_SUCCESS;
 }
 
-static sljit_si emit_sse2_logic(struct sljit_compiler *compiler, sljit_ub opcode,
-       sljit_si pref66, sljit_si xmm1, sljit_si xmm2, sljit_sw xmm2w)
+static sljit_s32 emit_sse2_logic(struct sljit_compiler *compiler, sljit_u8 opcode,
+       sljit_s32 pref66, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
 
        inst = emit_x86_instruction(compiler, 2 | (pref66 ? EX86_PREF_66 : 0) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
        FAIL_IF(!inst);
@@ -2310,63 +2268,63 @@ static sljit_si emit_sse2_logic(struct sljit_compiler *compiler, sljit_ub opcode
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si emit_sse2_load(struct sljit_compiler *compiler,
-       sljit_si single, sljit_si dst, sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,
+       sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw)
 {
        return emit_sse2(compiler, MOVSD_x_xm, single, dst, src, srcw);
 }
 
-static SLJIT_INLINE sljit_si emit_sse2_store(struct sljit_compiler *compiler,
-       sljit_si single, sljit_si dst, sljit_sw dstw, sljit_si src)
+static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,
+       sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src)
 {
        return emit_sse2(compiler, MOVSD_xm_x, single, src, dst, dstw);
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convw_fromd(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
-       sljit_ub *inst;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+       sljit_u8 *inst;
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       if (GET_OPCODE(op) == SLJIT_CONVW_FROMD)
+       if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)
                compiler->mode32 = 0;
 #endif
 
-       inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_SINGLE_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP2, dst_r, 0, src, srcw);
+       inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_F32_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP2, dst_r, 0, src, srcw);
        FAIL_IF(!inst);
        *inst++ = GROUP_0F;
        *inst = CVTTSD2SI_r_xm;
 
-       if (dst_r == TMP_REG1 && dst != SLJIT_UNUSED)
+       if (dst & SLJIT_MEM)
                return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;
-       sljit_ub *inst;
+       sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;
+       sljit_u8 *inst;
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       if (GET_OPCODE(op) == SLJIT_CONVD_FROMW)
+       if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)
                compiler->mode32 = 0;
 #endif
 
        if (src & SLJIT_IMM) {
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-               if (GET_OPCODE(op) == SLJIT_CONVD_FROMI)
-                       srcw = (sljit_si)srcw;
+               if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+                       srcw = (sljit_s32)srcw;
 #endif
                EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
                src = TMP_REG1;
                srcw = 0;
        }
 
-       inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_SINGLE_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw);
+       inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_F32_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw);
        FAIL_IF(!inst);
        *inst++ = GROUP_0F;
        *inst = CVTSI2SD_x_rm;
@@ -2375,27 +2333,26 @@ static SLJIT_INLINE sljit_si sljit_emit_fop1_convd_fromw(struct sljit_compiler *
        compiler->mode32 = 1;
 #endif
        if (dst_r == TMP_FREG)
-               return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
+               return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
        return SLJIT_SUCCESS;
 }
 
-static SLJIT_INLINE sljit_si sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       compiler->flags_saved = 0;
        if (!FAST_IS_REG(src1)) {
-               FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src1, src1w));
+               FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));
                src1 = TMP_FREG;
        }
-       return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_SINGLE_OP), src1, src2, src2w);
+       return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_F32_OP), src1, src2, src2w);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src, sljit_sw srcw)
 {
-       sljit_si dst_r;
+       sljit_s32 dst_r;
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
        compiler->mode32 = 1;
@@ -2404,65 +2361,65 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
        CHECK_ERROR();
        SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
 
-       if (GET_OPCODE(op) == SLJIT_DMOV) {
+       if (GET_OPCODE(op) == SLJIT_MOV_F64) {
                if (FAST_IS_REG(dst))
-                       return emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst, src, srcw);
+                       return emit_sse2_load(compiler, op & SLJIT_F32_OP, dst, src, srcw);
                if (FAST_IS_REG(src))
-                       return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, src);
-               FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src, srcw));
-               return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
+                       return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, src);
+               FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src, srcw));
+               return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
        }
 
-       if (GET_OPCODE(op) == SLJIT_CONVD_FROMS) {
+       if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) {
                dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;
                if (FAST_IS_REG(src)) {
                        /* We overwrite the high bits of source. From SLJIT point of view,
                           this is not an issue.
                           Note: In SSE3, we could also use MOVDDUP and MOVSLDUP. */
-                       FAIL_IF(emit_sse2_logic(compiler, UNPCKLPD_x_xm, op & SLJIT_SINGLE_OP, src, src, 0));
+                       FAIL_IF(emit_sse2_logic(compiler, UNPCKLPD_x_xm, op & SLJIT_F32_OP, src, src, 0));
                }
                else {
-                       FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_SINGLE_OP), TMP_FREG, src, srcw));
+                       FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_F32_OP), TMP_FREG, src, srcw));
                        src = TMP_FREG;
                }
 
-               FAIL_IF(emit_sse2_logic(compiler, CVTPD2PS_x_xm, op & SLJIT_SINGLE_OP, dst_r, src, 0));
+               FAIL_IF(emit_sse2_logic(compiler, CVTPD2PS_x_xm, op & SLJIT_F32_OP, dst_r, src, 0));
                if (dst_r == TMP_FREG)
-                       return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
+                       return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
                return SLJIT_SUCCESS;
        }
 
-       if (SLOW_IS_REG(dst)) {
+       if (FAST_IS_REG(dst)) {
                dst_r = dst;
                if (dst != src)
-                       FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src, srcw));
+                       FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw));
        }
        else {
                dst_r = TMP_FREG;
-               FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src, srcw));
+               FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw));
        }
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DNEG:
-               FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_SINGLE_OP ? sse2_buffer : sse2_buffer + 8)));
+       case SLJIT_NEG_F64:
+               FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_F32_OP ? sse2_buffer : sse2_buffer + 8)));
                break;
 
-       case SLJIT_DABS:
-               FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_SINGLE_OP ? sse2_buffer + 4 : sse2_buffer + 12)));
+       case SLJIT_ABS_F64:
+               FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_F32_OP ? sse2_buffer + 4 : sse2_buffer + 12)));
                break;
        }
 
        if (dst_r == TMP_FREG)
-               return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
+               return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src1, sljit_sw src1w,
-       sljit_si src2, sljit_sw src2w)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 src1, sljit_sw src1w,
+       sljit_s32 src2, sljit_sw src2w)
 {
-       sljit_si dst_r;
+       sljit_s32 dst_r;
 
        CHECK_ERROR();
        CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -2478,43 +2435,43 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
                dst_r = dst;
                if (dst == src1)
                        ; /* Do nothing here. */
-               else if (dst == src2 && (op == SLJIT_DADD || op == SLJIT_DMUL)) {
+               else if (dst == src2 && (op == SLJIT_ADD_F64 || op == SLJIT_MUL_F64)) {
                        /* Swap arguments. */
                        src2 = src1;
                        src2w = src1w;
                }
                else if (dst != src2)
-                       FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src1, src1w));
+                       FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src1, src1w));
                else {
                        dst_r = TMP_FREG;
-                       FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src1, src1w));
+                       FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));
                }
        }
        else {
                dst_r = TMP_FREG;
-               FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src1, src1w));
+               FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));
        }
 
        switch (GET_OPCODE(op)) {
-       case SLJIT_DADD:
-               FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
+       case SLJIT_ADD_F64:
+               FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));
                break;
 
-       case SLJIT_DSUB:
-               FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
+       case SLJIT_SUB_F64:
+               FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));
                break;
 
-       case SLJIT_DMUL:
-               FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
+       case SLJIT_MUL_F64:
+               FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));
                break;
 
-       case SLJIT_DDIV:
-               FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
+       case SLJIT_DIV_F64:
+               FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));
                break;
        }
 
        if (dst_r == TMP_FREG)
-               return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
+               return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
        return SLJIT_SUCCESS;
 }
 
@@ -2524,17 +2481,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
 
 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
        struct sljit_label *label;
 
        CHECK_ERROR_PTR();
        CHECK_PTR(check_sljit_emit_label(compiler));
 
-       /* We should restore the flags before the label,
-          since other taken jumps has their own flags as well. */
-       if (SLJIT_UNLIKELY(compiler->flags_saved))
-               PTR_FAIL_IF(emit_restore_flags(compiler, 0));
-
        if (compiler->last_label && compiler->last_label->size == compiler->size)
                return compiler->last_label;
 
@@ -2542,7 +2494,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
        PTR_FAIL_IF(!label);
        set_label(label, compiler);
 
-       inst = (sljit_ub*)ensure_buf(compiler, 2);
+       inst = (sljit_u8*)ensure_buf(compiler, 2);
        PTR_FAIL_IF(!inst);
 
        *inst++ = 0;
@@ -2551,20 +2503,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
        return label;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
        struct sljit_jump *jump;
 
        CHECK_ERROR_PTR();
        CHECK_PTR(check_sljit_emit_jump(compiler, type));
 
-       if (SLJIT_UNLIKELY(compiler->flags_saved)) {
-               if ((type & 0xff) <= SLJIT_JUMP)
-                       PTR_FAIL_IF(emit_restore_flags(compiler, 0));
-               compiler->flags_saved = 0;
-       }
-
        jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
        PTR_FAIL_IF_NULL(jump);
        set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
@@ -2580,17 +2526,25 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
        compiler->size += (type >= SLJIT_JUMP) ? (10 + 3) : (2 + 10 + 3);
 #endif
 
-       inst = (sljit_ub*)ensure_buf(compiler, 2);
+       inst = (sljit_u8*)ensure_buf(compiler, 2);
        PTR_FAIL_IF_NULL(inst);
 
        *inst++ = 0;
-       *inst++ = type + 4;
+       *inst++ = type + 2;
        return jump;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+#ifndef _WIN64
+#define IS_REG_CHANGED_BY_CALL(src, type) ((src) == SLJIT_R3)
+#else
+#define IS_REG_CHANGED_BY_CALL(src, type) ((src) == SLJIT_R2)
+#endif
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
 {
-       sljit_ub *inst;
+       sljit_u8 *inst;
        struct sljit_jump *jump;
 
        CHECK_ERROR();
@@ -2599,12 +2553,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
 
        CHECK_EXTRA_REGS(src, srcw, (void)0);
 
-       if (SLJIT_UNLIKELY(compiler->flags_saved)) {
-               if (type <= SLJIT_JUMP)
-                       FAIL_IF(emit_restore_flags(compiler, 0));
-               compiler->flags_saved = 0;
-       }
-
        if (type >= SLJIT_CALL1) {
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
 #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
@@ -2615,11 +2563,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
                if (src == SLJIT_MEM1(SLJIT_SP) && type >= SLJIT_CALL3)
                        srcw += sizeof(sljit_sw);
 #endif
-#endif
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64)
-               if (src == SLJIT_R2) {
-                       EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
-                       src = TMP_REG1;
+#else
+               if ((src & SLJIT_MEM) || IS_REG_CHANGED_BY_CALL(src, type)) {
+                       EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
+                       src = TMP_REG2;
                }
 #endif
                FAIL_IF(call_with_args(compiler, type));
@@ -2638,11 +2585,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
                compiler->size += 10 + 3;
 #endif
 
-               inst = (sljit_ub*)ensure_buf(compiler, 2);
+               inst = (sljit_u8*)ensure_buf(compiler, 2);
                FAIL_IF_NULL(inst);
 
                *inst++ = 0;
-               *inst++ = type + 4;
+               *inst++ = type + 2;
        }
        else {
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -2657,40 +2604,32 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
        return SLJIT_SUCCESS;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
-       sljit_si dst, sljit_sw dstw,
-       sljit_si src, sljit_sw srcw,
-       sljit_si type)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+       sljit_s32 dst, sljit_sw dstw,
+       sljit_s32 type)
 {
-       sljit_ub *inst;
-       sljit_ub cond_set = 0;
+       sljit_u8 *inst;
+       sljit_u8 cond_set = 0;
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       sljit_si reg;
-#else
-       /* CHECK_EXTRA_REGS migh overwrite these values. */
-       sljit_si dst_save = dst;
-       sljit_sw dstw_save = dstw;
+       sljit_s32 reg;
 #endif
+       /* ADJUST_LOCAL_OFFSET and CHECK_EXTRA_REGS might overwrite these values. */
+       sljit_s32 dst_save = dst;
+       sljit_sw dstw_save = dstw;
 
        CHECK_ERROR();
-       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
-       SLJIT_UNUSED_ARG(srcw);
-
-       if (dst == SLJIT_UNUSED)
-               return SLJIT_SUCCESS;
+       CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
 
        ADJUST_LOCAL_OFFSET(dst, dstw);
        CHECK_EXTRA_REGS(dst, dstw, (void)0);
-       if (SLJIT_UNLIKELY(compiler->flags_saved))
-               FAIL_IF(emit_restore_flags(compiler, op & SLJIT_KEEP_FLAGS));
 
        type &= 0xff;
        /* setcc = jcc + 0x10. */
        cond_set = get_jump_code(type) + 0x10;
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && dst == src) {
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 3);
+       if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst)) {
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 3);
                FAIL_IF(!inst);
                INC_SIZE(4 + 3);
                /* Set low register to conditional flag. */
@@ -2704,9 +2643,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
                return SLJIT_SUCCESS;
        }
 
-       reg = (op == SLJIT_MOV && FAST_IS_REG(dst)) ? dst : TMP_REG1;
+       reg = (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG1;
 
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 4);
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 4);
        FAIL_IF(!inst);
        INC_SIZE(4 + 4);
        /* Set low register to conditional flag. */
@@ -2715,6 +2654,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
        *inst++ = cond_set;
        *inst++ = MOD_REG | reg_lmap[reg];
        *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));
+       /* The movzx instruction does not affect flags. */
        *inst++ = GROUP_0F;
        *inst++ = MOVZX_r_rm8;
        *inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg];
@@ -2726,16 +2666,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
                compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV;
                return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
        }
+
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
                || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
        compiler->skip_checks = 1;
 #endif
-       return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REG1, 0);
-#else /* SLJIT_CONFIG_X86_64 */
+       return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
+
+#else
+       /* The SLJIT_CONFIG_X86_32 code path starts here. */
        if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) {
                if (reg_map[dst] <= 4) {
                        /* Low byte is accessible. */
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3);
                        FAIL_IF(!inst);
                        INC_SIZE(3 + 3);
                        /* Set low byte to conditional flag. */
@@ -2758,7 +2701,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
                        /* a xor reg, reg operation would overwrite the flags. */
                        EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0);
 
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 3);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
                        FAIL_IF(!inst);
                        INC_SIZE(3);
 
@@ -2769,7 +2712,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
                        return SLJIT_SUCCESS;
                }
 
-               inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
+               inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
                FAIL_IF(!inst);
                INC_SIZE(1 + 3 + 3 + 1);
                *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
@@ -2785,10 +2728,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
                return SLJIT_SUCCESS;
        }
 
-       if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && dst == src && reg_map[dst] <= 4) {
-               SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] == 0, scratch_reg1_must_be_eax);
+       if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && reg_map[dst] <= 4) {
+               SLJIT_ASSERT(reg_map[SLJIT_R0] == 0);
+
                if (dst != SLJIT_R0) {
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1);
                        FAIL_IF(!inst);
                        INC_SIZE(1 + 3 + 2 + 1);
                        /* Set low register to conditional flag. */
@@ -2801,7 +2745,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
                        *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
                }
                else {
-                       inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 3 + 2 + 2);
+                       inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 3 + 2 + 2);
                        FAIL_IF(!inst);
                        INC_SIZE(2 + 3 + 2 + 2);
                        /* Set low register to conditional flag. */
@@ -2819,7 +2763,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
        }
 
        /* Set TMP_REG1 to the bit. */
-       inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
+       inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
        FAIL_IF(!inst);
        INC_SIZE(1 + 3 + 3 + 1);
        *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
@@ -2845,7 +2789,47 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
 #endif /* SLJIT_CONFIG_X86_64 */
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
+       sljit_s32 dst_reg,
+       sljit_s32 src, sljit_sw srcw)
+{
+       sljit_u8* inst;
+
+       CHECK_ERROR();
+       CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       dst_reg &= ~SLJIT_I32_OP;
+
+       if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3))
+               return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
+#else
+       if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV))
+               return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
+#endif
+
+       /* ADJUST_LOCAL_OFFSET is not needed. */
+       CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = dst_reg & SLJIT_I32_OP;
+       dst_reg &= ~SLJIT_I32_OP;
+#endif
+
+       if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
+               EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
+               src = TMP_REG1;
+               srcw = 0;
+       }
+
+       inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw);
+       FAIL_IF(!inst);
+       *inst++ = GROUP_0F;
+       *inst = get_jump_code(type & 0xff) - 0x40;
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
 {
        CHECK_ERROR();
        CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
@@ -2863,25 +2847,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *co
        if (NOT_HALFWORD(offset)) {
                FAIL_IF(emit_load_imm64(compiler, TMP_REG1, offset));
 #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
-               SLJIT_ASSERT(emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);
+               SLJIT_ASSERT(emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);
                return compiler->error;
 #else
-               return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0);
+               return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0);
 #endif
        }
 #endif
 
        if (offset != 0)
-               return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
+               return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
        return emit_mov(compiler, dst, dstw, SLJIT_SP, 0);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
+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_ub *inst;
+       sljit_u8 *inst;
        struct sljit_const *const_;
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       sljit_si reg;
+       sljit_s32 reg;
 #endif
 
        CHECK_ERROR_PTR();
@@ -2896,19 +2880,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
 
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
        compiler->mode32 = 0;
-       reg = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+       reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
 
        if (emit_load_imm64(compiler, reg, init_value))
                return NULL;
 #else
-       if (dst == SLJIT_UNUSED)
-               dst = TMP_REG1;
-
        if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value))
                return NULL;
 #endif
 
-       inst = (sljit_ub*)ensure_buf(compiler, 2);
+       inst = (sljit_u8*)ensure_buf(compiler, 2);
        PTR_FAIL_IF(!inst);
 
        *inst++ = 0;
@@ -2923,82 +2904,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
        return const_;
 }
 
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+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);
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-       *(sljit_sw*)addr = new_addr - (addr + 4);
-#else
-       *(sljit_uw*)addr = new_addr;
-#endif
-}
-
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
-{
-       *(sljit_sw*)addr = new_constant;
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_sse2_available(void)
-{
-#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
-       if (cpu_has_sse2 == -1)
-               get_cpu_features();
-       return cpu_has_sse2;
+       sljit_unaligned_store_sw((void*)addr, new_target - (addr + 4) - (sljit_uw)executable_offset);
 #else
-       return 1;
+       sljit_unaligned_store_sw((void*)addr, (sljit_sw) new_target);
 #endif
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_cmov_available(void)
-{
-       if (cpu_has_cmov == -1)
-               get_cpu_features();
-       return cpu_has_cmov;
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_emit_cmov(struct sljit_compiler *compiler,
-       sljit_si type,
-       sljit_si dst_reg,
-       sljit_si src, sljit_sw srcw)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
 {
-       sljit_ub* inst;
-
-       CHECK_ERROR();
-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
-       CHECK_ARGUMENT(sljit_x86_is_cmov_available());
-       CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_INT_OP)));
-       CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_D_ORDERED);
-       CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_INT_OP));
-       FUNCTION_CHECK_SRC(src, srcw);
-#endif
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
-       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
-               fprintf(compiler->verbose, "  x86_cmov%s %s%s, ",
-                       !(dst_reg & SLJIT_INT_OP) ? "" : ".i",
-                       JUMP_PREFIX(type), jump_names[type & 0xff]);
-               sljit_verbose_reg(compiler, dst_reg & ~SLJIT_INT_OP);
-               fprintf(compiler->verbose, ", ");
-               sljit_verbose_param(compiler, src, srcw);
-               fprintf(compiler->verbose, "\n");
-       }
-#endif
-
-       ADJUST_LOCAL_OFFSET(src, srcw);
-       CHECK_EXTRA_REGS(src, srcw, (void)0);
-
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-       compiler->mode32 = dst_reg & SLJIT_INT_OP;
-#endif
-       dst_reg &= ~SLJIT_INT_OP;
-
-       if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
-               EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
-               src = TMP_REG1;
-               srcw = 0;
-       }
-
-       inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw);
-       FAIL_IF(!inst);
-       *inst++ = GROUP_0F;
-       *inst = get_jump_code(type & 0xff) - 0x40;
-       return SLJIT_SUCCESS;
+       SLJIT_UNUSED_ARG(executable_offset);
+       sljit_unaligned_store_sw((void*)addr, new_constant);
 }
index 5294b5f3f9be7c35a8f0ceb19812e9699bd3c6dd..9029db292c0a31ab143726b4ac7baca8c6da8e2a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Stack-less Just-In-Time compiler
  *
- *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -163,11 +163,11 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
 #include <fcntl.h>
 
 /* Some old systems does not have MAP_ANON. */
-static sljit_si dev_zero = -1;
+static sljit_s32 dev_zero = -1;
 
 #if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
 
-static SLJIT_INLINE sljit_si open_dev_zero(void)
+static SLJIT_INLINE sljit_s32 open_dev_zero(void)
 {
        dev_zero = open("/dev/zero", O_RDWR);
        return dev_zero < 0;
@@ -179,10 +179,13 @@ static SLJIT_INLINE sljit_si open_dev_zero(void)
 
 static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-static SLJIT_INLINE sljit_si open_dev_zero(void)
+static SLJIT_INLINE sljit_s32 open_dev_zero(void)
 {
        pthread_mutex_lock(&dev_zero_mutex);
-       dev_zero = open("/dev/zero", O_RDWR);
+       /* The dev_zero might be initialized by another thread during the waiting. */
+       if (dev_zero < 0) {
+               dev_zero = open("/dev/zero", O_RDWR);
+       }
        pthread_mutex_unlock(&dev_zero_mutex);
        return dev_zero < 0;
 }
@@ -203,10 +206,7 @@ static sljit_sw sljit_page_align = 0;
 SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data)
 {
        struct sljit_stack *stack;
-       union {
-               void *ptr;
-               sljit_uw uw;
-       } base;
+       void *ptr;
 #ifdef _WIN32
        SYSTEM_INFO si;
 #endif
@@ -230,29 +230,29 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
        }
 #endif
 
-       /* Align limit and max_limit. */
-       max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
-
        stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
        if (!stack)
                return NULL;
 
+       /* Align max_limit. */
+       max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
+
 #ifdef _WIN32
-       base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
-       if (!base.ptr) {
+       ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
+       if (!ptr) {
                SLJIT_FREE(stack, allocator_data);
                return NULL;
        }
-       stack->base = base.uw;
+       stack->max_limit = (sljit_u8 *)ptr;
+       stack->base = stack->max_limit + max_limit;
        stack->limit = stack->base;
-       stack->max_limit = stack->base + max_limit;
-       if (sljit_stack_resize(stack, stack->base + limit)) {
+       if (sljit_stack_resize(stack, stack->base - limit)) {
                sljit_free_stack(stack, allocator_data);
                return NULL;
        }
 #else
 #ifdef MAP_ANON
-       base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+       ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
 #else
        if (dev_zero < 0) {
                if (open_dev_zero()) {
@@ -260,15 +260,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
                        return NULL;
                }
        }
-       base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
+       ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
 #endif
-       if (base.ptr == MAP_FAILED) {
+       if (ptr == MAP_FAILED) {
                SLJIT_FREE(stack, allocator_data);
                return NULL;
        }
-       stack->base = base.uw;
-       stack->limit = stack->base + limit;
-       stack->max_limit = stack->base + max_limit;
+       stack->max_limit = (sljit_u8 *)ptr;
+       stack->base = stack->max_limit + max_limit;
+       stack->limit = stack->base - limit;
 #endif
        stack->top = stack->base;
        return stack;
@@ -276,53 +276,53 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
 
 #undef PAGE_ALIGN
 
-SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stackstack, void *allocator_data)
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
 {
        SLJIT_UNUSED_ARG(allocator_data);
 #ifdef _WIN32
-       VirtualFree((void*)stack->base, 0, MEM_RELEASE);
+       VirtualFree((void*)stack->max_limit, 0, MEM_RELEASE);
 #else
-       munmap((void*)stack->base, stack->max_limit - stack->base);
+       munmap((void*)stack->max_limit, stack->base - stack->max_limit);
 #endif
        SLJIT_FREE(stack, allocator_data);
 }
 
-SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_limit)
 {
        sljit_uw aligned_old_limit;
        sljit_uw aligned_new_limit;
 
-       if ((new_limit > stack->max_limit) || (new_limit < stack->base))
+       if ((new_limit < stack->max_limit) || (new_limit >= stack->base))
                return -1;
 #ifdef _WIN32
-       aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
-       aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
+       aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align;
+       aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align;
        if (aligned_new_limit != aligned_old_limit) {
-               if (aligned_new_limit > aligned_old_limit) {
-                       if (!VirtualAlloc((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_COMMIT, PAGE_READWRITE))
+               if (aligned_new_limit < aligned_old_limit) {
+                       if (!VirtualAlloc((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_COMMIT, PAGE_READWRITE))
                                return -1;
                }
                else {
-                       if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT))
+                       if (!VirtualFree((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_DECOMMIT))
                                return -1;
                }
        }
        stack->limit = new_limit;
        return 0;
 #else
-       if (new_limit >= stack->limit) {
+       if (new_limit <= stack->limit) {
                stack->limit = new_limit;
                return 0;
        }
-       aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
-       aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
+       aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align;
+       aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align;
        /* If madvise is available, we release the unnecessary space. */
 #if defined(MADV_DONTNEED)
-       if (aligned_new_limit < aligned_old_limit)
-               madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
+       if (aligned_new_limit > aligned_old_limit)
+               madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MADV_DONTNEED);
 #elif defined(POSIX_MADV_DONTNEED)
-       if (aligned_new_limit < aligned_old_limit)
-               posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED);
+       if (aligned_new_limit > aligned_old_limit)
+               posix_madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, POSIX_MADV_DONTNEED);
 #endif
        stack->limit = new_limit;
        return 0;
index 8379ce04d5b1ff83d989d3500949aa8acb0e028e..5c23f41fa818d00bd6f578a36de2ae47fe882b87 100644 (file)
@@ -5733,4 +5733,13 @@ AbcdCBefgBhiBqz
 "(?|(\k'Pm')|(?'Pm'))"
     abcd
 
+/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[,;:])(?=.{8,16})(?!.*[\s])/
+    \  Fred:099
+
+/(?=.*X)X$/ 
+    \  X
+     
+/X+(?#comment)?/
+    >XXX<
+
 /-- End of testinput1 --/
index ac9d2289854a1cf09543b7ad239648b10b0a42b3..6f0989a14c2b7947833abb60115cc856cbe99315 100644 (file)
@@ -138,4 +138,6 @@ is required for these tests. --/
 
 /.((?2)(?R)\1)()/B
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+
 /-- End of testinput11 --/
index 944be6943f5e17c7ca9a29c2b4620b295816119c..89ed4564bcd48348cae3333cdfdcbc6ac0b8153f 100644 (file)
@@ -104,4 +104,6 @@ and a couple of things that are different with JIT. --/
 /(.|.)*?bx/
     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabax
 
+/((?(?!))x)(?'name')(?1)/S++
+
 /-- End of testinput12 --/
index 83e26773471b7044a062f7d45d006f40cb452dc3..c065105b1ece9a9852227e4bd97d5af55727e0a5 100644 (file)
@@ -363,4 +363,7 @@ correctly, but that messes up comparisons). --/
 
 /abc/89
 
+//8+L
+    \xf1\xad\xae\xae
+
 /-- End of testinput15 --/
index 15419e63fa61cba7e96526493fa43dad1ab7b8bc..7ccde0a8c80dc3c435e4b1eff6f3dae85b1cef04 100644 (file)
 /s+/i8SI
     SSss\x{17f}
 
+/[\W\p{Any}]/BZ
+    abc
+    123 
+
+/[\W\pL]/BZ
+    abc
+    ** Failers 
+    123
+    
+/[\D]/8
+    \x{1d7cf}
+
+/[\D\P{Nd}]/8
+    \x{1d7cf}
+
+/[^\D]/8
+    a9b
+    ** Failers
+    \x{1d7cf}
+
+/[^\D\P{Nd}]/8
+    a9b
+    \x{1d7cf}
+    ** Failers
+    \x{10000}
+
 /-- End of testinput16 --/
index ce45afcb595362343e896f4e452d3715f643372b..dfe8c7befb65adadbce642f67af1909e23362739 100644 (file)
 /s+/i8SI
     SSss\x{17f}
 
+/[\D]/8
+    \x{1d7cf}
+
+/[\D\P{Nd}]/8
+    \x{1d7cf}
+
+/[^\D]/8
+    a9b
+    ** Failers
+    \x{1d7cf}
+
+/[^\D\P{Nd}]/8
+    a9b
+    \x{1d7cf}
+    ** Failers
+    \x{10000}
+
 /-- End of testinput19 --/ 
index e2e520f74042269fae65ad8f058ea28b3db8cf51..08c6f39a565b9974d298a376e068334f4000789d 100644 (file)
@@ -4217,4 +4217,36 @@ backtracking verbs. --/
 
 /a[[:punct:]b]/BZ
 
+/L(?#(|++<!(2)?/BZ
+
+/L(?#(|++<!(2)?/BOZ
+
+/L(?#(|++<!(2)?/BCZ
+
+/L(?#(|++<!(2)?/BCOZ
+
+/(A*)\E+/CBZ
+
+/()\Q\E*]/BCZ
+
+/(?<A>)(?J:(?<B>)(?<B>))(?<C>)/
+    \O\CC
+
+/(?=a\K)/ 
+    ring bpattingbobnd $ 1,oern cou \rb\L
+
+/(?<=((?C)0))/
+    9010
+    abcd
+     
+/((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/
+
+/\N(?(?C)0?!.)*/
+
+/(?<RA>abc)(?(R)xyz)/BZ
+
+/(?<R>abc)(?(R)xyz)/BZ
+
+/(?=.*[A-Z])/I
+
 /-- End of testinput2 --/
index aeb62a073fa0d87fdcf5d39081d714d189b80959..22ed1e64d57944318f3abdb98fe1cd7651953c77 100644 (file)
     \x{200}
     \x{37e}
 
+/[^[:^ascii:]\d]/8W
+    a
+    ~
+    0
+    \a
+    \x{7f}
+    \x{389}
+    \x{20ac}
+
+/(?=.*b)\pL/
+    11bb
+    
+/(?(?=.*b)(?=.*b)\pL|.*c)/
+    11bb
+
 /-- End of testinput6 --/
index e411a4b842e691771765a1a29f2994f0b525caba..f44a810f0f247a721e3bb32d77ce2e4089e2f088 100644 (file)
@@ -838,19 +838,14 @@ of case for anything other than the ASCII letters. --/
 /^s?c/mi8I
     scat
 
-/[\W\p{Any}]/BZ
-    abc
-    123 
-
-/[\W\pL]/BZ
-    abc
-    ** Failers 
-    123     
-
 /a[[:punct:]b]/WBZ
 
 /a[[:punct:]b]/8WBZ
 
 /a[b[:punct:]]/8WBZ
 
+/L(?#(|++<!(2)?/B8COZ
+
+/L(?#(|++<!(2)?/B8WCZ
+
 /-- End of testinput7 --/
index 931dd717e746221089c75cb5b50adec7b71acc7b..e931410479fc7ce9df1a5256284619b9bdc3eeed 100644 (file)
     bbb
     aaa 
 
+/()()a+/O=
+    aaa\D
+    a\D
+
+/(02-)?[0-9]{3}-[0-9]{3}/
+    02-123-123
+
 /-- End of testinput8 --/
index e852ab9544cb5e282c60507ae723caad76af93b7..eff8ecc948c04abee3ef7e05538785027061ba31 100644 (file)
@@ -9434,4 +9434,16 @@ No match
  0: 
  1: 
 
+/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[,;:])(?=.{8,16})(?!.*[\s])/
+    \  Fred:099
+ 0: 
+
+/(?=.*X)X$/ 
+    \  X
+ 0: X
+     
+/X+(?#comment)?/
+    >XXX<
+ 0: X
+
 /-- End of testinput1 --/
index 9a0a12d509fd12e6b91027334dfcada4568974e4..3c485da7083c90702aaf3d128766779fb6792e05 100644 (file)
@@ -231,7 +231,7 @@ Memory allocation (code space): 73
 ------------------------------------------------------------------
 
 /(?P<a>a)...(?P=a)bbb(?P>a)d/BM
-Memory allocation (code space): 77
+Memory allocation (code space): 93
 ------------------------------------------------------------------
   0  24 Bra
   2   5 CBra 1
@@ -765,4 +765,7 @@ Memory allocation (code space): 14
  25     End
 ------------------------------------------------------------------
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: regular expression is too complicated at offset 490
+
 /-- End of testinput11 --/
index 57e5da02795293ce1586068242d7263098d61c79..e19518db594449c9223b042cb22a4a28ce3dd0c0 100644 (file)
@@ -231,7 +231,7 @@ Memory allocation (code space): 155
 ------------------------------------------------------------------
 
 /(?P<a>a)...(?P=a)bbb(?P>a)d/BM
-Memory allocation (code space): 157
+Memory allocation (code space): 189
 ------------------------------------------------------------------
   0  24 Bra
   2   5 CBra 1
@@ -765,4 +765,7 @@ Memory allocation (code space): 28
  25     End
 ------------------------------------------------------------------
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: missing ) at offset 509
+
 /-- End of testinput11 --/
index 748548a5abbd25cb8be4340be243ce35ac5ad1c4..5a4fbb23663f646a4746889cb6c95145e2530521 100644 (file)
@@ -231,7 +231,7 @@ Memory allocation (code space): 45
 ------------------------------------------------------------------
 
 /(?P<a>a)...(?P=a)bbb(?P>a)d/BM
-Memory allocation (code space): 50
+Memory allocation (code space): 62
 ------------------------------------------------------------------
   0  30 Bra
   3   7 CBra 1
@@ -765,4 +765,7 @@ Memory allocation (code space): 10
  38     End
 ------------------------------------------------------------------
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: missing ) at offset 509
+
 /-- End of testinput11 --/
index 87911086f498c2f9ff3bf16fb36182464253a325..7632c4e580138c3c5306fd61d99a2ac41fe76a89 100644 (file)
@@ -201,4 +201,6 @@ No match, mark = m (JIT)
     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabax
 Error -8 (match limit exceeded)
 
+/((?(?!))x)(?'name')(?1)/S++
+
 /-- End of testinput12 --/
index bad2807c2fd9e14df14f240407d1680bc92bd64b..e4e123c39832b59e7312332b412a1ededcfa7963 100644 (file)
@@ -1136,4 +1136,9 @@ Failed: setting UTF is disabled by the application at offset 0
 /abc/89
 Failed: setting UTF is disabled by the application at offset 0
 
+//8+L
+    \xf1\xad\xae\xae
+ 0: 
+ 0+ \x{6dbae}
+
 /-- End of testinput15 --/
index fd184cdbeee7e88b871782405546ef8c3e6fb94b..e6ba26acfd4ca35253e96680781cb311c0bfb680 100644 (file)
@@ -138,4 +138,56 @@ Starting chars: S s \xc5
     SSss\x{17f}
  0: SSss\x{17f}
 
+/[\W\p{Any}]/BZ
+------------------------------------------------------------------
+        Bra
+        [\x00-/:-@[-^`{-\xff\p{Any}]
+        Ket
+        End
+------------------------------------------------------------------
+    abc
+ 0: a
+    123 
+ 0: 1
+
+/[\W\pL]/BZ
+------------------------------------------------------------------
+        Bra
+        [\x00-/:-@[-^`{-\xff\p{L}]
+        Ket
+        End
+------------------------------------------------------------------
+    abc
+ 0: a
+    ** Failers 
+ 0: *
+    123
+No match
+    
+/[\D]/8
+    \x{1d7cf}
+ 0: \x{1d7cf}
+
+/[\D\P{Nd}]/8
+    \x{1d7cf}
+ 0: \x{1d7cf}
+
+/[^\D]/8
+    a9b
+ 0: 9
+    ** Failers
+No match
+    \x{1d7cf}
+No match
+
+/[^\D\P{Nd}]/8
+    a9b
+ 0: 9
+    \x{1d7cf}
+ 0: \x{1d7cf}
+    ** Failers
+No match
+    \x{10000}
+No match
+
 /-- End of testinput16 --/
index eb8a8f6cd34aff179e32ca472cbcc035bd5de1b1..982bea4c136006384a2e06e17850c71825cfa514 100644 (file)
@@ -105,4 +105,30 @@ Starting chars: S s \xff
     SSss\x{17f}
  0: SSss\x{17f}
 
+/[\D]/8
+    \x{1d7cf}
+ 0: \x{1d7cf}
+
+/[\D\P{Nd}]/8
+    \x{1d7cf}
+ 0: \x{1d7cf}
+
+/[^\D]/8
+    a9b
+ 0: 9
+    ** Failers
+No match
+    \x{1d7cf}
+No match
+
+/[^\D\P{Nd}]/8
+    a9b
+ 0: 9
+    \x{1d7cf}
+ 0: \x{1d7cf}
+    ** Failers
+No match
+    \x{10000}
+No match
+
 /-- End of testinput19 --/ 
index 85c565d1326efa9ab0eff30a4fadf14e7aa17b33..811bbefc84c091deb073a40709cd0f25b7619215 100644 (file)
@@ -419,7 +419,7 @@ Need char = '>'
 
 /(?U)<.*>/I
 Capturing subpattern count = 0
-Options: ungreedy
+No options
 First char = '<'
 Need char = '>'
     abc<def>ghi<klm>nop
@@ -443,7 +443,7 @@ Need char = '='
 
 /(?U)={3,}?/I
 Capturing subpattern count = 0
-Options: ungreedy
+No options
 First char = '='
 Need char = '='
     abc========def
@@ -477,7 +477,7 @@ Failed: lookbehind assertion is not fixed length at offset 12
 
 /(?i)abc/I
 Capturing subpattern count = 0
-Options: caseless
+No options
 First char = 'a' (caseless)
 Need char = 'c' (caseless)
 
@@ -489,7 +489,7 @@ No need char
 
 /(?i)^1234/I
 Capturing subpattern count = 0
-Options: anchored caseless
+Options: anchored
 No first char
 No need char
 
@@ -502,7 +502,7 @@ No need char
 /(?s).*/I
 Capturing subpattern count = 0
 May match empty string
-Options: anchored dotall
+Options: anchored
 No first char
 No need char
 
@@ -516,7 +516,7 @@ Starting chars: a b c d
 
 /(?i)[abcd]/IS
 Capturing subpattern count = 0
-Options: caseless
+No options
 No first char
 No need char
 Subject length lower bound = 1
@@ -524,7 +524,7 @@ Starting chars: A B C D a b c d
 
 /(?m)[xy]|(b|c)/IS
 Capturing subpattern count = 1
-Options: multiline
+No options
 No first char
 No need char
 Subject length lower bound = 1
@@ -538,7 +538,7 @@ No need char
 
 /(?i)(^a|^b)/Im
 Capturing subpattern count = 1
-Options: caseless multiline
+Options: multiline
 First char at start or follows newline
 No need char
 
@@ -555,13 +555,13 @@ Failed: malformed number or name after (?( at offset 4
 Failed: malformed number or name after (?( at offset 4
 
 /(?(?i))/
-Failed: assertion expected after (?( at offset 3
+Failed: assertion expected after (?( or (?(?C) at offset 3
 
 /(?(abc))/
 Failed: reference to non-existent subpattern at offset 7
 
 /(?(?<ab))/
-Failed: assertion expected after (?( at offset 3
+Failed: assertion expected after (?( or (?(?C) at offset 3
 
 /((?s)blah)\s+\1/I
 Capturing subpattern count = 1
@@ -1179,7 +1179,7 @@ No need char
         End
 ------------------------------------------------------------------
 Capturing subpattern count = 1
-Options: anchored dotall
+Options: anchored
 No first char
 No need char
 
@@ -2735,7 +2735,7 @@ No match
         End
 ------------------------------------------------------------------
 Capturing subpattern count = 0
-Options: caseless extended
+Options: extended
 First char = 'a' (caseless)
 Need char = 'c' (caseless)
 
@@ -2748,7 +2748,7 @@ Need char = 'c' (caseless)
         End
 ------------------------------------------------------------------
 Capturing subpattern count = 0
-Options: caseless extended
+Options: extended
 First char = 'a' (caseless)
 Need char = 'c' (caseless)
 
@@ -3095,7 +3095,7 @@ Need char = 'b'
         End
 ------------------------------------------------------------------
 Capturing subpattern count = 0
-Options: ungreedy
+No options
 First char = 'x'
 Need char = 'b'
     xaaaab
@@ -3497,7 +3497,7 @@ Need char = 'c'
 
 /(?i)[ab]/IS
 Capturing subpattern count = 0
-Options: caseless
+No options
 No first char
 No need char
 Subject length lower bound = 1
@@ -6299,7 +6299,7 @@ Capturing subpattern count = 3
 Named capturing subpatterns:
   A   2
   A   3
-Options: anchored dupnames
+Options: anchored
 Duplicate name status changes
 No first char
 No need char
@@ -7870,7 +7870,7 @@ No match
 Failed: malformed number or name after (?( at offset 6
 
 /(?(''))/
-Failed: assertion expected after (?( at offset 4
+Failed: assertion expected after (?( or (?(?C) at offset 4
 
 /(?('R')stuff)/
 Failed: reference to non-existent subpattern at offset 7
@@ -9380,7 +9380,7 @@ No need char
 /(?(?=.*b).*b|^d)/I
 Capturing subpattern count = 0
 No options
-First char at start or follows newline
+No first char
 No need char
 
 /xyz/C
@@ -14346,7 +14346,7 @@ No match
 "((?2)+)((?1))"
 
 "(?(?<E>.*!.*)?)"
-Failed: assertion expected after (?( at offset 3
+Failed: assertion expected after (?( or (?(?C) at offset 3
 
 "X((?2)()*+){2}+"BZ
 ------------------------------------------------------------------
@@ -14574,4 +14574,135 @@ No match
         End
 ------------------------------------------------------------------
 
+/L(?#(|++<!(2)?/BZ
+------------------------------------------------------------------
+        Bra
+        L?+
+        Ket
+        End
+------------------------------------------------------------------
+
+/L(?#(|++<!(2)?/BOZ
+------------------------------------------------------------------
+        Bra
+        L?
+        Ket
+        End
+------------------------------------------------------------------
+
+/L(?#(|++<!(2)?/BCZ
+------------------------------------------------------------------
+        Bra
+        Callout 255 0 14
+        L?+
+        Callout 255 14 0
+        Ket
+        End
+------------------------------------------------------------------
+
+/L(?#(|++<!(2)?/BCOZ
+------------------------------------------------------------------
+        Bra
+        Callout 255 0 14
+        L?
+        Callout 255 14 0
+        Ket
+        End
+------------------------------------------------------------------
+
+/(A*)\E+/CBZ
+------------------------------------------------------------------
+        Bra
+        Callout 255 0 7
+        SCBra 1
+        Callout 255 1 2
+        A*
+        Callout 255 3 0
+        KetRmax
+        Callout 255 7 0
+        Ket
+        End
+------------------------------------------------------------------
+
+/()\Q\E*]/BCZ
+------------------------------------------------------------------
+        Bra
+        Callout 255 0 7
+        Brazero
+        SCBra 1
+        Callout 255 1 0
+        KetRmax
+        Callout 255 7 1
+        ]
+        Callout 255 8 0
+        Ket
+        End
+------------------------------------------------------------------
+
+/(?<A>)(?J:(?<B>)(?<B>))(?<C>)/
+    \O\CC
+Matched, but too many substrings
+copy substring C failed -7
+
+/(?=a\K)/ 
+    ring bpattingbobnd $ 1,oern cou \rb\L
+Start of matched string is beyond its end - displaying from end to start.
+ 0: a
+ 0L 
+
+/(?<=((?C)0))/
+    9010
+--->9010
+  0  ^       0
+  0   ^      0
+ 0: 
+ 1: 0
+    abcd
+--->abcd
+  0  ^       0
+  0   ^      0
+  0    ^     0
+  0     ^    0
+No match
+     
+/((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/
+
+/\N(?(?C)0?!.)*/
+Failed: assertion expected after (?( or (?(?C) at offset 4
+
+/(?<RA>abc)(?(R)xyz)/BZ
+------------------------------------------------------------------
+        Bra
+        CBra 1
+        abc
+        Ket
+        Cond
+        Cond recurse any
+        xyz
+        Ket
+        Ket
+        End
+------------------------------------------------------------------
+
+/(?<R>abc)(?(R)xyz)/BZ
+------------------------------------------------------------------
+        Bra
+        CBra 1
+        abc
+        Ket
+        Cond
+      1 Cond ref
+        xyz
+        Ket
+        Ket
+        End
+------------------------------------------------------------------
+
+/(?=.*[A-Z])/I
+Capturing subpattern count = 0
+May match empty string
+No options
+No first char
+No need char
+
 /-- End of testinput2 --/
index beb85aaa0b6ec20d4a3018328fc9e7ea18f2c90a..422d38335780aad8b49cf76a23196d09569c60e5 100644 (file)
@@ -2557,4 +2557,28 @@ No match
     \x{37e}
  0: \x{37e}
 
+/[^[:^ascii:]\d]/8W
+    a
+ 0: a
+    ~
+ 0: ~
+    0
+No match
+    \a
+ 0: \x{07}
+    \x{7f}
+ 0: \x{7f}
+    \x{389}
+No match
+    \x{20ac}
+No match
+
+/(?=.*b)\pL/
+    11bb
+ 0: b
+    
+/(?(?=.*b)(?=.*b)\pL|.*c)/
+    11bb
+ 0: b
+
 /-- End of testinput6 --/
index cc9ebdd5588820bc4b927a60858b22ae3fb340c3..2b167b28d1c427743b2bf1b587afad44b13c5c69 100644 (file)
@@ -2295,33 +2295,25 @@ Need char = 'c' (caseless)
     scat
  0: sc
 
-/[\W\p{Any}]/BZ
+/a[[:punct:]b]/WBZ
 ------------------------------------------------------------------
         Bra
-        [\x00-/:-@[-^`{-\xff\p{Any}]
+        a
+        [b[:punct:]]
         Ket
         End
 ------------------------------------------------------------------
-    abc
- 0: a
-    123 
- 0: 1
 
-/[\W\pL]/BZ
+/a[[:punct:]b]/8WBZ
 ------------------------------------------------------------------
         Bra
-        [\x00-/:-@[-^`{-\xff\p{L}]
+        a
+        [b[:punct:]]
         Ket
         End
 ------------------------------------------------------------------
-    abc
- 0: a
-    ** Failers 
- 0: *
-    123     
-No match
 
-/a[[:punct:]b]/WBZ
+/a[b[:punct:]]/8WBZ
 ------------------------------------------------------------------
         Bra
         a
@@ -2330,20 +2322,22 @@ No match
         End
 ------------------------------------------------------------------
 
-/a[[:punct:]b]/8WBZ
+/L(?#(|++<!(2)?/B8COZ
 ------------------------------------------------------------------
         Bra
-        a
-        [b[:punct:]]
+        Callout 255 0 14
+        L?
+        Callout 255 14 0
         Ket
         End
 ------------------------------------------------------------------
 
-/a[b[:punct:]]/8WBZ
+/L(?#(|++<!(2)?/B8WCZ
 ------------------------------------------------------------------
         Bra
-        a
-        [b[:punct:]]
+        Callout 255 0 14
+        L?+
+        Callout 255 14 0
         Ket
         End
 ------------------------------------------------------------------
index e4fa4977561531c573e3b6f388698dc0fa224ccb..4984376d3c86f933f01fe27b370f678b53f2cdec 100644 (file)
@@ -7791,4 +7791,18 @@ Matched, but offsets vector is too small to show all matches
     aaa 
 No match
 
+/()()a+/O=
+    aaa\D
+** Show all captures ignored after DFA matching
+ 0: aaa
+ 1: aa
+ 2: a
+    a\D
+** Show all captures ignored after DFA matching
+ 0: a
+
+/(02-)?[0-9]{3}-[0-9]{3}/
+    02-123-123
+ 0: 02-123-123
+
 /-- End of testinput8 --/
index 9779afaa3668e51b3eece8d52fd69d7887ab093b..750e720d749eeb5452548e67a8cb227329dd6f59 100644 (file)
@@ -175,6 +175,10 @@ static PHP_MINFO_FUNCTION(pcre)
        php_info_print_table_row(2, "PCRE JIT Support", "not compiled in" );
 #endif
 
+#ifdef HAVE_PCRE_VALGRIND_SUPPORT
+       php_info_print_table_row(2, "PCRE Valgrind Support", "enabled" );
+#endif
+
        php_info_print_table_end();
 
        DISPLAY_INI_ENTRIES();
index 93d8722063de879b8eec2a9b96823a7c6851895c..8cdaa03b20bd5b1721d576935d4b9e3f04ac9b90 100755 (executable)
@@ -1915,14 +1915,19 @@ TEST $file
                $env['USE_ZEND_ALLOC'] = '0';
                $env['ZEND_DONT_UNLOAD_MODULES'] = 1;
 
+               $valgrind_cmd = "valgrind -q --tool=memcheck --trace-children=yes";
+               if (strpos($test_file, "pcre") !== false) {
+                       $valgrind_cmd .= " --smc-check=all";
+               }
+
                /* --vex-iropt-register-updates=allregs-at-mem-access is necessary for phpdbg watchpoint tests */
                if (version_compare($valgrind_version, '3.8.0', '>=')) {
                        /* valgrind 3.3.0+ doesn't have --log-file-exactly option */
-                       $cmd = "valgrind -q --tool=memcheck --trace-children=yes --vex-iropt-register-updates=allregs-at-mem-access --log-file=$memcheck_filename $cmd";
+                       $cmd = "$valgrind_cmd --vex-iropt-register-updates=allregs-at-mem-access --log-file=$memcheck_filename $cmd";
                } elseif (version_compare($valgrind_version, '3.3.0', '>=')) {
-                       $cmd = "valgrind -q --tool=memcheck --trace-children=yes --vex-iropt-precise-memory-exns=yes --log-file=$memcheck_filename $cmd";
+                       $cmd = "$valgrind_cmd --vex-iropt-precise-memory-exns=yes --log-file=$memcheck_filename $cmd";
                } else {
-                       $cmd = "valgrind -q --tool=memcheck --trace-children=yes --vex-iropt-precise-memory-exns=yes --log-file-exactly=$memcheck_filename $cmd";
+                       $cmd = "$valgrind_cmd --vex-iropt-precise-memory-exns=yes --log-file-exactly=$memcheck_filename $cmd";
                }
 
        } else {