pcre2 2.2.1 → 2.2.2
raw patch · 86 files changed
+84297/−63168 lines, 86 files
Files
- README.md +16/−24
- pcre2.cabal +25/−11
- src/c/config.h +50/−18
- src/c/pcre2.h +55/−38
- src/c/pcre2/maint/ucptest.c +68/−130
- src/c/pcre2/src/pcre2_auto_possess.c +11/−5
- src/c/pcre2/src/pcre2_chkdint.c +96/−0
- src/c/pcre2/src/pcre2_compile.c +10990/−10612
- src/c/pcre2/src/pcre2_context.c +43/−21
- src/c/pcre2/src/pcre2_convert.c +10/−3
- src/c/pcre2/src/pcre2_dfa_match.c +119/−60
- src/c/pcre2/src/pcre2_dftables.c +7/−13
- src/c/pcre2/src/pcre2_error.c +7/−3
- src/c/pcre2/src/pcre2_extuni.c +21/−7
- src/c/pcre2/src/pcre2_find_bracket.c +5/−5
- src/c/pcre2/src/pcre2_fuzzsupport.c +531/−108
- src/c/pcre2/src/pcre2_internal.h +104/−68
- src/c/pcre2/src/pcre2_intmodedep.h +48/−42
- src/c/pcre2/src/pcre2_jit_compile.c +14919/−14456
- src/c/pcre2/src/pcre2_jit_match.c +15/−1
- src/c/pcre2/src/pcre2_jit_misc.c +5/−3
- src/c/pcre2/src/pcre2_jit_neon_inc.h +30/−23
- src/c/pcre2/src/pcre2_jit_simd_inc.h +2309/−1812
- src/c/pcre2/src/pcre2_jit_test.c +34/−14
- src/c/pcre2/src/pcre2_maketables.c +5/−3
- src/c/pcre2/src/pcre2_match.c +419/−178
- src/c/pcre2/src/pcre2_match_data.c +21/−2
- src/c/pcre2/src/pcre2_printint.c +102/−84
- src/c/pcre2/src/pcre2_study.c +97/−7
- src/c/pcre2/src/pcre2_substitute.c +14/−11
- src/c/pcre2/src/pcre2_substring.c +5/−2
- src/c/pcre2/src/pcre2_tables.c +6/−6
- src/c/pcre2/src/pcre2_ucd.c +5380/−5316
- src/c/pcre2/src/pcre2_ucp.h +25/−23
- src/c/pcre2/src/pcre2_ucptables.c +269/−260
- src/c/pcre2/src/pcre2_valid_utf.c +24/−24
- src/c/pcre2/src/pcre2_xclass.c +36/−17
- src/c/pcre2/src/pcre2grep.c +220/−94
- src/c/pcre2/src/pcre2posix.c +72/−87
- src/c/pcre2/src/pcre2posix.h +32/−15
- src/c/pcre2/src/pcre2posix_test.c +209/−0
- src/c/pcre2/src/pcre2test.c +451/−194
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c +137/−0
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c +327/−0
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c +89/−0
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c +62/−0
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c +40/−0
- src/c/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c +72/−0
- src/c/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c +172/−0
- src/c/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c +141/−0
- src/c/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c +102/−0
- src/c/pcre2/src/sljit/sljitConfig.h +3/−33
- src/c/pcre2/src/sljit/sljitConfigCPU.h +188/−0
- src/c/pcre2/src/sljit/sljitConfigInternal.h +264/−234
- src/c/pcre2/src/sljit/sljitExecAllocator.c +0/−411
- src/c/pcre2/src/sljit/sljitLir.c +3464/−2664
- src/c/pcre2/src/sljit/sljitLir.h +2422/−1549
- src/c/pcre2/src/sljit/sljitNativeARM_32.c +4599/−3083
- src/c/pcre2/src/sljit/sljitNativeARM_64.c +3396/−2091
- src/c/pcre2/src/sljit/sljitNativeARM_T2_32.c +4233/−2585
- src/c/pcre2/src/sljit/sljitNativeLOONGARCH_64.c +3765/−0
- src/c/pcre2/src/sljit/sljitNativeMIPS_32.c +197/−383
- src/c/pcre2/src/sljit/sljitNativeMIPS_64.c +108/−426
- src/c/pcre2/src/sljit/sljitNativeMIPS_common.c +4230/−2481
- src/c/pcre2/src/sljit/sljitNativePPC_32.c +223/−22
- src/c/pcre2/src/sljit/sljitNativePPC_64.c +263/−53
- src/c/pcre2/src/sljit/sljitNativePPC_common.c +3060/−2488
- src/c/pcre2/src/sljit/sljitNativeRISCV_32.c +142/−0
- src/c/pcre2/src/sljit/sljitNativeRISCV_64.c +222/−0
- src/c/pcre2/src/sljit/sljitNativeRISCV_common.c +3121/−0
- src/c/pcre2/src/sljit/sljitNativeS390X.c +4476/−3335
- src/c/pcre2/src/sljit/sljitNativeSPARC_32.c +0/−283
- src/c/pcre2/src/sljit/sljitNativeSPARC_common.c +0/−1673
- src/c/pcre2/src/sljit/sljitNativeX86_32.c +1601/−1339
- src/c/pcre2/src/sljit/sljitNativeX86_64.c +611/−197
- src/c/pcre2/src/sljit/sljitNativeX86_common.c +4950/−3070
- src/c/pcre2/src/sljit/sljitProtExecAllocator.c +0/−474
- src/c/pcre2/src/sljit/sljitSerialize.c +516/−0
- src/c/pcre2/src/sljit/sljitWXExecAllocator.c +0/−229
- src/c/pcre2/vms/stdint.h +9/−0
- src/c/pcre2_chartables.c +3/−9
- src/hs/Text/Regex/Pcre2.hs +18/−57
- src/hs/Text/Regex/Pcre2/Foreign/TH.hs +5/−8
- src/hs/Text/Regex/Pcre2/Internal.hs +74/−89
- src/hs/Text/Regex/Pcre2/TH.hs +83/−102
- test/Spec.hs +4/−0
README.md view
@@ -3,7 +3,7 @@  [](https://hackage.haskell.org/package/pcre2) -Regular expressions for Haskell. +Regular expressions for Haskell. ## Teasers ```haskell@@ -16,7 +16,7 @@ ```haskell case "The quick brown fox" of [regex|\bbrown\s+(?<animal>[A-z]+)\b|] -> Text.putStrLn animal- _ -> error "nothing brown"+ _ -> die "nothing brown" ``` ```haskell let kv'd = lined . packed . [_regex|(?x) # Extended PCRE2 syntax@@ -38,31 +38,30 @@ Just v' | v /= v' -> do liftIO $ Text.putStrLn $ "setting " <> k <> " to " <> v' _capture @2 .= v'- _ -> liftIO $ Text.putStrLn "no change"+ _ -> liftIO $ Text.putStrLn $ "no change for " <> k ``` ## Features * No opaque "`Regex`" object. Instead, quiet functions with simple types—for the most part it's `Text` _(pattern)_ `-> Text` _(subject)_- `-> result`. Use partial application to create performant,- compile-once-match-many code.+ `-> result`. * No [custom typeclasses](https://hackage.haskell.org/package/regex-base/docs/Text-Regex-Base-RegexLike.html#t:RegexContext). * A single datatype for both compile and match options, the `Option` monoid.-* `Text` everywhere. See [below](#unicode) for a version guide.+* UTF-8 `Text` everywhere. * Match success expressed via `Alternative`. * Opt-in Template Haskell facilities for compile-time verification of patterns, indexing captures, and memoizing inline regexes. * Opt-in `lens` support. * No failure monads to express compile errors, preferring pure functions and- throwing imprecise exceptions with pretty `Show` instances. Write simple- code and debug it. Or, don't, and use the Template Haskell features instead.- Both are first-class.+ throwing imprecise exceptions with pretty `Show` instances. Write simple code+ and debug it. Or, don't, and use the Template Haskell features instead. Both+ are first-class. * Vast presentation of PCRE2 functionality. We can even register Haskell callbacks to run during matching! * Zero-copying of substrings where beneficial. * Few dependencies.-* Bundled, statically-linked UTF-8 (formerly UTF-16) build of up-to-date PCRE2- (version 10.40), with a complete, exposed Haskell binding.+* Bundled, statically-linked build of up-to-date PCRE2 (version 10.44), with a+ complete, exposed Haskell binding. ## Performance Currently we are slower than other libraries. For example:@@ -75,22 +74,15 @@ [pcre-light](https://hackage.haskell.org/package/pcre-light)/[-heavy](https://hackage.haskell.org/package/pcre-heavy)/[lens-regex-pcre](https://hackage.haskell.org/package/lens-regex-pcre) are recommended instead of this library for the very best performance. -## Unicode-| Encoding | `text` version | `pcre2` version | Code unit representation |-| :-- | :-- | :-- | :-- |-| UTF-8 | ≥ 2 | ≥ 2.2 | `Foreign.C.Types.CUChar` |-| UTF-16 | < 2 | < 2.2 | `Foreign.C.Types.CUShort` |- ## Wishlist-* Many performance optimizations. Currently we are slower than other libraries.- For example:-* Make use of DFA matching and JIT compilation.-* Improve PCRE2 C compile time.-* Add splitting support.+* Many performance optimizations.+* Make use of DFA matching for lazy (infinite) inputs. This likely requires+ some upstream changes as well but in theory it's possible+* Improve compile time. Support external `libpcre2` maybe ## License-[Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). +[Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). PCRE2 is distributed under the [3-clause BSD](https://www.pcre.org/licence.txt) license. ## Main Author-©2020–2022 Shlomo Shuck+©2020–2025 Steven Shuck
pcre2.cabal view
@@ -1,19 +1,19 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.34.4.+-- This file has been generated from package.yaml by hpack version 0.37.0. -- -- see: https://github.com/sol/hpack name: pcre2-version: 2.2.1+version: 2.2.2 synopsis: Regular expressions via the PCRE2 C library (included) description: Please see the README on GitHub at <https://github.com/sjshuck/hs-pcre2> category: Text homepage: https://github.com/sjshuck/hs-pcre2#readme bug-reports: https://github.com/sjshuck/hs-pcre2/issues-author: Shlomo Shuck and contributors+author: Steven Shuck and contributors maintainer: stevenjshuck@gmail.com-copyright: 2020-2022 Shlomo Shuck+copyright: 2020-2025 Steven Shuck license: Apache-2.0 license-file: LICENSE build-type: Simple@@ -30,11 +30,14 @@ src/c/pcre2/src/pcre2_ucp.h src/c/pcre2/src/pcre2posix.h src/c/pcre2/src/sljit/sljitConfig.h+ src/c/pcre2/src/sljit/sljitConfigCPU.h src/c/pcre2/src/sljit/sljitConfigInternal.h src/c/pcre2/src/sljit/sljitLir.h+ src/c/pcre2/vms/stdint.h src/c/pcre2/maint/ucptest.c src/c/pcre2/maint/utf8.c src/c/pcre2/src/pcre2_auto_possess.c+ src/c/pcre2/src/pcre2_chkdint.c src/c/pcre2/src/pcre2_compile.c src/c/pcre2/src/pcre2_config.c src/c/pcre2/src/pcre2_context.c@@ -70,27 +73,37 @@ src/c/pcre2/src/pcre2demo.c src/c/pcre2/src/pcre2grep.c src/c/pcre2/src/pcre2posix.c+ src/c/pcre2/src/pcre2posix_test.c src/c/pcre2/src/pcre2test.c- src/c/pcre2/src/sljit/sljitExecAllocator.c+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c+ src/c/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c+ src/c/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c+ src/c/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c+ src/c/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c src/c/pcre2/src/sljit/sljitLir.c src/c/pcre2/src/sljit/sljitNativeARM_32.c src/c/pcre2/src/sljit/sljitNativeARM_64.c src/c/pcre2/src/sljit/sljitNativeARM_T2_32.c+ src/c/pcre2/src/sljit/sljitNativeLOONGARCH_64.c src/c/pcre2/src/sljit/sljitNativeMIPS_32.c src/c/pcre2/src/sljit/sljitNativeMIPS_64.c src/c/pcre2/src/sljit/sljitNativeMIPS_common.c src/c/pcre2/src/sljit/sljitNativePPC_32.c src/c/pcre2/src/sljit/sljitNativePPC_64.c src/c/pcre2/src/sljit/sljitNativePPC_common.c+ src/c/pcre2/src/sljit/sljitNativeRISCV_32.c+ src/c/pcre2/src/sljit/sljitNativeRISCV_64.c+ src/c/pcre2/src/sljit/sljitNativeRISCV_common.c src/c/pcre2/src/sljit/sljitNativeS390X.c- src/c/pcre2/src/sljit/sljitNativeSPARC_32.c- src/c/pcre2/src/sljit/sljitNativeSPARC_common.c src/c/pcre2/src/sljit/sljitNativeX86_32.c src/c/pcre2/src/sljit/sljitNativeX86_64.c src/c/pcre2/src/sljit/sljitNativeX86_common.c- src/c/pcre2/src/sljit/sljitProtExecAllocator.c+ src/c/pcre2/src/sljit/sljitSerialize.c src/c/pcre2/src/sljit/sljitUtils.c- src/c/pcre2/src/sljit/sljitWXExecAllocator.c src/c/pcre2_chartables.c source-repository head@@ -109,14 +122,15 @@ Paths_pcre2 hs-source-dirs: src/hs- ghc-options: -W -optc=-DPCRE2_CODE_UNIT_WIDTH=8 -optc=-DPCRE2_STATIC=1 -optc=-Wno-discarded-qualifiers -optc=-Wno-incompatible-pointer-types- cc-options: -DHAVE_CONFIG_H -DPCRE2_CODE_UNIT_WIDTH=8 -DHAVE_INTTYPES_H=1 -DHAVE_LIMITS_H=1 -DHAVE_MEMMOVE_H=1 -DHAVE_STDINT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRERROR_H=1 -DHAVE_STRING_H=1 -DSUPPORT_JIT=1 -DSUPPORT_UNICODE=1+ ghc-options: -W -optc=-DPCRE2_CODE_UNIT_WIDTH=8 -optc=-DPCRE2_STATIC=1 -optc=-DSUPPORT_PCRE2_8 -optc=-Wno-discarded-qualifiers -optc=-Wno-incompatible-pointer-types+ cc-options: -DHAVE_CONFIG_H -DHAVE_INTTYPES_H=1 -DHAVE_LIMITS_H=1 -DHAVE_MEMMOVE_H=1 -DHAVE_STDINT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRERROR_H=1 -DHAVE_STRING_H=1 -DSUPPORT_JIT=1 -DSUPPORT_UNICODE=1 include-dirs: src/c src/c/pcre2/src c-sources: src/c/pcre2/src/pcre2_auto_possess.c src/c/pcre2_chartables.c+ src/c/pcre2/src/pcre2_chkdint.c src/c/pcre2/src/pcre2_compile.c src/c/pcre2/src/pcre2_config.c src/c/pcre2/src/pcre2_context.c
src/c/config.h view
@@ -55,9 +55,12 @@ /* Define this if your compiler supports __attribute__((uninitialized)) */ /* #undef HAVE_ATTRIBUTE_UNINITIALIZED */ -/* Define to 1 if you have the `bcopy' function. */+/* Define to 1 if you have the 'bcopy' function. */ /* #undef HAVE_BCOPY */ +/* Define this if your compiler provides __builtin_mul_overflow() */+/* #undef HAVE_BUILTIN_MUL_OVERFLOW */+ /* Define to 1 if you have the <bzlib.h> header file. */ /* #undef HAVE_BZLIB_H */ @@ -79,16 +82,16 @@ /* Define to 1 if you have the <limits.h> header file. */ /* #undef HAVE_LIMITS_H */ -/* Define to 1 if you have the `memfd_create' function. */+/* Define to 1 if you have the 'memfd_create' function. */ /* #undef HAVE_MEMFD_CREATE */ -/* Define to 1 if you have the `memmove' function. */+/* Define to 1 if you have the 'memmove' function. */ /* #undef HAVE_MEMMOVE */ /* Define to 1 if you have the <minix/config.h> header file. */ /* #undef HAVE_MINIX_CONFIG_H */ -/* Define to 1 if you have the `mkostemp' function. */+/* Define to 1 if you have the 'mkostemp' function. */ /* #undef HAVE_MKOSTEMP */ /* Define if you have POSIX threads libraries and header files. */@@ -109,7 +112,7 @@ /* Define to 1 if you have the `realpath' function. */ /* #undef HAVE_REALPATH */ -/* Define to 1 if you have the `secure_getenv' function. */+/* Define to 1 if you have the 'secure_getenv' function. */ /* #undef HAVE_SECURE_GETENV */ /* Define to 1 if you have the <stdint.h> header file. */@@ -121,7 +124,7 @@ /* Define to 1 if you have the <stdlib.h> header file. */ /* #undef HAVE_STDLIB_H */ -/* Define to 1 if you have the `strerror' function. */+/* Define to 1 if you have the 'strerror' function. */ /* #undef HAVE_STRERROR */ /* Define to 1 if you have the <strings.h> header file. */@@ -181,7 +184,7 @@ matching attempt. The value is also used to limit a loop counter in pcre2_dfa_match(). There is a runtime interface for setting a different limit. The limit exists in order to catch runaway regular expressions that- take for ever to determine that they do not match. The default is set very+ take forever to determine that they do not match. The default is set very large so that it does not accidentally catch legitimate cases. */ #ifndef MATCH_LIMIT #define MATCH_LIMIT 10000000@@ -212,9 +215,15 @@ Care must be taken if it is increased, because it guards against integer overflow caused by enormously large patterns. */ #ifndef MAX_NAME_SIZE-#define MAX_NAME_SIZE 32+#define MAX_NAME_SIZE 128 #endif +/* The value of MAX_VARLOOKBEHIND specifies the default maximum length, in+ characters, for a variable-length lookbehind assertion. */+#ifndef MAX_VARLOOKBEHIND+#define MAX_VARLOOKBEHIND 255+#endif+ /* Defining NEVER_BACKSLASH_C locks out the use of \C in all patterns. */ /* #undef NEVER_BACKSLASH_C */ @@ -236,7 +245,7 @@ #define PACKAGE_NAME "PCRE2" /* Define to the full name and version of this package. */-#define PACKAGE_STRING "PCRE2 10.40"+#define PACKAGE_STRING "PCRE2 10.44" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "pcre2"@@ -245,7 +254,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */-#define PACKAGE_VERSION "10.40"+#define PACKAGE_VERSION "10.44" /* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested parentheses (of any kind) in a pattern. This limits the amount of system@@ -275,12 +284,16 @@ /* Define to any value to include debugging code. */ /* #undef PCRE2_DEBUG */ +/* to make a symbol visible */+#define PCRE2_EXPORT+ /* If you are compiling for a system other than a Unix-like system or Win32, and it needs some magic to be inserted before the definition of a function that is exported by the library, define this macro to contain the relevant magic. If you do not define this macro, a suitable- __declspec value is used for Windows systems; in other environments- "extern" is used for a C compiler and "extern C" for a C++ compiler.+ __declspec value is used for Windows systems; in other environments+ a compiler relevant "extern" is used with any "visibility" related+ attributes from PCRE2_EXPORT included. This macro apears at the start of every exported function that is part of the external API. It does not appear on functions that are "external" in the C sense, but which are internal to the library. */@@ -298,11 +311,14 @@ unless SUPPORT_JIT is also defined. */ /* #undef SLJIT_PROT_EXECUTABLE_ALLOCATOR */ -/* Define to 1 if all of the C90 standard headers exist (not just the ones+/* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ /* #undef STDC_HEADERS */ +/* Define to any value to enable differential fuzzing support. */+/* #undef SUPPORT_DIFF_FUZZ */+ /* Define to any value to enable support for Just-In-Time compiling. */ /* #undef SUPPORT_JIT */ @@ -350,7 +366,7 @@ /* Define to any value for valgrind support to find invalid memory reads. */ /* #undef SUPPORT_VALGRIND */ -/* Enable extensions on AIX 3, Interix. */+/* Enable extensions on AIX, Interix, z/OS. */ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif@@ -411,11 +427,15 @@ #ifndef __STDC_WANT_IEC_60559_DFP_EXT__ # define __STDC_WANT_IEC_60559_DFP_EXT__ 1 #endif+/* Enable extensions specified by C23 Annex F. */+#ifndef __STDC_WANT_IEC_60559_EXT__+# define __STDC_WANT_IEC_60559_EXT__ 1+#endif /* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ #ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ # define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1 #endif-/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */+/* Enable extensions specified by C23 Annex H and ISO/IEC TS 18661-3:2015. */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ # define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 #endif@@ -438,14 +458,26 @@ #endif /* Version number of package */-#define VERSION "10.40"+#define VERSION "10.44" -/* Define to empty if `const' does not conform to ANSI C. */+/* Number of bits in a file offset, on hosts where this is settable. */+/* #undef _FILE_OFFSET_BITS */++/* Define to 1 on platforms where this makes off_t a 64-bit type. */+/* #undef _LARGE_FILES */++/* Number of bits in time_t, on hosts where this is settable. */+/* #undef _TIME_BITS */++/* Define to 1 on platforms where this makes time_t a 64-bit type. */+/* #undef __MINGW_USE_VC2005_COMPAT */++/* Define to empty if 'const' does not conform to ANSI C. */ /* #undef const */ /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ /* #undef int64_t */ -/* Define to `unsigned int' if <sys/types.h> does not define. */+/* Define as 'unsigned int' if <stddef.h> doesn't define. */ /* #undef size_t */
src/c/pcre2.h view
@@ -5,7 +5,7 @@ /* This is the public header file for the PCRE library, second API, to be #included by applications that call PCRE2 functions. - Copyright (c) 2016-2021 University of Cambridge+ Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -42,9 +42,9 @@ /* The current PCRE version information. */ #define PCRE2_MAJOR 10-#define PCRE2_MINOR 40+#define PCRE2_MINOR 44 #define PCRE2_PRERELEASE -#define PCRE2_DATE 2022-04-14+#define PCRE2_DATE 2024-06-07 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE2, the appropriate@@ -153,6 +153,12 @@ #define PCRE2_EXTRA_ESCAPED_CR_IS_LF 0x00000010u /* C */ #define PCRE2_EXTRA_ALT_BSUX 0x00000020u /* C */ #define PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK 0x00000040u /* C */+#define PCRE2_EXTRA_CASELESS_RESTRICT 0x00000080u /* C */+#define PCRE2_EXTRA_ASCII_BSD 0x00000100u /* C */+#define PCRE2_EXTRA_ASCII_BSS 0x00000200u /* C */+#define PCRE2_EXTRA_ASCII_BSW 0x00000400u /* C */+#define PCRE2_EXTRA_ASCII_POSIX 0x00000800u /* C */+#define PCRE2_EXTRA_ASCII_DIGIT 0x00001000u /* C */ /* These are for pcre2_jit_compile(). */ @@ -180,11 +186,12 @@ #define PCRE2_SUBSTITUTE_UNSET_EMPTY 0x00000400u /* pcre2_substitute() only */ #define PCRE2_SUBSTITUTE_UNKNOWN_UNSET 0x00000800u /* pcre2_substitute() only */ #define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u /* pcre2_substitute() only */-#define PCRE2_NO_JIT 0x00002000u /* Not for pcre2_dfa_match() */+#define PCRE2_NO_JIT 0x00002000u /* not for pcre2_dfa_match() */ #define PCRE2_COPY_MATCHED_SUBJECT 0x00004000u #define PCRE2_SUBSTITUTE_LITERAL 0x00008000u /* pcre2_substitute() only */ #define PCRE2_SUBSTITUTE_MATCHED 0x00010000u /* pcre2_substitute() only */ #define PCRE2_SUBSTITUTE_REPLACEMENT_ONLY 0x00020000u /* pcre2_substitute() only */+#define PCRE2_DISABLE_RECURSELOOP_CHECK 0x00040000u /* not for pcre2_dfa_match() or pcre2_jit_match() */ /* Options for pcre2_pattern_convert(). */ @@ -399,6 +406,7 @@ #define PCRE2_ERROR_CONVERT_SYNTAX (-64) #define PCRE2_ERROR_INTERNAL_DUPMATCH (-65) #define PCRE2_ERROR_DFA_UINVALID_UTF (-66)+#define PCRE2_ERROR_INVALIDOFFSET (-67) /* Request types for pcre2_pattern_info() */@@ -572,19 +580,19 @@ /* Functions for manipulating contexts. */ #define PCRE2_GENERAL_CONTEXT_FUNCTIONS \-PCRE2_EXP_DECL pcre2_general_context PCRE2_CALL_CONVENTION \- *pcre2_general_context_copy(pcre2_general_context *); \-PCRE2_EXP_DECL pcre2_general_context PCRE2_CALL_CONVENTION \- *pcre2_general_context_create(void *(*)(PCRE2_SIZE, void *), \+PCRE2_EXP_DECL pcre2_general_context *PCRE2_CALL_CONVENTION \+ pcre2_general_context_copy(pcre2_general_context *); \+PCRE2_EXP_DECL pcre2_general_context *PCRE2_CALL_CONVENTION \+ pcre2_general_context_create(void *(*)(size_t, void *), \ void (*)(void *, void *), void *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_general_context_free(pcre2_general_context *); #define PCRE2_COMPILE_CONTEXT_FUNCTIONS \-PCRE2_EXP_DECL pcre2_compile_context PCRE2_CALL_CONVENTION \- *pcre2_compile_context_copy(pcre2_compile_context *); \-PCRE2_EXP_DECL pcre2_compile_context PCRE2_CALL_CONVENTION \- *pcre2_compile_context_create(pcre2_general_context *);\+PCRE2_EXP_DECL pcre2_compile_context *PCRE2_CALL_CONVENTION \+ pcre2_compile_context_copy(pcre2_compile_context *); \+PCRE2_EXP_DECL pcre2_compile_context *PCRE2_CALL_CONVENTION \+ pcre2_compile_context_create(pcre2_general_context *);\ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_compile_context_free(pcre2_compile_context *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \@@ -596,6 +604,10 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_max_pattern_length(pcre2_compile_context *, PCRE2_SIZE); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_max_pattern_compiled_length(pcre2_compile_context *, PCRE2_SIZE); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_max_varlookbehind(pcre2_compile_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_newline(pcre2_compile_context *, uint32_t); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_parens_nest_limit(pcre2_compile_context *, uint32_t); \@@ -604,10 +616,10 @@ int (*)(uint32_t, void *), void *); #define PCRE2_MATCH_CONTEXT_FUNCTIONS \-PCRE2_EXP_DECL pcre2_match_context PCRE2_CALL_CONVENTION \- *pcre2_match_context_copy(pcre2_match_context *); \-PCRE2_EXP_DECL pcre2_match_context PCRE2_CALL_CONVENTION \- *pcre2_match_context_create(pcre2_general_context *); \+PCRE2_EXP_DECL pcre2_match_context *PCRE2_CALL_CONVENTION \+ pcre2_match_context_copy(pcre2_match_context *); \+PCRE2_EXP_DECL pcre2_match_context *PCRE2_CALL_CONVENTION \+ pcre2_match_context_create(pcre2_general_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_match_context_free(pcre2_match_context *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \@@ -628,13 +640,13 @@ pcre2_set_recursion_limit(pcre2_match_context *, uint32_t); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_recursion_memory_management(pcre2_match_context *, \- void *(*)(PCRE2_SIZE, void *), void (*)(void *, void *), void *);+ void *(*)(size_t, void *), void (*)(void *, void *), void *); #define PCRE2_CONVERT_CONTEXT_FUNCTIONS \-PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \- *pcre2_convert_context_copy(pcre2_convert_context *); \-PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \- *pcre2_convert_context_create(pcre2_general_context *); \+PCRE2_EXP_DECL pcre2_convert_context *PCRE2_CALL_CONVENTION \+ pcre2_convert_context_copy(pcre2_convert_context *); \+PCRE2_EXP_DECL pcre2_convert_context *PCRE2_CALL_CONVENTION \+ pcre2_convert_context_create(pcre2_general_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_convert_context_free(pcre2_convert_context *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \@@ -646,15 +658,15 @@ /* Functions concerned with compiling a pattern to PCRE internal code. */ #define PCRE2_COMPILE_FUNCTIONS \-PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \- *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, \+PCRE2_EXP_DECL pcre2_code *PCRE2_CALL_CONVENTION \+ pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, \ pcre2_compile_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_code_free(pcre2_code *); \-PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \- *pcre2_code_copy(const pcre2_code *); \-PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \- *pcre2_code_copy_with_tables(const pcre2_code *);+PCRE2_EXP_DECL pcre2_code *PCRE2_CALL_CONVENTION \+ pcre2_code_copy(const pcre2_code *); \+PCRE2_EXP_DECL pcre2_code *PCRE2_CALL_CONVENTION \+ pcre2_code_copy_with_tables(const pcre2_code *); /* Functions that give information about a compiled pattern. */@@ -670,10 +682,10 @@ /* Functions for running a match and inspecting the result. */ #define PCRE2_MATCH_FUNCTIONS \-PCRE2_EXP_DECL pcre2_match_data PCRE2_CALL_CONVENTION \- *pcre2_match_data_create(uint32_t, pcre2_general_context *); \-PCRE2_EXP_DECL pcre2_match_data PCRE2_CALL_CONVENTION \- *pcre2_match_data_create_from_pattern(const pcre2_code *, \+PCRE2_EXP_DECL pcre2_match_data *PCRE2_CALL_CONVENTION \+ pcre2_match_data_create(uint32_t, pcre2_general_context *); \+PCRE2_EXP_DECL pcre2_match_data *PCRE2_CALL_CONVENTION \+ pcre2_match_data_create_from_pattern(const pcre2_code *, \ pcre2_general_context *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_dfa_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \@@ -687,10 +699,12 @@ pcre2_get_mark(pcre2_match_data *); \ PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \ pcre2_get_match_data_size(pcre2_match_data *); \+PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \+ pcre2_get_match_data_heapframes_size(pcre2_match_data *); \ PCRE2_EXP_DECL uint32_t PCRE2_CALL_CONVENTION \ pcre2_get_ovector_count(pcre2_match_data *); \-PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \- *pcre2_get_ovector_pointer(pcre2_match_data *); \+PCRE2_EXP_DECL PCRE2_SIZE *PCRE2_CALL_CONVENTION \+ pcre2_get_ovector_pointer(pcre2_match_data *); \ PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \ pcre2_get_startchar(pcre2_match_data *); @@ -722,7 +736,7 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_substring_number_from_name(const pcre2_code *, PCRE2_SPTR); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \- pcre2_substring_list_free(PCRE2_SPTR *); \+ pcre2_substring_list_free(PCRE2_UCHAR **); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_substring_list_get(pcre2_match_data *, PCRE2_UCHAR ***, PCRE2_SIZE **); @@ -770,8 +784,8 @@ uint32_t, pcre2_match_data *, pcre2_match_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_jit_free_unused_memory(pcre2_general_context *); \-PCRE2_EXP_DECL pcre2_jit_stack PCRE2_CALL_CONVENTION \- *pcre2_jit_stack_create(PCRE2_SIZE, PCRE2_SIZE, pcre2_general_context *); \+PCRE2_EXP_DECL pcre2_jit_stack *PCRE2_CALL_CONVENTION \+ pcre2_jit_stack_create(size_t, size_t, pcre2_general_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_jit_stack_assign(pcre2_match_context *, pcre2_jit_callback, void *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \@@ -783,8 +797,8 @@ #define PCRE2_OTHER_FUNCTIONS \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_get_error_message(int, PCRE2_UCHAR *, PCRE2_SIZE); \-PCRE2_EXP_DECL const uint8_t PCRE2_CALL_CONVENTION \- *pcre2_maketables(pcre2_general_context *); \+PCRE2_EXP_DECL const uint8_t *PCRE2_CALL_CONVENTION \+ pcre2_maketables(pcre2_general_context *); \ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ pcre2_maketables_free(pcre2_general_context *, const uint8_t *); @@ -851,6 +865,7 @@ #define pcre2_general_context_free PCRE2_SUFFIX(pcre2_general_context_free_) #define pcre2_get_error_message PCRE2_SUFFIX(pcre2_get_error_message_) #define pcre2_get_mark PCRE2_SUFFIX(pcre2_get_mark_)+#define pcre2_get_match_data_heapframes_size PCRE2_SUFFIX(pcre2_get_match_data_heapframes_size_) #define pcre2_get_match_data_size PCRE2_SUFFIX(pcre2_get_match_data_size_) #define pcre2_get_ovector_pointer PCRE2_SUFFIX(pcre2_get_ovector_pointer_) #define pcre2_get_ovector_count PCRE2_SUFFIX(pcre2_get_ovector_count_)@@ -886,7 +901,9 @@ #define pcre2_set_glob_separator PCRE2_SUFFIX(pcre2_set_glob_separator_) #define pcre2_set_heap_limit PCRE2_SUFFIX(pcre2_set_heap_limit_) #define pcre2_set_match_limit PCRE2_SUFFIX(pcre2_set_match_limit_)+#define pcre2_set_max_varlookbehind PCRE2_SUFFIX(pcre2_set_max_varlookbehind_) #define pcre2_set_max_pattern_length PCRE2_SUFFIX(pcre2_set_max_pattern_length_)+#define pcre2_set_max_pattern_compiled_length PCRE2_SUFFIX(pcre2_set_max_pattern_compiled_length_) #define pcre2_set_newline PCRE2_SUFFIX(pcre2_set_newline_) #define pcre2_set_parens_nest_limit PCRE2_SUFFIX(pcre2_set_parens_nest_limit_) #define pcre2_set_offset_limit PCRE2_SUFFIX(pcre2_set_offset_limit_)
src/c/pcre2/maint/ucptest.c view
@@ -2,12 +2,13 @@ * A program for testing the Unicode property table * ***************************************************/ -/* Copyright (c) University of Cambridge 2008-2022 */+/* Copyright (c) University of Cambridge 2008-2023 */ /* Compile thus: - gcc -DHAVE_CONFIG_H -DPCRE2_CODE_UNIT_WIDTH=8 -o ucptest \- ucptest.c ../src/pcre2_ucd.c ../src/pcre2_tables.c+ gcc -DHAVE_CONFIG_H -DPCRE2_CODE_UNIT_WIDTH=8 \+ -fvisibility=hidden -o ucptest ucptest.c \+ ../src/pcre2_ord2utf.c ../src/pcre2_ucd.c ../src/pcre2_tables.c Add -lreadline or -ledit if PCRE2 was configured with readline or libedit support in pcre2test.@@ -75,7 +76,7 @@ and negative requirements. All must be satisfied. Sequences of two or more characters are shown as ranges, for example-U+0041..U+004A. No more than 100 lines are are output. If there are more+U+0041..U+004A. No more than 100 lines are output. If there are more characters, the list ends with ... The command "list" must be followed by one of property names script, bool,@@ -87,7 +88,7 @@ #endif #ifndef SUPPORT_UNICODE-#define SUPPORT_UNICODE+#error "Unicode support not enabled" #endif #include <ctype.h>@@ -125,7 +126,6 @@ #define CSS (char **) #define US (unsigned char *) #define CUS (const unsigned char *)-#define USS (unsigned char **) /* -------------------------------------------------------------------*/ @@ -183,108 +183,33 @@ }; static const unsigned char *bd_names[] = {- US"AL", US"Arabic letter",- US"AN", US"Arabid number",- US"B", US"Paragraph separator",- US"BN", US"Boundary neutral",- US"CS", US"Common separator",- US"EN", US"European number",- US"ES", US"European separator",- US"ET", US"European terminator",- US"FSI", US"First string isolate",- US"L", US"Left-to-right",- US"LRE", US"Left-to-right embedding",- US"LRI", US"Left-to-right isolate",- US"LRO", US"Left-to-right override",- US"NSM", US"Non-spacing mark",- US"ON", US"Other neutral",- US"PDF", US"Pop directional format",- US"PDI", US"Pop directional isolate",- US"R", US"Right-to-left",- US"RLE", US"Right-to-left embedding",- US"RLI", US"Right-to-left isolate",- US"RLO", US"Right-to-left override",- US"S", US"Segment separator",- US"WS", US"White space"+ US"AL", US"ArabicLetter",+ US"AN", US"ArabicNumber",+ US"B", US"ParagraphSeparator",+ US"BN", US"BoundaryNeutral",+ US"CS", US"CommonSeparator",+ US"EN", US"EuropeanNumber",+ US"ES", US"EuropeanSeparator",+ US"ET", US"EuropeanTerminator",+ US"FSI", US"FirstStrongIsolate",+ US"L", US"LeftToRight",+ US"LRE", US"LeftToRightEmbedding",+ US"LRI", US"LeftToRightIsolate",+ US"LRO", US"LeftToRightOverride",+ US"NSM", US"NonspacingMark",+ US"ON", US"OtherNeutral",+ US"PDF", US"PopDirectionalFormat",+ US"PDI", US"PopDirectionalIsolate",+ US"R", US"RightToLeft",+ US"RLE", US"RightToLeftEmbedding",+ US"RLI", US"RightToLeftIsolate",+ US"RLO", US"RightToLeftOverride",+ US"S", US"SegmentSeparator",+ US"WS", US"WhiteSpace" }; -static const unsigned int utf8_table1[] = {- 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff}; -static const int utf8_table2[] = {- 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};--/* Macro to pick up the remaining bytes of a UTF-8 character, advancing-the pointer. */--#define GETUTF8INC(c, eptr) \- { \- if ((c & 0x20u) == 0) \- c = ((c & 0x1fu) << 6) | (*eptr++ & 0x3fu); \- else if ((c & 0x10u) == 0) \- { \- c = ((c & 0x0fu) << 12) | ((*eptr & 0x3fu) << 6) | (eptr[1] & 0x3fu); \- eptr += 2; \- } \- else if ((c & 0x08u) == 0) \- { \- c = ((c & 0x07u) << 18) | ((*eptr & 0x3fu) << 12) | \- ((eptr[1] & 0x3fu) << 6) | (eptr[2] & 0x3fu); \- eptr += 3; \- } \- else if ((c & 0x04u) == 0) \- { \- c = ((c & 0x03u) << 24) | ((*eptr & 0x3fu) << 18) | \- ((eptr[1] & 0x3fu) << 12) | ((eptr[2] & 0x3fu) << 6) | \- (eptr[3] & 0x3fu); \- eptr += 4; \- } \- else \- { \- c = ((c & 0x01u) << 30) | ((*eptr & 0x3fu) << 24) | \- ((eptr[1] & 0x3fu) << 18) | ((eptr[2] & 0x3fu) << 12) | \- ((eptr[3] & 0x3fu) << 6) | (eptr[4] & 0x3fu); \- eptr += 5; \- } \- }--- /*************************************************-* Convert character value to UTF-8 *-*************************************************/--/* This function takes an unsigned long integer value in the range 0 --0x7fffffff and encodes it as a UTF-8 character in 1 to 6 bytes.--Arguments:- cvalue the character value- buffer pointer to buffer for result - at least 6 bytes long--Returns: number of bytes placed in the buffer- 0 if input code point is too big-*/--static size_t-ord2utf8(unsigned int cvalue, unsigned char *buffer)-{-size_t i, j;-for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)- if (cvalue <= utf8_table1[i]) break;-if (i >= sizeof(utf8_table1)/sizeof(int)) return 0;-buffer += i;-for (j = i; j > 0; j--)- {- *buffer-- = 0x80 | (cvalue & 0x3f);- cvalue >>= 6;- }-*buffer = utf8_table2[i] | cvalue;-return i + 1;-}----/************************************************* * Test for interaction * *************************************************/ @@ -357,7 +282,7 @@ static void print_prop(unsigned int c, BOOL is_just_one) {-int type = UCD_CATEGORY(c);+unsigned int type = UCD_CATEGORY(c); int fulltype = UCD_CHARTYPE(c); int script = UCD_SCRIPT(c); int scriptx = UCD_SCRIPTX(c);@@ -471,9 +396,9 @@ printf("U+%04X %s %s: %s, %s, %s", c, bidiclass, typename, fulltypename, scriptname, graphbreak); -if (is_just_one && othercase != c)+if (is_just_one && (othercase != c || caseset != 0)) {- printf(", U+%04X", othercase);+ if (othercase != c) printf(", U+%04X", othercase); if (caseset != 0) { const uint32_t *p = PRIV(ucd_caseless_sets) + caseset - 1;@@ -502,8 +427,7 @@ if (bprops != 0) { const char *sep = "";- const uint32_t *p = PRIV(ucd_boolprop_sets) + - bprops * ucd_boolprop_sets_item_size;+ const uint32_t *p = PRIV(ucd_boolprop_sets) + bprops; printf(", ["); for (int i = 0; i < ucp_Bprop_Count; i++) if (MAPBIT(p, i) != 0)@@ -517,8 +441,8 @@ if (show_character && is_just_one) { unsigned char buffer[8];- size_t len = ord2utf8(c, buffer);- printf(", >%.*s<", (int)len, buffer);+ int len = (int)PRIV(ord2utf_8)(c, buffer);+ printf(", >%.*s<", len, buffer); } printf("\n");@@ -546,7 +470,6 @@ int type = -1; int gbreak = -1; int bidiclass = -1;-BOOL bidicontrol = FALSE; BOOL script_not = FALSE; BOOL type_not = FALSE; BOOL gbreak_not = FALSE;@@ -558,13 +481,10 @@ while (*s != 0) { unsigned int offset = 0;- BOOL scriptx_not = FALSE;- char *value_start; for (t = name; *s != 0 && !isspace(*s); s++) *t++ = *s; *t = 0; while (isspace(*s)) s++;- value_start = s; for (t = value; *s != 0 && !isspace(*s); s++) {@@ -576,12 +496,13 @@ if (strcmp(CS name, "script") == 0 || strcmp(CS name, "scriptx") == 0) {+ BOOL x = (name[6] == 'x');+ BOOL scriptx_not = FALSE; for (t = value; *t != 0; t++) *t = tolower(*t); if (value[0] == '!') {- if (name[6] == 'x') scriptx_not = TRUE;- else script_not = TRUE;+ if (x) scriptx_not = TRUE; else script_not = TRUE; offset = 1; } @@ -592,8 +513,22 @@ PRIV(utt_names) + u->name_offset) == 0) { c = u->value;- if (name[6] == 'x')+ if (x && !scriptx_not && u->type == PT_SC) {+ if (script < 0)+ {+ x = FALSE;+ script = -1;+ script_not = scriptx_not;+ }+ else if (!script_not)+ {+ printf("No characters found\n");+ return;+ }+ }+ if (x)+ { scriptx_list[scriptx_count++] = scriptx_not? (-c):c; } else@@ -659,7 +594,7 @@ for (i = 0; i < sizeof(type_names)/sizeof(char *); i += 2) {- if (strcmp(CS (value + offset), CS type_names[i]) == 0)+ if (strcmp(CS (value + offset), CCS type_names[i]) == 0) { type = i/2; break;@@ -690,7 +625,7 @@ for (i = 0; i < sizeof(gb_names)/sizeof(char *); i += 2) {- if (strcmp(CS (value + offset), CS gb_names[i]) == 0)+ if (strcmp(CS (value + offset), CCS gb_names[i]) == 0) { gbreak = i/2; break;@@ -720,9 +655,9 @@ bidiclass_not = TRUE; offset = 1; }- for (i = 0; i < sizeof(bd_names)/sizeof(char *); i += 2)+ for (i = 0; i < sizeof(bd_names)/sizeof(char *); i++) {- if (strcasecmp(CS (value + offset), CS bd_names[i]) == 0)+ if (strcasecmp(CS (value + offset), CCS bd_names[i]) == 0) { bidiclass = i/2; break;@@ -767,12 +702,15 @@ /* Positive requirment */ if (scriptx_list[i] >= 0) {- if ((bits_scriptx[x] & (1u<<y)) != 0) found++;+ if (scriptx_list[i] == UCD_SCRIPT(c) ||+ ((scriptx_list[i] < ucp_Unknown) &&+ (bits_scriptx[x] & (1u<<y)) != 0)) found++; } /* Negative requirement */ else {- if ((bits_scriptx[x] & (1u<<y)) == 0) found++;+ if ((-(scriptx_list[i]) < ucp_Unknown) &&+ (bits_scriptx[x] & (1u<<y)) == 0) found++; } } @@ -781,8 +719,7 @@ if (bprop_count > 0) {- const uint32_t *bits_bprop = PRIV(ucd_boolprop_sets) + - UCD_BPROPS(c) * ucd_boolprop_sets_item_size;+ const uint32_t *bits_bprop = PRIV(ucd_boolprop_sets) + UCD_BPROPS(c); unsigned int found = 0; for (i = 0; i < bprop_count; i++)@@ -906,13 +843,14 @@ if (c > 0x7fu) { GETCHARINC(c, t);+ endptr = t; }- endptr = t+1;+ else endptr = t+1; } else {- if (strncmp(CS t, "U+", 2) == 0) t += 2;- c = strtoul(CS t, CSS(&endptr), 16);+ if (memcmp(t, "U+", 2) == 0) t += 2;+ c = (uint32_t)strtoul(CS t, CSS(&endptr), 16); } if (*endptr != 0 && !isspace(*endptr))@@ -1021,7 +959,7 @@ char *arg = argv[first_arg]; unsigned char *s = buffer; - if (*arg != '+' && strncmp(arg, "U+", 2) != 0 && !isdigit(*arg))+ if (*arg != '+' && memcmp(arg, "U+", 2) != 0 && !isdigit(*arg)) { while (*arg != 0) {
src/c/pcre2/src/pcre2_auto_possess.c view
@@ -560,6 +560,8 @@ for(;;) {+ PCRE2_SPTR bracode;+ /* All operations move the code pointer forward. Therefore infinite recursions are not possible. */ @@ -617,7 +619,8 @@ recursions. (This could be improved by keeping a list of group numbers that are called by recursion.) */ - switch(*(code - GET(code, 1)))+ bracode = code - GET(code, 1);+ switch(*bracode) { case OP_CBRA: case OP_SCBRA:@@ -636,15 +639,18 @@ break; /* Atomic sub-patterns and assertions can always auto-possessify their- last iterator. However, if the group was entered as a result of checking- a previous iterator, this is not possible. */+ last iterator except for variable length lookbehinds. However, if the+ group was entered as a result of checking a previous iterator, this is+ not possible. */ case OP_ASSERT: case OP_ASSERT_NOT:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT: case OP_ONCE: return !entered_a_group;++ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ return (bracode[1+LINK_SIZE] == OP_VREVERSE)? FALSE : !entered_a_group; /* Non-atomic assertions - don't possessify last iterator. This needs more thought. */
+ src/c/pcre2/src/pcre2_chkdint.c view
@@ -0,0 +1,96 @@+/*************************************************+* Perl-Compatible Regular Expressions *+*************************************************/++/* PCRE is a library of functions to support regular expressions whose syntax+and semantics are as close as possible to those of the Perl 5 language.++ Written by Philip Hazel+ Copyright (c) 2023 University of Cambridge++-----------------------------------------------------------------------------+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright notice,+ this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++ * Neither the name of the University of Cambridge nor the names of its+ contributors may be used to endorse or promote products derived from+ this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.+-----------------------------------------------------------------------------+*/++/* This file contains functions to implement checked integer operation */++#ifndef PCRE2_PCRE2TEST+#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include "pcre2_internal.h"+#endif++/*************************************************+* Checked Integer Multiplication *+*************************************************/++/*+Arguments:+ r A pointer to PCRE2_SIZE to store the answer+ a, b Two integers++Returns: Bool indicating if the operation overflows++It is modeled after C23's <stdckdint.h> interface+The INT64_OR_DOUBLE type is a 64-bit integer type when available,+otherwise double. */++BOOL+PRIV(ckd_smul)(PCRE2_SIZE *r, int a, int b)+{+#ifdef HAVE_BUILTIN_MUL_OVERFLOW+PCRE2_SIZE m;++if (__builtin_mul_overflow(a, b, &m)) return TRUE;++*r = m;+#else+INT64_OR_DOUBLE m;++#ifdef PCRE2_DEBUG+if (a < 0 || b < 0) abort();+#endif++m = (INT64_OR_DOUBLE)a * (INT64_OR_DOUBLE)b;++#if defined INT64_MAX || defined int64_t+if (sizeof(m) > sizeof(*r) && m > (INT64_OR_DOUBLE)PCRE2_SIZE_MAX) return TRUE;+*r = (PCRE2_SIZE)m;+#else+if (m > PCRE2_SIZE_MAX) return TRUE;+*r = m;+#endif++#endif++return FALSE;+}++/* End of pcre_chkdint.c */
src/c/pcre2/src/pcre2_compile.c view
@@ -7,10617 +7,10995 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2022 University of Cambridge--------------------------------------------------------------------------------Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:-- * Redistributions of source code must retain the above copyright notice,- this list of conditions and the following disclaimer.-- * Redistributions in binary form must reproduce the above copyright- notice, this list of conditions and the following disclaimer in the- documentation and/or other materials provided with the distribution.-- * Neither the name of the University of Cambridge nor the names of its- contributors may be used to endorse or promote products derived from- this software without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE-POSSIBILITY OF SUCH DAMAGE.-------------------------------------------------------------------------------*/---#ifdef HAVE_CONFIG_H-#include "config.h"-#endif--#define NLBLOCK cb /* Block containing newline information */-#define PSSTART start_pattern /* Field containing processed string start */-#define PSEND end_pattern /* Field containing processed string end */--#include "pcre2_internal.h"--/* In rare error cases debugging might require calling pcre2_printint(). */--#if 0-#ifdef EBCDIC-#define PRINTABLE(c) ((c) >= 64 && (c) < 255)-#else-#define PRINTABLE(c) ((c) >= 32 && (c) < 127)-#endif-#include "pcre2_printint.c"-#define DEBUG_CALL_PRINTINT-#endif--/* Other debugging code can be enabled by these defines. */--/* #define DEBUG_SHOW_CAPTURES */-/* #define DEBUG_SHOW_PARSED */--/* There are a few things that vary with different code unit sizes. Handle them-by defining macros in order to minimize #if usage. */--#if PCRE2_CODE_UNIT_WIDTH == 8-#define STRING_UTFn_RIGHTPAR STRING_UTF8_RIGHTPAR, 5-#define XDIGIT(c) xdigitab[c]--#else /* Either 16-bit or 32-bit */-#define XDIGIT(c) (MAX_255(c)? xdigitab[c] : 0xff)--#if PCRE2_CODE_UNIT_WIDTH == 16-#define STRING_UTFn_RIGHTPAR STRING_UTF16_RIGHTPAR, 6--#else /* 32-bit */-#define STRING_UTFn_RIGHTPAR STRING_UTF32_RIGHTPAR, 6-#endif-#endif--/* Macros to store and retrieve a PCRE2_SIZE value in the parsed pattern, which-consists of uint32_t elements. Assume that if uint32_t can't hold it, two of-them will be able to (i.e. assume a 64-bit world). */--#if PCRE2_SIZE_MAX <= UINT32_MAX-#define PUTOFFSET(s,p) *p++ = s-#define GETOFFSET(s,p) s = *p++-#define GETPLUSOFFSET(s,p) s = *(++p)-#define READPLUSOFFSET(s,p) s = p[1]-#define SKIPOFFSET(p) p++-#define SIZEOFFSET 1-#else-#define PUTOFFSET(s,p) \- { *p++ = (uint32_t)(s >> 32); *p++ = (uint32_t)(s & 0xffffffff); }-#define GETOFFSET(s,p) \- { s = ((PCRE2_SIZE)p[0] << 32) | (PCRE2_SIZE)p[1]; p += 2; }-#define GETPLUSOFFSET(s,p) \- { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; p += 2; }-#define READPLUSOFFSET(s,p) \- { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; }-#define SKIPOFFSET(p) p += 2-#define SIZEOFFSET 2-#endif--/* Macros for manipulating elements of the parsed pattern vector. */--#define META_CODE(x) (x & 0xffff0000u)-#define META_DATA(x) (x & 0x0000ffffu)-#define META_DIFF(x,y) ((x-y)>>16)--/* Function definitions to allow mutual recursion */--#ifdef SUPPORT_UNICODE-static unsigned int- add_list_to_class_internal(uint8_t *, PCRE2_UCHAR **, uint32_t,- compile_block *, const uint32_t *, unsigned int);-#endif--static int- compile_regex(uint32_t, PCRE2_UCHAR **, uint32_t **, int *, uint32_t,- uint32_t *, uint32_t *, uint32_t *, uint32_t *, branch_chain *,- compile_block *, PCRE2_SIZE *);--static int- get_branchlength(uint32_t **, int *, int *, parsed_recurse_check *,- compile_block *);--static BOOL- set_lookbehind_lengths(uint32_t **, int *, int *, parsed_recurse_check *,- compile_block *);--static int- check_lookbehinds(uint32_t *, uint32_t **, parsed_recurse_check *,- compile_block *, int *);---/*************************************************-* Code parameters and static tables *-*************************************************/--#define MAX_GROUP_NUMBER 65535u-#define MAX_REPEAT_COUNT 65535u-#define REPEAT_UNLIMITED (MAX_REPEAT_COUNT+1)--/* COMPILE_WORK_SIZE specifies the size of stack workspace, which is used in-different ways in the different pattern scans. The parsing and group--identifying pre-scan uses it to handle nesting, and needs it to be 16-bit-aligned for this. Having defined the size in code units, we set up-C16_WORK_SIZE as the number of elements in the 16-bit vector.--During the first compiling phase, when determining how much memory is required,-the regex is partly compiled into this space, but the compiled parts are-discarded as soon as they can be, so that hopefully there will never be an-overrun. The code does, however, check for an overrun, which can occur for-pathological patterns. The size of the workspace depends on LINK_SIZE because-the length of compiled items varies with this.--In the real compile phase, this workspace is not currently used. */--#define COMPILE_WORK_SIZE (3000*LINK_SIZE) /* Size in code units */--#define C16_WORK_SIZE \- ((COMPILE_WORK_SIZE * sizeof(PCRE2_UCHAR))/sizeof(uint16_t))--/* A uint32_t vector is used for caching information about the size of-capturing groups, to improve performance. A default is created on the stack of-this size. */--#define GROUPINFO_DEFAULT_SIZE 256--/* The overrun tests check for a slightly smaller size so that they detect the-overrun before it actually does run off the end of the data block. */--#define WORK_SIZE_SAFETY_MARGIN (100)--/* This value determines the size of the initial vector that is used for-remembering named groups during the pre-compile. It is allocated on the stack,-but if it is too small, it is expanded, in a similar way to the workspace. The-value is the number of slots in the list. */--#define NAMED_GROUP_LIST_SIZE 20--/* The pre-compiling pass over the pattern creates a parsed pattern in a vector-of uint32_t. For short patterns this lives on the stack, with this size. Heap-memory is used for longer patterns. */--#define PARSED_PATTERN_DEFAULT_SIZE 1024--/* Maximum length value to check against when making sure that the variable-that holds the compiled pattern length does not overflow. We make it a bit less-than INT_MAX to allow for adding in group terminating code units, so that we-don't have to check them every time. */--#define OFLOW_MAX (INT_MAX - 20)--/* Code values for parsed patterns, which are stored in a vector of 32-bit-unsigned ints. Values less than META_END are literal data values. The coding-for identifying the item is in the top 16-bits, leaving 16 bits for the-additional data that some of them need. The META_CODE, META_DATA, and META_DIFF-macros are used to manipulate parsed pattern elements.--NOTE: When these definitions are changed, the table of extra lengths for each-code (meta_extra_lengths, just below) must be updated to remain in step. */--#define META_END 0x80000000u /* End of pattern */--#define META_ALT 0x80010000u /* alternation */-#define META_ATOMIC 0x80020000u /* atomic group */-#define META_BACKREF 0x80030000u /* Back ref */-#define META_BACKREF_BYNAME 0x80040000u /* \k'name' */-#define META_BIGVALUE 0x80050000u /* Next is a literal > META_END */-#define META_CALLOUT_NUMBER 0x80060000u /* (?C with numerical argument */-#define META_CALLOUT_STRING 0x80070000u /* (?C with string argument */-#define META_CAPTURE 0x80080000u /* Capturing parenthesis */-#define META_CIRCUMFLEX 0x80090000u /* ^ metacharacter */-#define META_CLASS 0x800a0000u /* start non-empty class */-#define META_CLASS_EMPTY 0x800b0000u /* empty class */-#define META_CLASS_EMPTY_NOT 0x800c0000u /* negative empty class */-#define META_CLASS_END 0x800d0000u /* end of non-empty class */-#define META_CLASS_NOT 0x800e0000u /* start non-empty negative class */-#define META_COND_ASSERT 0x800f0000u /* (?(?assertion)... */-#define META_COND_DEFINE 0x80100000u /* (?(DEFINE)... */-#define META_COND_NAME 0x80110000u /* (?(<name>)... */-#define META_COND_NUMBER 0x80120000u /* (?(digits)... */-#define META_COND_RNAME 0x80130000u /* (?(R&name)... */-#define META_COND_RNUMBER 0x80140000u /* (?(Rdigits)... */-#define META_COND_VERSION 0x80150000u /* (?(VERSION<op>x.y)... */-#define META_DOLLAR 0x80160000u /* $ metacharacter */-#define META_DOT 0x80170000u /* . metacharacter */-#define META_ESCAPE 0x80180000u /* \d and friends */-#define META_KET 0x80190000u /* closing parenthesis */-#define META_NOCAPTURE 0x801a0000u /* no capture parens */-#define META_OPTIONS 0x801b0000u /* (?i) and friends */-#define META_POSIX 0x801c0000u /* POSIX class item */-#define META_POSIX_NEG 0x801d0000u /* negative POSIX class item */-#define META_RANGE_ESCAPED 0x801e0000u /* range with at least one escape */-#define META_RANGE_LITERAL 0x801f0000u /* range defined literally */-#define META_RECURSE 0x80200000u /* Recursion */-#define META_RECURSE_BYNAME 0x80210000u /* (?&name) */-#define META_SCRIPT_RUN 0x80220000u /* (*script_run:...) */--/* These must be kept together to make it easy to check that an assertion-is present where expected in a conditional group. */--#define META_LOOKAHEAD 0x80230000u /* (?= */-#define META_LOOKAHEADNOT 0x80240000u /* (?! */-#define META_LOOKBEHIND 0x80250000u /* (?<= */-#define META_LOOKBEHINDNOT 0x80260000u /* (?<! */--/* These cannot be conditions */--#define META_LOOKAHEAD_NA 0x80270000u /* (*napla: */-#define META_LOOKBEHIND_NA 0x80280000u /* (*naplb: */--/* These must be kept in this order, with consecutive values, and the _ARG-versions of COMMIT, PRUNE, SKIP, and THEN immediately after their non-argument-versions. */--#define META_MARK 0x80290000u /* (*MARK) */-#define META_ACCEPT 0x802a0000u /* (*ACCEPT) */-#define META_FAIL 0x802b0000u /* (*FAIL) */-#define META_COMMIT 0x802c0000u /* These */-#define META_COMMIT_ARG 0x802d0000u /* pairs */-#define META_PRUNE 0x802e0000u /* must */-#define META_PRUNE_ARG 0x802f0000u /* be */-#define META_SKIP 0x80300000u /* kept */-#define META_SKIP_ARG 0x80310000u /* in */-#define META_THEN 0x80320000u /* this */-#define META_THEN_ARG 0x80330000u /* order */--/* These must be kept in groups of adjacent 3 values, and all together. */--#define META_ASTERISK 0x80340000u /* * */-#define META_ASTERISK_PLUS 0x80350000u /* *+ */-#define META_ASTERISK_QUERY 0x80360000u /* *? */-#define META_PLUS 0x80370000u /* + */-#define META_PLUS_PLUS 0x80380000u /* ++ */-#define META_PLUS_QUERY 0x80390000u /* +? */-#define META_QUERY 0x803a0000u /* ? */-#define META_QUERY_PLUS 0x803b0000u /* ?+ */-#define META_QUERY_QUERY 0x803c0000u /* ?? */-#define META_MINMAX 0x803d0000u /* {n,m} repeat */-#define META_MINMAX_PLUS 0x803e0000u /* {n,m}+ repeat */-#define META_MINMAX_QUERY 0x803f0000u /* {n,m}? repeat */--#define META_FIRST_QUANTIFIER META_ASTERISK-#define META_LAST_QUANTIFIER META_MINMAX_QUERY--/* This is a special "meta code" that is used only to distinguish (*asr: from-(*sr: in the table of aphabetic assertions. It is never stored in the parsed-pattern because (*asr: is turned into (*sr:(*atomic: at that stage. There is-therefore no need for it to have a length entry, so use a high value. */--#define META_ATOMIC_SCRIPT_RUN 0x8fff0000u--/* Table of extra lengths for each of the meta codes. Must be kept in step with-the definitions above. For some items these values are a basic length to which-a variable amount has to be added. */--static unsigned char meta_extra_lengths[] = {- 0, /* META_END */- 0, /* META_ALT */- 0, /* META_ATOMIC */- 0, /* META_BACKREF - more if group is >= 10 */- 1+SIZEOFFSET, /* META_BACKREF_BYNAME */- 1, /* META_BIGVALUE */- 3, /* META_CALLOUT_NUMBER */- 3+SIZEOFFSET, /* META_CALLOUT_STRING */- 0, /* META_CAPTURE */- 0, /* META_CIRCUMFLEX */- 0, /* META_CLASS */- 0, /* META_CLASS_EMPTY */- 0, /* META_CLASS_EMPTY_NOT */- 0, /* META_CLASS_END */- 0, /* META_CLASS_NOT */- 0, /* META_COND_ASSERT */- SIZEOFFSET, /* META_COND_DEFINE */- 1+SIZEOFFSET, /* META_COND_NAME */- 1+SIZEOFFSET, /* META_COND_NUMBER */- 1+SIZEOFFSET, /* META_COND_RNAME */- 1+SIZEOFFSET, /* META_COND_RNUMBER */- 3, /* META_COND_VERSION */- 0, /* META_DOLLAR */- 0, /* META_DOT */- 0, /* META_ESCAPE - more for ESC_P, ESC_p, ESC_g, ESC_k */- 0, /* META_KET */- 0, /* META_NOCAPTURE */- 1, /* META_OPTIONS */- 1, /* META_POSIX */- 1, /* META_POSIX_NEG */- 0, /* META_RANGE_ESCAPED */- 0, /* META_RANGE_LITERAL */- SIZEOFFSET, /* META_RECURSE */- 1+SIZEOFFSET, /* META_RECURSE_BYNAME */- 0, /* META_SCRIPT_RUN */- 0, /* META_LOOKAHEAD */- 0, /* META_LOOKAHEADNOT */- SIZEOFFSET, /* META_LOOKBEHIND */- SIZEOFFSET, /* META_LOOKBEHINDNOT */- 0, /* META_LOOKAHEAD_NA */- SIZEOFFSET, /* META_LOOKBEHIND_NA */- 1, /* META_MARK - plus the string length */- 0, /* META_ACCEPT */- 0, /* META_FAIL */- 0, /* META_COMMIT */- 1, /* META_COMMIT_ARG - plus the string length */- 0, /* META_PRUNE */- 1, /* META_PRUNE_ARG - plus the string length */- 0, /* META_SKIP */- 1, /* META_SKIP_ARG - plus the string length */- 0, /* META_THEN */- 1, /* META_THEN_ARG - plus the string length */- 0, /* META_ASTERISK */- 0, /* META_ASTERISK_PLUS */- 0, /* META_ASTERISK_QUERY */- 0, /* META_PLUS */- 0, /* META_PLUS_PLUS */- 0, /* META_PLUS_QUERY */- 0, /* META_QUERY */- 0, /* META_QUERY_PLUS */- 0, /* META_QUERY_QUERY */- 2, /* META_MINMAX */- 2, /* META_MINMAX_PLUS */- 2 /* META_MINMAX_QUERY */-};--/* Types for skipping parts of a parsed pattern. */--enum { PSKIP_ALT, PSKIP_CLASS, PSKIP_KET };--/* Macro for setting individual bits in class bitmaps. It took some-experimenting to figure out how to stop gcc 5.3.0 from warning with--Wconversion. This version gets a warning:-- #define SETBIT(a,b) a[(b)/8] |= (uint8_t)(1u << ((b)&7))--Let's hope the apparently less efficient version isn't actually so bad if the-compiler is clever with identical subexpressions. */--#define SETBIT(a,b) a[(b)/8] = (uint8_t)(a[(b)/8] | (1u << ((b)&7)))--/* Values and flags for the unsigned xxcuflags variables that accompany xxcu-variables, which are concerned with first and required code units. A value-greater than or equal to REQ_NONE means "no code unit set"; otherwise the-matching xxcu variable is set, and the low valued bits are relevant. */--#define REQ_UNSET 0xffffffffu /* Not yet found anything */-#define REQ_NONE 0xfffffffeu /* Found not fixed character */-#define REQ_CASELESS 0x00000001u /* Code unit in xxcu is caseless */-#define REQ_VARY 0x00000002u /* Code unit is followed by non-literal */--/* These flags are used in the groupinfo vector. */--#define GI_SET_FIXED_LENGTH 0x80000000u-#define GI_NOT_FIXED_LENGTH 0x40000000u-#define GI_FIXED_LENGTH_MASK 0x0000ffffu--/* This simple test for a decimal digit works for both ASCII/Unicode and EBCDIC-and is fast (a good compiler can turn it into a subtraction and unsigned-comparison). */--#define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9)--/* Table to identify hex digits. The tables in chartables are dependent on the-locale, and may mark arbitrary characters as digits. We want to recognize only-0-9, a-z, and A-Z as hex digits, which is why we have a private table here. It-costs 256 bytes, but it is a lot faster than doing character value tests (at-least in some simple cases I timed), and in some applications one wants PCRE2-to compile efficiently as well as match efficiently. The value in the table is-the binary hex digit value, or 0xff for non-hex digits. */--/* This is the "normal" case, for ASCII systems, and EBCDIC systems running in-UTF-8 mode. */--#ifndef EBCDIC-static const uint8_t xdigitab[] =- {- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0- 7 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 8- 15 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 16- 23 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 24- 31 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - ' */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* ( - / */- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0 - 7 */- 0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff, /* 8 - ? */- 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* @ - G */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* H - O */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* P - W */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* X - _ */- 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* ` - g */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* h - o */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* p - w */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* x -127 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 128-135 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 136-143 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 144-151 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 152-159 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 160-167 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 168-175 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 176-183 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 184-191 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 192-199 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 2ff-207 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 208-215 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 216-223 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 224-231 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 232-239 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 240-247 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};/* 248-255 */--#else--/* This is the "abnormal" case, for EBCDIC systems not running in UTF-8 mode. */--static const uint8_t xdigitab[] =- {- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0- 7 0 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 8- 15 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 16- 23 10 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 24- 31 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 32- 39 20 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 40- 47 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 48- 55 30 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 56- 63 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - 71 40 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 72- | */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* & - 87 50 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 88- 95 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - -103 60 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 104- ? */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 112-119 70 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 120- " */- 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* 128- g 80 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* h -143 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 144- p 90 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* q -159 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 160- x A0 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* y -175 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* ^ -183 B0 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 184-191 */- 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* { - G C0 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* H -207 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* } - P D0 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* Q -223 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* \ - X E0 */- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* Y -239 */- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0 - 7 F0 */- 0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff};/* 8 -255 */-#endif /* EBCDIC */---/* Table for handling alphanumeric escaped characters. Positive returns are-simple data values; negative values are for special things like \d and so on.-Zero means further processing is needed (for things like \x), or the escape is-invalid. */--/* This is the "normal" table for ASCII systems or for EBCDIC systems running-in UTF-8 mode. It runs from '0' to 'z'. */--#ifndef EBCDIC-#define ESCAPES_FIRST CHAR_0-#define ESCAPES_LAST CHAR_z-#define UPPER_CASE(c) (c-32)--static const short int escapes[] = {- 0, 0,- 0, 0,- 0, 0,- 0, 0,- 0, 0,- CHAR_COLON, CHAR_SEMICOLON,- CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN,- CHAR_GREATER_THAN_SIGN, CHAR_QUESTION_MARK,- CHAR_COMMERCIAL_AT, -ESC_A,- -ESC_B, -ESC_C,- -ESC_D, -ESC_E,- 0, -ESC_G,- -ESC_H, 0,- 0, -ESC_K,- 0, 0,- -ESC_N, 0,- -ESC_P, -ESC_Q,- -ESC_R, -ESC_S,- 0, 0,- -ESC_V, -ESC_W,- -ESC_X, 0,- -ESC_Z, CHAR_LEFT_SQUARE_BRACKET,- CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET,- CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE,- CHAR_GRAVE_ACCENT, CHAR_BEL,- -ESC_b, 0,- -ESC_d, CHAR_ESC,- CHAR_FF, 0,- -ESC_h, 0,- 0, -ESC_k,- 0, 0,- CHAR_LF, 0,- -ESC_p, 0,- CHAR_CR, -ESC_s,- CHAR_HT, 0,- -ESC_v, -ESC_w,- 0, 0,- -ESC_z-};--#else--/* This is the "abnormal" table for EBCDIC systems without UTF-8 support.-It runs from 'a' to '9'. For some minimal testing of EBCDIC features, the code-is sometimes compiled on an ASCII system. In this case, we must not use CHAR_a-because it is defined as 'a', which of course picks up the ASCII value. */--#if 'a' == 0x81 /* Check for a real EBCDIC environment */-#define ESCAPES_FIRST CHAR_a-#define ESCAPES_LAST CHAR_9-#define UPPER_CASE(c) (c+64)-#else /* Testing in an ASCII environment */-#define ESCAPES_FIRST ((unsigned char)'\x81') /* EBCDIC 'a' */-#define ESCAPES_LAST ((unsigned char)'\xf9') /* EBCDIC '9' */-#define UPPER_CASE(c) (c-32)-#endif--static const short int escapes[] = {-/* 80 */ CHAR_BEL, -ESC_b, 0, -ESC_d, CHAR_ESC, CHAR_FF, 0,-/* 88 */ -ESC_h, 0, 0, '{', 0, 0, 0, 0,-/* 90 */ 0, 0, -ESC_k, 0, 0, CHAR_LF, 0, -ESC_p,-/* 98 */ 0, CHAR_CR, 0, '}', 0, 0, 0, 0,-/* A0 */ 0, '~', -ESC_s, CHAR_HT, 0, -ESC_v, -ESC_w, 0,-/* A8 */ 0, -ESC_z, 0, 0, 0, '[', 0, 0,-/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0,-/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-',-/* C0 */ '{', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G,-/* C8 */ -ESC_H, 0, 0, 0, 0, 0, 0, 0,-/* D0 */ '}', 0, -ESC_K, 0, 0, -ESC_N, 0, -ESC_P,-/* D8 */ -ESC_Q, -ESC_R, 0, 0, 0, 0, 0, 0,-/* E0 */ '\\', 0, -ESC_S, 0, 0, -ESC_V, -ESC_W, -ESC_X,-/* E8 */ 0, -ESC_Z, 0, 0, 0, 0, 0, 0,-/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,-/* F8 */ 0, 0-};--/* We also need a table of characters that may follow \c in an EBCDIC-environment for characters 0-31. */--static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";--#endif /* EBCDIC */---/* Table of special "verbs" like (*PRUNE). This is a short table, so it is-searched linearly. Put all the names into a single string, in order to reduce-the number of relocations when a shared library is dynamically linked. The-string is built from string macros so that it works in UTF-8 mode on EBCDIC-platforms. */--typedef struct verbitem {- unsigned int len; /* Length of verb name */- uint32_t meta; /* Base META_ code */- int has_arg; /* Argument requirement */-} verbitem;--static const char verbnames[] =- "\0" /* Empty name is a shorthand for MARK */- STRING_MARK0- STRING_ACCEPT0- STRING_F0- STRING_FAIL0- STRING_COMMIT0- STRING_PRUNE0- STRING_SKIP0- STRING_THEN;--static const verbitem verbs[] = {- { 0, META_MARK, +1 }, /* > 0 => must have an argument */- { 4, META_MARK, +1 },- { 6, META_ACCEPT, -1 }, /* < 0 => Optional argument, convert to pre-MARK */- { 1, META_FAIL, -1 },- { 4, META_FAIL, -1 },- { 6, META_COMMIT, 0 },- { 5, META_PRUNE, 0 }, /* Optional argument; bump META code if found */- { 4, META_SKIP, 0 },- { 4, META_THEN, 0 }-};--static const int verbcount = sizeof(verbs)/sizeof(verbitem);--/* Verb opcodes, indexed by their META code offset from META_MARK. */--static const uint32_t verbops[] = {- OP_MARK, OP_ACCEPT, OP_FAIL, OP_COMMIT, OP_COMMIT_ARG, OP_PRUNE,- OP_PRUNE_ARG, OP_SKIP, OP_SKIP_ARG, OP_THEN, OP_THEN_ARG };--/* Table of "alpha assertions" like (*pla:...), similar to the (*VERB) table. */--typedef struct alasitem {- unsigned int len; /* Length of name */- uint32_t meta; /* Base META_ code */-} alasitem;--static const char alasnames[] =- STRING_pla0- STRING_plb0- STRING_napla0- STRING_naplb0- STRING_nla0- STRING_nlb0- STRING_positive_lookahead0- STRING_positive_lookbehind0- STRING_non_atomic_positive_lookahead0- STRING_non_atomic_positive_lookbehind0- STRING_negative_lookahead0- STRING_negative_lookbehind0- STRING_atomic0- STRING_sr0- STRING_asr0- STRING_script_run0- STRING_atomic_script_run;--static const alasitem alasmeta[] = {- { 3, META_LOOKAHEAD },- { 3, META_LOOKBEHIND },- { 5, META_LOOKAHEAD_NA },- { 5, META_LOOKBEHIND_NA },- { 3, META_LOOKAHEADNOT },- { 3, META_LOOKBEHINDNOT },- { 18, META_LOOKAHEAD },- { 19, META_LOOKBEHIND },- { 29, META_LOOKAHEAD_NA },- { 30, META_LOOKBEHIND_NA },- { 18, META_LOOKAHEADNOT },- { 19, META_LOOKBEHINDNOT },- { 6, META_ATOMIC },- { 2, META_SCRIPT_RUN }, /* sr = script run */- { 3, META_ATOMIC_SCRIPT_RUN }, /* asr = atomic script run */- { 10, META_SCRIPT_RUN }, /* script run */- { 17, META_ATOMIC_SCRIPT_RUN } /* atomic script run */-};--static const int alascount = sizeof(alasmeta)/sizeof(alasitem);--/* Offsets from OP_STAR for case-independent and negative repeat opcodes. */--static uint32_t chartypeoffset[] = {- OP_STAR - OP_STAR, OP_STARI - OP_STAR,- OP_NOTSTAR - OP_STAR, OP_NOTSTARI - OP_STAR };--/* Tables of names of POSIX character classes and their lengths. The names are-now all in a single string, to reduce the number of relocations when a shared-library is dynamically loaded. The list of lengths is terminated by a zero-length entry. The first three must be alpha, lower, upper, as this is assumed-for handling case independence. The indices for graph, print, and punct are-needed, so identify them. */--static const char posix_names[] =- STRING_alpha0 STRING_lower0 STRING_upper0 STRING_alnum0- STRING_ascii0 STRING_blank0 STRING_cntrl0 STRING_digit0- STRING_graph0 STRING_print0 STRING_punct0 STRING_space0- STRING_word0 STRING_xdigit;--static const uint8_t posix_name_lengths[] = {- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };--#define PC_GRAPH 8-#define PC_PRINT 9-#define PC_PUNCT 10--/* Table of class bit maps for each POSIX class. Each class is formed from a-base map, with an optional addition or removal of another map. Then, for some-classes, there is some additional tweaking: for [:blank:] the vertical space-characters are removed, and for [:alpha:] and [:alnum:] the underscore-character is removed. The triples in the table consist of the base map offset,-second map offset or -1 if no second map, and a non-negative value for map-addition or a negative value for map subtraction (if there are two maps). The-absolute value of the third field has these meanings: 0 => no tweaking, 1 =>-remove vertical space characters, 2 => remove underscore. */--static const int posix_class_maps[] = {- cbit_word, cbit_digit, -2, /* alpha */- cbit_lower, -1, 0, /* lower */- cbit_upper, -1, 0, /* upper */- cbit_word, -1, 2, /* alnum - word without underscore */- cbit_print, cbit_cntrl, 0, /* ascii */- cbit_space, -1, 1, /* blank - a GNU extension */- cbit_cntrl, -1, 0, /* cntrl */- cbit_digit, -1, 0, /* digit */- cbit_graph, -1, 0, /* graph */- cbit_print, -1, 0, /* print */- cbit_punct, -1, 0, /* punct */- cbit_space, -1, 0, /* space */- cbit_word, -1, 0, /* word - a Perl extension */- cbit_xdigit,-1, 0 /* xdigit */-};--#ifdef SUPPORT_UNICODE--/* The POSIX class Unicode property substitutes that are used in UCP mode must-be in the order of the POSIX class names, defined above. */--static int posix_substitutes[] = {- PT_GC, ucp_L, /* alpha */- PT_PC, ucp_Ll, /* lower */- PT_PC, ucp_Lu, /* upper */- PT_ALNUM, 0, /* alnum */- -1, 0, /* ascii, treat as non-UCP */- -1, 1, /* blank, treat as \h */- PT_PC, ucp_Cc, /* cntrl */- PT_PC, ucp_Nd, /* digit */- PT_PXGRAPH, 0, /* graph */- PT_PXPRINT, 0, /* print */- PT_PXPUNCT, 0, /* punct */- PT_PXSPACE, 0, /* space */ /* Xps is POSIX space, but from 8.34 */- PT_WORD, 0, /* word */ /* Perl and POSIX space are the same */- -1, 0 /* xdigit, treat as non-UCP */-};-#define POSIX_SUBSIZE (sizeof(posix_substitutes) / (2*sizeof(uint32_t)))-#endif /* SUPPORT_UNICODE */--/* Masks for checking option settings. When PCRE2_LITERAL is set, only a subset-are allowed. */--#define PUBLIC_LITERAL_COMPILE_OPTIONS \- (PCRE2_ANCHORED|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_ENDANCHORED| \- PCRE2_FIRSTLINE|PCRE2_LITERAL|PCRE2_MATCH_INVALID_UTF| \- PCRE2_NO_START_OPTIMIZE|PCRE2_NO_UTF_CHECK|PCRE2_USE_OFFSET_LIMIT|PCRE2_UTF)--#define PUBLIC_COMPILE_OPTIONS \- (PUBLIC_LITERAL_COMPILE_OPTIONS| \- PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \- PCRE2_ALT_VERBNAMES|PCRE2_DOLLAR_ENDONLY|PCRE2_DOTALL|PCRE2_DUPNAMES| \- PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_MATCH_UNSET_BACKREF| \- PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C|PCRE2_NEVER_UCP| \- PCRE2_NEVER_UTF|PCRE2_NO_AUTO_CAPTURE|PCRE2_NO_AUTO_POSSESS| \- PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_UCP|PCRE2_UNGREEDY)--#define PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS \- (PCRE2_EXTRA_MATCH_LINE|PCRE2_EXTRA_MATCH_WORD)--#define PUBLIC_COMPILE_EXTRA_OPTIONS \- (PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS| \- PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES|PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL| \- PCRE2_EXTRA_ESCAPED_CR_IS_LF|PCRE2_EXTRA_ALT_BSUX| \- PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK)--/* Compile time error code numbers. They are given names so that they can more-easily be tracked. When a new number is added, the tables called eint1 and-eint2 in pcre2posix.c may need to be updated, and a new error text must be-added to compile_error_texts in pcre2_error.c. Also, the error codes in-pcre2.h.in must be updated - their values are exactly 100 greater than these-values. */--enum { ERR0 = COMPILE_ERROR_BASE,- ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10,- ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20,- ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30,- ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40,- ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, 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, ERR87, ERR88, ERR89, ERR90,- ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98, ERR99 };--/* This is a table of start-of-pattern options such as (*UTF) and settings such-as (*LIMIT_MATCH=nnnn) and (*CRLF). For completeness and backward-compatibility, (*UTFn) is supported in the relevant libraries, but (*UTF) is-generic and always supported. */--enum { PSO_OPT, /* Value is an option bit */- PSO_FLG, /* Value is a flag bit */- PSO_NL, /* Value is a newline type */- PSO_BSR, /* Value is a \R type */- PSO_LIMH, /* Read integer value for heap limit */- PSO_LIMM, /* Read integer value for match limit */- PSO_LIMD }; /* Read integer value for depth limit */--typedef struct pso {- const uint8_t *name;- uint16_t length;- uint16_t type;- uint32_t value;-} pso;--/* NB: STRING_UTFn_RIGHTPAR contains the length as well */--static pso pso_list[] = {- { (uint8_t *)STRING_UTFn_RIGHTPAR, PSO_OPT, PCRE2_UTF },- { (uint8_t *)STRING_UTF_RIGHTPAR, 4, PSO_OPT, PCRE2_UTF },- { (uint8_t *)STRING_UCP_RIGHTPAR, 4, PSO_OPT, PCRE2_UCP },- { (uint8_t *)STRING_NOTEMPTY_RIGHTPAR, 9, PSO_FLG, PCRE2_NOTEMPTY_SET },- { (uint8_t *)STRING_NOTEMPTY_ATSTART_RIGHTPAR, 17, PSO_FLG, PCRE2_NE_ATST_SET },- { (uint8_t *)STRING_NO_AUTO_POSSESS_RIGHTPAR, 16, PSO_OPT, PCRE2_NO_AUTO_POSSESS },- { (uint8_t *)STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR, 18, PSO_OPT, PCRE2_NO_DOTSTAR_ANCHOR },- { (uint8_t *)STRING_NO_JIT_RIGHTPAR, 7, PSO_FLG, PCRE2_NOJIT },- { (uint8_t *)STRING_NO_START_OPT_RIGHTPAR, 13, PSO_OPT, PCRE2_NO_START_OPTIMIZE },- { (uint8_t *)STRING_LIMIT_HEAP_EQ, 11, PSO_LIMH, 0 },- { (uint8_t *)STRING_LIMIT_MATCH_EQ, 12, PSO_LIMM, 0 },- { (uint8_t *)STRING_LIMIT_DEPTH_EQ, 12, PSO_LIMD, 0 },- { (uint8_t *)STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMD, 0 },- { (uint8_t *)STRING_CR_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_CR },- { (uint8_t *)STRING_LF_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_LF },- { (uint8_t *)STRING_CRLF_RIGHTPAR, 5, PSO_NL, PCRE2_NEWLINE_CRLF },- { (uint8_t *)STRING_ANY_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_ANY },- { (uint8_t *)STRING_NUL_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_NUL },- { (uint8_t *)STRING_ANYCRLF_RIGHTPAR, 8, PSO_NL, PCRE2_NEWLINE_ANYCRLF },- { (uint8_t *)STRING_BSR_ANYCRLF_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_ANYCRLF },- { (uint8_t *)STRING_BSR_UNICODE_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_UNICODE }-};--/* This table is used when converting repeating opcodes into possessified-versions as a result of an explicit possessive quantifier such as ++. A zero-value means there is no possessified version - in those cases the item in-question must be wrapped in ONCE brackets. The table is truncated at OP_CALLOUT-because all relevant opcodes are less than that. */--static const uint8_t opcode_possessify[] = {- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 15 */- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 31 */-- 0, /* NOTI */- OP_POSSTAR, 0, /* STAR, MINSTAR */- OP_POSPLUS, 0, /* PLUS, MINPLUS */- OP_POSQUERY, 0, /* QUERY, MINQUERY */- OP_POSUPTO, 0, /* UPTO, MINUPTO */- 0, /* EXACT */- 0, 0, 0, 0, /* POS{STAR,PLUS,QUERY,UPTO} */-- OP_POSSTARI, 0, /* STARI, MINSTARI */- OP_POSPLUSI, 0, /* PLUSI, MINPLUSI */- OP_POSQUERYI, 0, /* QUERYI, MINQUERYI */- OP_POSUPTOI, 0, /* UPTOI, MINUPTOI */- 0, /* EXACTI */- 0, 0, 0, 0, /* POS{STARI,PLUSI,QUERYI,UPTOI} */-- OP_NOTPOSSTAR, 0, /* NOTSTAR, NOTMINSTAR */- OP_NOTPOSPLUS, 0, /* NOTPLUS, NOTMINPLUS */- OP_NOTPOSQUERY, 0, /* NOTQUERY, NOTMINQUERY */- OP_NOTPOSUPTO, 0, /* NOTUPTO, NOTMINUPTO */- 0, /* NOTEXACT */- 0, 0, 0, 0, /* NOTPOS{STAR,PLUS,QUERY,UPTO} */-- OP_NOTPOSSTARI, 0, /* NOTSTARI, NOTMINSTARI */- OP_NOTPOSPLUSI, 0, /* NOTPLUSI, NOTMINPLUSI */- OP_NOTPOSQUERYI, 0, /* NOTQUERYI, NOTMINQUERYI */- OP_NOTPOSUPTOI, 0, /* NOTUPTOI, NOTMINUPTOI */- 0, /* NOTEXACTI */- 0, 0, 0, 0, /* NOTPOS{STARI,PLUSI,QUERYI,UPTOI} */-- OP_TYPEPOSSTAR, 0, /* TYPESTAR, TYPEMINSTAR */- OP_TYPEPOSPLUS, 0, /* TYPEPLUS, TYPEMINPLUS */- OP_TYPEPOSQUERY, 0, /* TYPEQUERY, TYPEMINQUERY */- OP_TYPEPOSUPTO, 0, /* TYPEUPTO, TYPEMINUPTO */- 0, /* TYPEEXACT */- 0, 0, 0, 0, /* TYPEPOS{STAR,PLUS,QUERY,UPTO} */-- OP_CRPOSSTAR, 0, /* CRSTAR, CRMINSTAR */- OP_CRPOSPLUS, 0, /* CRPLUS, CRMINPLUS */- OP_CRPOSQUERY, 0, /* CRQUERY, CRMINQUERY */- OP_CRPOSRANGE, 0, /* CRRANGE, CRMINRANGE */- 0, 0, 0, 0, /* CRPOS{STAR,PLUS,QUERY,RANGE} */-- 0, 0, 0, /* CLASS, NCLASS, XCLASS */- 0, 0, /* REF, REFI */- 0, 0, /* DNREF, DNREFI */- 0, 0 /* RECURSE, CALLOUT */-};---#ifdef DEBUG_SHOW_PARSED-/*************************************************-* Show the parsed pattern for debugging *-*************************************************/--/* For debugging the pre-scan, this code, which outputs the parsed data vector,-can be enabled. */--static void show_parsed(compile_block *cb)-{-uint32_t *pptr = cb->parsed_pattern;--for (;;)- {- int max, min;- PCRE2_SIZE offset;- uint32_t i;- uint32_t length;- uint32_t meta_arg = META_DATA(*pptr);-- fprintf(stderr, "+++ %02d %.8x ", (int)(pptr - cb->parsed_pattern), *pptr);-- if (*pptr < META_END)- {- if (*pptr > 32 && *pptr < 128) fprintf(stderr, "%c", *pptr);- pptr++;- }-- else switch (META_CODE(*pptr++))- {- default:- fprintf(stderr, "**** OOPS - unknown META value - giving up ****\n");- return;-- case META_END:- fprintf(stderr, "META_END\n");- return;-- case META_CAPTURE:- fprintf(stderr, "META_CAPTURE %d", meta_arg);- break;-- case META_RECURSE:- GETOFFSET(offset, pptr);- fprintf(stderr, "META_RECURSE %d %zd", meta_arg, offset);- break;-- case META_BACKREF:- if (meta_arg < 10)- offset = cb->small_ref_offset[meta_arg];- else- GETOFFSET(offset, pptr);- fprintf(stderr, "META_BACKREF %d %zd", meta_arg, offset);- break;-- case META_ESCAPE:- if (meta_arg == ESC_P || meta_arg == ESC_p)- {- uint32_t ptype = *pptr >> 16;- uint32_t pvalue = *pptr++ & 0xffff;- fprintf(stderr, "META \\%c %d %d", (meta_arg == ESC_P)? 'P':'p',- ptype, pvalue);- }- else- {- uint32_t cc;- /* There's just one escape we might have here that isn't negated in the- escapes table. */- if (meta_arg == ESC_g) cc = CHAR_g;- else for (cc = ESCAPES_FIRST; cc <= ESCAPES_LAST; cc++)- {- if (meta_arg == (uint32_t)(-escapes[cc - ESCAPES_FIRST])) break;- }- if (cc > ESCAPES_LAST) cc = CHAR_QUESTION_MARK;- fprintf(stderr, "META \\%c", cc);- }- break;-- case META_MINMAX:- min = *pptr++;- max = *pptr++;- if (max != REPEAT_UNLIMITED)- fprintf(stderr, "META {%d,%d}", min, max);- else- fprintf(stderr, "META {%d,}", min);- break;-- case META_MINMAX_QUERY:- min = *pptr++;- max = *pptr++;- if (max != REPEAT_UNLIMITED)- fprintf(stderr, "META {%d,%d}?", min, max);- else- fprintf(stderr, "META {%d,}?", min);- break;-- case META_MINMAX_PLUS:- min = *pptr++;- max = *pptr++;- if (max != REPEAT_UNLIMITED)- fprintf(stderr, "META {%d,%d}+", min, max);- else- fprintf(stderr, "META {%d,}+", min);- break;-- case META_BIGVALUE: fprintf(stderr, "META_BIGVALUE %.8x", *pptr++); break;- case META_CIRCUMFLEX: fprintf(stderr, "META_CIRCUMFLEX"); break;- case META_COND_ASSERT: fprintf(stderr, "META_COND_ASSERT"); break;- case META_DOLLAR: fprintf(stderr, "META_DOLLAR"); break;- case META_DOT: fprintf(stderr, "META_DOT"); break;- case META_ASTERISK: fprintf(stderr, "META *"); break;- case META_ASTERISK_QUERY: fprintf(stderr, "META *?"); break;- case META_ASTERISK_PLUS: fprintf(stderr, "META *+"); break;- case META_PLUS: fprintf(stderr, "META +"); break;- case META_PLUS_QUERY: fprintf(stderr, "META +?"); break;- case META_PLUS_PLUS: fprintf(stderr, "META ++"); break;- case META_QUERY: fprintf(stderr, "META ?"); break;- case META_QUERY_QUERY: fprintf(stderr, "META ??"); break;- case META_QUERY_PLUS: fprintf(stderr, "META ?+"); break;-- case META_ATOMIC: fprintf(stderr, "META (?>"); break;- case META_NOCAPTURE: fprintf(stderr, "META (?:"); break;- case META_LOOKAHEAD: fprintf(stderr, "META (?="); break;- case META_LOOKAHEADNOT: fprintf(stderr, "META (?!"); break;- case META_LOOKAHEAD_NA: fprintf(stderr, "META (*napla:"); break;- case META_SCRIPT_RUN: fprintf(stderr, "META (*sr:"); break;- case META_KET: fprintf(stderr, "META )"); break;- case META_ALT: fprintf(stderr, "META | %d", meta_arg); break;-- case META_CLASS: fprintf(stderr, "META ["); break;- case META_CLASS_NOT: fprintf(stderr, "META [^"); break;- case META_CLASS_END: fprintf(stderr, "META ]"); break;- case META_CLASS_EMPTY: fprintf(stderr, "META []"); break;- case META_CLASS_EMPTY_NOT: fprintf(stderr, "META [^]"); break;-- case META_RANGE_LITERAL: fprintf(stderr, "META - (literal)"); break;- case META_RANGE_ESCAPED: fprintf(stderr, "META - (escaped)"); break;-- case META_POSIX: fprintf(stderr, "META_POSIX %d", *pptr++); break;- case META_POSIX_NEG: fprintf(stderr, "META_POSIX_NEG %d", *pptr++); break;-- case META_ACCEPT: fprintf(stderr, "META (*ACCEPT)"); break;- case META_FAIL: fprintf(stderr, "META (*FAIL)"); break;- case META_COMMIT: fprintf(stderr, "META (*COMMIT)"); break;- case META_PRUNE: fprintf(stderr, "META (*PRUNE)"); break;- case META_SKIP: fprintf(stderr, "META (*SKIP)"); break;- case META_THEN: fprintf(stderr, "META (*THEN)"); break;-- case META_OPTIONS: fprintf(stderr, "META_OPTIONS 0x%02x", *pptr++); break;-- case META_LOOKBEHIND:- fprintf(stderr, "META (?<= %d offset=", meta_arg);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- break;-- case META_LOOKBEHIND_NA:- fprintf(stderr, "META (*naplb: %d offset=", meta_arg);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- break;-- case META_LOOKBEHINDNOT:- fprintf(stderr, "META (?<! %d offset=", meta_arg);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- break;-- case META_CALLOUT_NUMBER:- fprintf(stderr, "META (?C%d) next=%d/%d", pptr[2], pptr[0],- pptr[1]);- pptr += 3;- break;-- case META_CALLOUT_STRING:- {- uint32_t patoffset = *pptr++; /* Offset of next pattern item */- uint32_t patlength = *pptr++; /* Length of next pattern item */- fprintf(stderr, "META (?Cstring) length=%d offset=", *pptr++);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd next=%d/%d", offset, patoffset, patlength);- }- break;-- case META_RECURSE_BYNAME:- fprintf(stderr, "META (?(&name) length=%d offset=", *pptr++);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- break;-- case META_BACKREF_BYNAME:- fprintf(stderr, "META_BACKREF_BYNAME length=%d offset=", *pptr++);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- break;-- case META_COND_NUMBER:- fprintf(stderr, "META_COND_NUMBER %d offset=", pptr[SIZEOFFSET]);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- pptr++;- break;-- case META_COND_DEFINE:- fprintf(stderr, "META (?(DEFINE) offset=");- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- break;-- case META_COND_VERSION:- fprintf(stderr, "META (?(VERSION%s", (*pptr++ == 0)? "=" : ">=");- fprintf(stderr, "%d.", *pptr++);- fprintf(stderr, "%d)", *pptr++);- break;-- case META_COND_NAME:- fprintf(stderr, "META (?(<name>) length=%d offset=", *pptr++);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- break;-- case META_COND_RNAME:- fprintf(stderr, "META (?(R&name) length=%d offset=", *pptr++);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- break;-- /* This is kept as a name, because it might be. */-- case META_COND_RNUMBER:- fprintf(stderr, "META (?(Rnumber) length=%d offset=", *pptr++);- GETOFFSET(offset, pptr);- fprintf(stderr, "%zd", offset);- break;-- case META_MARK:- fprintf(stderr, "META (*MARK:");- goto SHOWARG;-- case META_COMMIT_ARG:- fprintf(stderr, "META (*COMMIT:");- goto SHOWARG;-- case META_PRUNE_ARG:- fprintf(stderr, "META (*PRUNE:");- goto SHOWARG;-- case META_SKIP_ARG:- fprintf(stderr, "META (*SKIP:");- goto SHOWARG;-- case META_THEN_ARG:- fprintf(stderr, "META (*THEN:");- SHOWARG:- length = *pptr++;- for (i = 0; i < length; i++)- {- uint32_t cc = *pptr++;- if (cc > 32 && cc < 128) fprintf(stderr, "%c", cc);- else fprintf(stderr, "\\x{%x}", cc);- }- fprintf(stderr, ") length=%u", length);- break;- }- fprintf(stderr, "\n");- }-return;-}-#endif /* DEBUG_SHOW_PARSED */----/*************************************************-* Copy compiled code *-*************************************************/--/* Compiled JIT code cannot be copied, so the new compiled block has no-associated JIT data. */--PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION-pcre2_code_copy(const pcre2_code *code)-{-PCRE2_SIZE* ref_count;-pcre2_code *newcode;--if (code == NULL) return NULL;-newcode = code->memctl.malloc(code->blocksize, code->memctl.memory_data);-if (newcode == NULL) return NULL;-memcpy(newcode, code, code->blocksize);-newcode->executable_jit = NULL;--/* If the code is one that has been deserialized, increment the reference count-in the decoded tables. */--if ((code->flags & PCRE2_DEREF_TABLES) != 0)- {- ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH);- (*ref_count)++;- }--return newcode;-}----/*************************************************-* Copy compiled code and character tables *-*************************************************/--/* Compiled JIT code cannot be copied, so the new compiled block has no-associated JIT data. This version of code_copy also makes a separate copy of-the character tables. */--PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION-pcre2_code_copy_with_tables(const pcre2_code *code)-{-PCRE2_SIZE* ref_count;-pcre2_code *newcode;-uint8_t *newtables;--if (code == NULL) return NULL;-newcode = code->memctl.malloc(code->blocksize, code->memctl.memory_data);-if (newcode == NULL) return NULL;-memcpy(newcode, code, code->blocksize);-newcode->executable_jit = NULL;--newtables = code->memctl.malloc(TABLES_LENGTH + sizeof(PCRE2_SIZE),- code->memctl.memory_data);-if (newtables == NULL)- {- code->memctl.free((void *)newcode, code->memctl.memory_data);- return NULL;- }-memcpy(newtables, code->tables, TABLES_LENGTH);-ref_count = (PCRE2_SIZE *)(newtables + TABLES_LENGTH);-*ref_count = 1;--newcode->tables = newtables;-newcode->flags |= PCRE2_DEREF_TABLES;-return newcode;-}----/*************************************************-* Free compiled code *-*************************************************/--PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION-pcre2_code_free(pcre2_code *code)-{-PCRE2_SIZE* ref_count;--if (code != NULL)- {- if (code->executable_jit != NULL)- PRIV(jit_free)(code->executable_jit, &code->memctl);-- if ((code->flags & PCRE2_DEREF_TABLES) != 0)- {- /* Decoded tables belong to the codes after deserialization, and they must- be freed when there are no more references to them. The *ref_count should- always be > 0. */-- ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH);- if (*ref_count > 0)- {- (*ref_count)--;- if (*ref_count == 0)- code->memctl.free((void *)code->tables, code->memctl.memory_data);- }- }-- code->memctl.free(code, code->memctl.memory_data);- }-}----/*************************************************-* Read a number, possibly signed *-*************************************************/--/* This function is used to read numbers in the pattern. The initial pointer-must be the sign or first digit of the number. When relative values (introduced-by + or -) are allowed, they are relative group numbers, and the result must be-greater than zero.--Arguments:- ptrptr points to the character pointer variable- ptrend points to the end of the input string- allow_sign if < 0, sign not allowed; if >= 0, sign is relative to this- max_value the largest number allowed- max_error the error to give for an over-large number- intptr where to put the result- errcodeptr where to put an error code--Returns: TRUE - a number was read- FALSE - errorcode == 0 => no number was found- errorcode != 0 => an error occurred-*/--static BOOL-read_number(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, int32_t allow_sign,- uint32_t max_value, uint32_t max_error, int *intptr, int *errorcodeptr)-{-int sign = 0;-uint32_t n = 0;-PCRE2_SPTR ptr = *ptrptr;-BOOL yield = FALSE;--*errorcodeptr = 0;--if (allow_sign >= 0 && ptr < ptrend)- {- if (*ptr == CHAR_PLUS)- {- sign = +1;- max_value -= allow_sign;- ptr++;- }- else if (*ptr == CHAR_MINUS)- {- sign = -1;- ptr++;- }- }--if (ptr >= ptrend || !IS_DIGIT(*ptr)) return FALSE;-while (ptr < ptrend && IS_DIGIT(*ptr))- {- n = n * 10 + *ptr++ - CHAR_0;- if (n > max_value)- {- *errorcodeptr = max_error;- goto EXIT;- }- }--if (allow_sign >= 0 && sign != 0)- {- if (n == 0)- {- *errorcodeptr = ERR26; /* +0 and -0 are not allowed */- goto EXIT;- }-- if (sign > 0) n += allow_sign;- else if ((int)n > allow_sign)- {- *errorcodeptr = ERR15; /* Non-existent subpattern */- goto EXIT;- }- else n = allow_sign + 1 - n;- }--yield = TRUE;--EXIT:-*intptr = n;-*ptrptr = ptr;-return yield;-}----/*************************************************-* Read repeat counts *-*************************************************/--/* Read an item of the form {n,m} and return the values if non-NULL pointers-are supplied. Repeat counts must be less than 65536 (MAX_REPEAT_COUNT); a-larger value is used for "unlimited". We have to use signed arguments for-read_number() because it is capable of returning a signed value.--Arguments:- ptrptr points to pointer to character after'{'- ptrend pointer to end of input- minp if not NULL, pointer to int for min- maxp if not NULL, pointer to int for max (-1 if no max)- returned as -1 if no max- errorcodeptr points to error code variable--Returns: FALSE if not a repeat quantifier, errorcode set zero- FALSE on error, with errorcode set non-zero- TRUE on success, with pointer updated to point after '}'-*/--static BOOL-read_repeat_counts(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *minp,- uint32_t *maxp, int *errorcodeptr)-{-PCRE2_SPTR p;-BOOL yield = FALSE;-BOOL had_comma = FALSE;-int32_t min = 0;-int32_t max = REPEAT_UNLIMITED; /* This value is larger than MAX_REPEAT_COUNT */--/* Check the syntax */--*errorcodeptr = 0;-for (p = *ptrptr;; p++)- {- uint32_t c;- if (p >= ptrend) return FALSE;- c = *p;- if (IS_DIGIT(c)) continue;- if (c == CHAR_RIGHT_CURLY_BRACKET) break;- if (c == CHAR_COMMA)- {- if (had_comma) return FALSE;- had_comma = TRUE;- }- else return FALSE;- }--/* The only error from read_number() is for a number that is too big. */--p = *ptrptr;-if (!read_number(&p, ptrend, -1, MAX_REPEAT_COUNT, ERR5, &min, errorcodeptr))- goto EXIT;--if (*p == CHAR_RIGHT_CURLY_BRACKET)- {- p++;- max = min;- }-else- {- if (*(++p) != CHAR_RIGHT_CURLY_BRACKET)- {- if (!read_number(&p, ptrend, -1, MAX_REPEAT_COUNT, ERR5, &max,- errorcodeptr))- goto EXIT;- if (max < min)- {- *errorcodeptr = ERR4;- goto EXIT;- }- }- p++;- }--yield = TRUE;-if (minp != NULL) *minp = (uint32_t)min;-if (maxp != NULL) *maxp = (uint32_t)max;--/* Update the pattern pointer */--EXIT:-*ptrptr = p;-return yield;-}----/*************************************************-* Handle escapes *-*************************************************/--/* This function is called when a \ has been encountered. It either returns a-positive value for a simple escape such as \d, or 0 for a data character, which-is placed in chptr. A backreference to group n is returned as negative n. On-entry, ptr is pointing at the character after \. On exit, it points after the-final code unit of the escape sequence.--This function is also called from pcre2_substitute() to handle escape sequences-in replacement strings. In this case, the cb argument is NULL, and in the case-of escapes that have further processing, only sequences that define a data-character are recognised. The isclass argument is not relevant; the options-argument is the final value of the compiled pattern's options.--Arguments:- ptrptr points to the input position pointer- ptrend points to the end of the input- chptr points to a returned data character- errorcodeptr points to the errorcode variable (containing zero)- options the current options bits- isclass TRUE if inside a character class- cb compile data block or NULL when called from pcre2_substitute()--Returns: zero => a data character- positive => a special escape sequence- negative => a numerical back reference- on error, errorcodeptr is set non-zero-*/--int-PRIV(check_escape)(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *chptr,- int *errorcodeptr, uint32_t options, uint32_t extra_options, BOOL isclass,- compile_block *cb)-{-BOOL utf = (options & PCRE2_UTF) != 0;-PCRE2_SPTR ptr = *ptrptr;-uint32_t c, cc;-int escape = 0;-int i;--/* If backslash is at the end of the string, it's an error. */--if (ptr >= ptrend)- {- *errorcodeptr = ERR1;- return 0;- }--GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */-*errorcodeptr = 0; /* Be optimistic */--/* Non-alphanumerics are literals, so we just leave the value in c. An initial-value test saves a memory lookup for code points outside the alphanumeric-range. */--if (c < ESCAPES_FIRST || c > ESCAPES_LAST) {} /* Definitely literal */--/* Otherwise, do a table lookup. Non-zero values need little processing here. A-positive value is a literal value for something like \n. A negative value is-the negation of one of the ESC_ macros that is passed back for handling by the-calling function. Some extra checking is needed for \N because only \N{U+dddd}-is supported. If the value is zero, further processing is handled below. */--else if ((i = escapes[c - ESCAPES_FIRST]) != 0)- {- if (i > 0)- {- c = (uint32_t)i;- if (c == CHAR_CR && (extra_options & PCRE2_EXTRA_ESCAPED_CR_IS_LF) != 0)- c = CHAR_LF;- }- else /* Negative table entry */- {- escape = -i; /* Else return a special escape */- if (cb != NULL && (escape == ESC_P || escape == ESC_p || escape == ESC_X))- cb->external_flags |= PCRE2_HASBKPORX; /* Note \P, \p, or \X */-- /* Perl supports \N{name} for character names and \N{U+dddd} for numerical- Unicode code points, as well as plain \N for "not newline". PCRE does not- support \N{name}. However, it does support quantification such as \N{2,3},- so if \N{ is not followed by U+dddd we check for a quantifier. */-- if (escape == ESC_N && ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET)- {- PCRE2_SPTR p = ptr + 1;-- /* \N{U+ can be handled by the \x{ code. However, this construction is- not valid in EBCDIC environments because it specifies a Unicode- character, not a codepoint in the local code. For example \N{U+0041}- must be "A" in all environments. Also, in Perl, \N{U+ forces Unicode- casing semantics for the entire pattern, so allow it only in UTF (i.e.- Unicode) mode. */-- if (ptrend - p > 1 && *p == CHAR_U && p[1] == CHAR_PLUS)- {-#ifdef EBCDIC- *errorcodeptr = ERR93;-#else- if (utf)- {- ptr = p + 1;- escape = 0; /* Not a fancy escape after all */- goto COME_FROM_NU;- }- else *errorcodeptr = ERR93;-#endif- }-- /* Give an error if what follows is not a quantifier, but don't override- an error set by the quantifier reader (e.g. number overflow). */-- else- {- if (!read_repeat_counts(&p, ptrend, NULL, NULL, errorcodeptr) &&- *errorcodeptr == 0)- *errorcodeptr = ERR37;- }- }- }- }--/* Escapes that need further processing, including those that are unknown, have-a zero entry in the lookup table. When called from pcre2_substitute(), only \c,-\o, and \x are recognized (\u and \U can never appear as they are used for case-forcing). */--else- {- int s;- PCRE2_SPTR oldptr;- BOOL overflow;- BOOL alt_bsux =- ((options & PCRE2_ALT_BSUX) | (extra_options & PCRE2_EXTRA_ALT_BSUX)) != 0;-- /* Filter calls from pcre2_substitute(). */-- if (cb == NULL)- {- if (c != CHAR_c && c != CHAR_o && c != CHAR_x)- {- *errorcodeptr = ERR3;- return 0;- }- alt_bsux = FALSE; /* Do not modify \x handling */- }-- switch (c)- {- /* A number of Perl escapes are not handled by PCRE. We give an explicit- error. */-- case CHAR_F:- case CHAR_l:- case CHAR_L:- *errorcodeptr = ERR37;- break;-- /* \u is unrecognized when neither PCRE2_ALT_BSUX nor PCRE2_EXTRA_ALT_BSUX- is set. Otherwise, \u must be followed by exactly four hex digits or, if- PCRE2_EXTRA_ALT_BSUX is set, by any number of hex digits in braces.- Otherwise it is a lowercase u letter. This gives some compatibility with- ECMAScript (aka JavaScript). */-- case CHAR_u:- if (!alt_bsux) *errorcodeptr = ERR37; else- {- uint32_t xc;-- if (ptr >= ptrend) break;- if (*ptr == CHAR_LEFT_CURLY_BRACKET &&- (extra_options & PCRE2_EXTRA_ALT_BSUX) != 0)- {- PCRE2_SPTR hptr = ptr + 1;- cc = 0;-- while (hptr < ptrend && (xc = XDIGIT(*hptr)) != 0xff)- {- if ((cc & 0xf0000000) != 0) /* Test for 32-bit overflow */- {- *errorcodeptr = ERR77;- ptr = hptr; /* Show where */- break; /* *hptr != } will cause another break below */- }- cc = (cc << 4) | xc;- hptr++;- }-- if (hptr == ptr + 1 || /* No hex digits */- hptr >= ptrend || /* Hit end of input */- *hptr != CHAR_RIGHT_CURLY_BRACKET) /* No } terminator */- break; /* Hex escape not recognized */-- c = cc; /* Accept the code point */- ptr = hptr + 1;- }-- else /* Must be exactly 4 hex digits */- {- if (ptrend - ptr < 4) break; /* Less than 4 chars */- if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */- if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */- cc = (cc << 4) | xc;- if ((xc = XDIGIT(ptr[2])) == 0xff) break; /* Not a hex digit */- cc = (cc << 4) | xc;- if ((xc = XDIGIT(ptr[3])) == 0xff) break; /* Not a hex digit */- c = (cc << 4) | xc;- ptr += 4;- }-- if (utf)- {- if (c > 0x10ffffU) *errorcodeptr = ERR77;- else- if (c >= 0xd800 && c <= 0xdfff &&- (extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)- *errorcodeptr = ERR73;- }- else if (c > MAX_NON_UTF_CHAR) *errorcodeptr = ERR77;- }- break;-- /* \U is unrecognized unless PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set,- in which case it is an upper case letter. */-- case CHAR_U:- if (!alt_bsux) *errorcodeptr = ERR37;- break;-- /* In a character class, \g is just a literal "g". Outside a character- class, \g must be followed by one of a number of specific things:-- (1) A number, either plain or braced. If positive, it is an absolute- backreference. If negative, it is a relative backreference. This is a Perl- 5.10 feature.-- (2) Perl 5.10 also supports \g{name} as a reference to a named group. This- is part of Perl's movement towards a unified syntax for back references. As- this is synonymous with \k{name}, we fudge it up by pretending it really- was \k{name}.-- (3) For Oniguruma compatibility we also support \g followed by a name or a- number either in angle brackets or in single quotes. However, these are- (possibly recursive) subroutine calls, _not_ backreferences. We return- the ESC_g code.-- Summary: Return a negative number for a numerical back reference, ESC_k for- a named back reference, and ESC_g for a named or numbered subroutine call.- */-- case CHAR_g:- if (isclass) break;-- if (ptr >= ptrend)- {- *errorcodeptr = ERR57;- break;- }-- if (*ptr == CHAR_LESS_THAN_SIGN || *ptr == CHAR_APOSTROPHE)- {- escape = ESC_g;- break;- }-- /* If there is a brace delimiter, try to read a numerical reference. If- there isn't one, assume we have a name and treat it as \k. */-- if (*ptr == CHAR_LEFT_CURLY_BRACKET)- {- PCRE2_SPTR p = ptr + 1;- if (!read_number(&p, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s,- errorcodeptr))- {- if (*errorcodeptr == 0) escape = ESC_k; /* No number found */- break;- }- if (p >= ptrend || *p != CHAR_RIGHT_CURLY_BRACKET)- {- *errorcodeptr = ERR57;- break;- }- ptr = p + 1;- }-- /* Read an undelimited number */-- else- {- if (!read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s,- errorcodeptr))- {- if (*errorcodeptr == 0) *errorcodeptr = ERR57; /* No number found */- break;- }- }-- if (s <= 0)- {- *errorcodeptr = ERR15;- break;- }-- escape = -s;- break;-- /* The handling of escape sequences consisting of a string of digits- starting with one that is not zero is not straightforward. Perl has changed- over the years. Nowadays \g{} for backreferences and \o{} for octal are- recommended to avoid the ambiguities in the old syntax.-- Outside a character class, the digits are read as a decimal number. If the- number is less than 10, or if there are that many previous extracting left- brackets, it is a back reference. Otherwise, up to three octal digits are- read to form an escaped character code. Thus \123 is likely to be octal 123- (cf \0123, which is octal 012 followed by the literal 3).-- Inside a character class, \ followed by a digit is always either a literal- 8 or 9 or an octal number. */-- case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5:- case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:-- if (!isclass)- {- oldptr = ptr;- ptr--; /* Back to the digit */-- /* As we know we are at a digit, the only possible error from- read_number() is a number that is too large to be a group number. In this- case we fall through handle this as not a group reference. If we have- read a small enough number, check for a back reference.-- \1 to \9 are always back references. \8x and \9x are too; \1x to \7x- are octal escapes if there are not that many previous captures. */-- if (read_number(&ptr, ptrend, -1, INT_MAX/10 - 1, 0, &s, errorcodeptr) &&- (s < 10 || oldptr[-1] >= CHAR_8 || s <= (int)cb->bracount))- {- if (s > (int)MAX_GROUP_NUMBER) *errorcodeptr = ERR61;- else escape = -s; /* Indicates a back reference */- break;- }-- ptr = oldptr; /* Put the pointer back and fall through */- }-- /* Handle a digit following \ when the number is not a back reference, or- we are within a character class. If the first digit is 8 or 9, Perl used to- generate a binary zero and then treat the digit as a following literal. At- least by Perl 5.18 this changed so as not to insert the binary zero. */-- if (c >= CHAR_8) break;-- /* Fall through */-- /* \0 always starts an octal number, but we may drop through to here with a- larger first octal digit. The original code used just to take the least- significant 8 bits of octal numbers (I think this is what early Perls used- to do). Nowadays we allow for larger numbers in UTF-8 mode and 16-bit mode,- but no more than 3 octal digits. */-- case CHAR_0:- c -= CHAR_0;- while(i++ < 2 && ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7)- c = c * 8 + *ptr++ - CHAR_0;-#if PCRE2_CODE_UNIT_WIDTH == 8- if (!utf && c > 0xff) *errorcodeptr = ERR51;-#endif- break;-- /* \o is a relatively new Perl feature, supporting a more general way of- specifying character codes in octal. The only supported form is \o{ddd}. */-- case CHAR_o:- if (ptr >= ptrend || *ptr++ != CHAR_LEFT_CURLY_BRACKET)- {- ptr--;- *errorcodeptr = ERR55;- }- else if (ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)- *errorcodeptr = ERR78;- else- {- c = 0;- overflow = FALSE;- while (ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7)- {- cc = *ptr++;- if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */-#if PCRE2_CODE_UNIT_WIDTH == 32- if (c >= 0x20000000l) { overflow = TRUE; break; }-#endif- c = (c << 3) + (cc - CHAR_0);-#if PCRE2_CODE_UNIT_WIDTH == 8- if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; }-#elif PCRE2_CODE_UNIT_WIDTH == 16- if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; }-#elif PCRE2_CODE_UNIT_WIDTH == 32- if (utf && c > 0x10ffffU) { overflow = TRUE; break; }-#endif- }- if (overflow)- {- while (ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++;- *errorcodeptr = ERR34;- }- else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)- {- if (utf && c >= 0xd800 && c <= 0xdfff &&- (extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)- {- ptr--;- *errorcodeptr = ERR73;- }- }- else- {- ptr--;- *errorcodeptr = ERR64;- }- }- break;-- /* When PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set, \x must be followed- by two hexadecimal digits. Otherwise it is a lowercase x letter. */-- case CHAR_x:- if (alt_bsux)- {- uint32_t xc;- if (ptrend - ptr < 2) break; /* Less than 2 characters */- if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */- if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */- c = (cc << 4) | xc;- ptr += 2;- }-- /* Handle \x in Perl's style. \x{ddd} is a character code which can be- greater than 0xff in UTF-8 or non-8bit mode, but only if the ddd are hex- digits. If not, { used to be treated as a data character. However, Perl- seems to read hex digits up to the first non-such, and ignore the rest, so- that, for example \x{zz} matches a binary zero. This seems crazy, so PCRE- now gives an error. */-- else- {- if (ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET)- {-#ifndef EBCDIC- COME_FROM_NU:-#endif- if (++ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)- {- *errorcodeptr = ERR78;- break;- }- c = 0;- overflow = FALSE;-- while (ptr < ptrend && (cc = XDIGIT(*ptr)) != 0xff)- {- ptr++;- if (c == 0 && cc == 0) continue; /* Leading zeroes */-#if PCRE2_CODE_UNIT_WIDTH == 32- if (c >= 0x10000000l) { overflow = TRUE; break; }-#endif- c = (c << 4) | cc;- if ((utf && c > 0x10ffffU) || (!utf && c > MAX_NON_UTF_CHAR))- {- overflow = TRUE;- break;- }- }-- if (overflow)- {- while (ptr < ptrend && XDIGIT(*ptr) != 0xff) ptr++;- *errorcodeptr = ERR34;- }- else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)- {- if (utf && c >= 0xd800 && c <= 0xdfff &&- (extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)- {- ptr--;- *errorcodeptr = ERR73;- }- }-- /* If the sequence of hex digits does not end with '}', give an error.- We used just to recognize this construct and fall through to the normal- \x handling, but nowadays Perl gives an error, which seems much more- sensible, so we do too. */-- else- {- ptr--;- *errorcodeptr = ERR67;- }- } /* End of \x{} processing */-- /* Read a up to two hex digits after \x */-- else- {- c = 0;- if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */- ptr++;- c = cc;- if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */- ptr++;- c = (c << 4) | cc;- } /* End of \xdd handling */- } /* End of Perl-style \x handling */- break;-- /* The handling of \c is different in ASCII and EBCDIC environments. In an- ASCII (or Unicode) environment, an error is given if the character- following \c is not a printable ASCII character. Otherwise, the following- character is upper-cased if it is a letter, and after that the 0x40 bit is- flipped. The result is the value of the escape.-- In an EBCDIC environment the handling of \c is compatible with the- specification in the perlebcdic document. The following character must be- a letter or one of small number of special characters. These provide a- means of defining the character values 0-31.-- For testing the EBCDIC handling of \c in an ASCII environment, recognize- the EBCDIC value of 'c' explicitly. */--#if defined EBCDIC && 'a' != 0x81- case 0x83:-#else- case CHAR_c:-#endif- if (ptr >= ptrend)- {- *errorcodeptr = ERR2;- break;- }- c = *ptr;- if (c >= CHAR_a && c <= CHAR_z) c = UPPER_CASE(c);-- /* Handle \c in an ASCII/Unicode environment. */--#ifndef EBCDIC /* ASCII/UTF-8 coding */- if (c < 32 || c > 126) /* Excludes all non-printable ASCII */- {- *errorcodeptr = ERR68;- break;- }- c ^= 0x40;-- /* Handle \c in an EBCDIC environment. The special case \c? is converted to- 255 (0xff) or 95 (0x5f) if other characters suggest we are using the- POSIX-BC encoding. (This is the way Perl indicates that it handles \c?.)- The other valid sequences correspond to a list of specific characters. */--#else- if (c == CHAR_QUESTION_MARK)- c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff;- else- {- for (i = 0; i < 32; i++)- {- if (c == ebcdic_escape_c[i]) break;- }- if (i < 32) c = i; else *errorcodeptr = ERR68;- }-#endif /* EBCDIC */-- ptr++;- break;-- /* Any other alphanumeric following \ is an error. Perl gives an error only- if in warning mode, but PCRE doesn't have a warning mode. */-- default:- *errorcodeptr = ERR3;- *ptrptr = ptr - 1; /* Point to the character at fault */- return 0;- }- }--/* Set the pointer to the next character before returning. */--*ptrptr = ptr;-*chptr = c;-return escape;-}----#ifdef SUPPORT_UNICODE-/*************************************************-* Handle \P and \p *-*************************************************/--/* This function is called after \P or \p has been encountered, provided that-PCRE2 is compiled with support for UTF and Unicode properties. On entry, the-contents of ptrptr are pointing after the P or p. On exit, it is left pointing-after the final code unit of the escape sequence.--Arguments:- ptrptr the pattern position pointer- negptr a boolean that is set TRUE for negation else FALSE- ptypeptr an unsigned int that is set to the type value- pdataptr an unsigned int that is set to the detailed property value- errorcodeptr the error code variable- cb the compile data--Returns: TRUE if the type value was found, or FALSE for an invalid type-*/--static BOOL-get_ucp(PCRE2_SPTR *ptrptr, BOOL *negptr, uint16_t *ptypeptr,- uint16_t *pdataptr, int *errorcodeptr, compile_block *cb)-{-PCRE2_UCHAR c;-PCRE2_SIZE i, bot, top;-PCRE2_SPTR ptr = *ptrptr;-PCRE2_UCHAR name[50];-PCRE2_UCHAR *vptr = NULL;-uint16_t ptscript = PT_NOTSCRIPT;--if (ptr >= cb->end_pattern) goto ERROR_RETURN;-c = *ptr++;-*negptr = FALSE;--/* \P or \p can be followed by a name in {}, optionally preceded by ^ for-negation. */--if (c == CHAR_LEFT_CURLY_BRACKET)- {- if (ptr >= cb->end_pattern) goto ERROR_RETURN;-- if (*ptr == CHAR_CIRCUMFLEX_ACCENT)- {- *negptr = TRUE;- ptr++;- }-- for (i = 0; i < (int)(sizeof(name) / sizeof(PCRE2_UCHAR)) - 1; i++)- {- if (ptr >= cb->end_pattern) goto ERROR_RETURN;- c = *ptr++;- while (c == '_' || c == '-' || isspace(c))- {- if (ptr >= cb->end_pattern) goto ERROR_RETURN;- c = *ptr++;- }- if (c == CHAR_NUL) goto ERROR_RETURN;- if (c == CHAR_RIGHT_CURLY_BRACKET) break;- name[i] = tolower(c);- if ((c == ':' || c == '=') && vptr == NULL) vptr = name + i;- }-- if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN;- name[i] = 0;- }--/* If { doesn't follow \p or \P there is just one following character, which-must be an ASCII letter. */--else if (MAX_255(c) && (cb->ctypes[c] & ctype_letter) != 0)- {- name[0] = tolower(c);- name[1] = 0;- }-else goto ERROR_RETURN;--*ptrptr = ptr;--/* If the property contains ':' or '=' we have class name and value separately-specified. The following are supported:-- . Bidi_Class (synonym bc), for which the property names are "bidi<name>".- . Script (synonym sc) for which the property name is the script name- . Script_Extensions (synonym scx), ditto--As this is a small number, we currently just check the names directly. If this-grows, a sorted table and a switch will be neater.--For both the script properties, set a PT_xxx value so that (1) they can be-distinguished and (2) invalid script names that happen to be the name of-another property can be diagnosed. */--if (vptr != NULL)- {- int offset = 0;- PCRE2_UCHAR sname[8];-- *vptr = 0; /* Terminate property name */- if (PRIV(strcmp_c8)(name, STRING_bidiclass) == 0 ||- PRIV(strcmp_c8)(name, STRING_bc) == 0)- {- offset = 4;- sname[0] = CHAR_b;- sname[1] = CHAR_i; /* There is no strcpy_c8 function */- sname[2] = CHAR_d;- sname[3] = CHAR_i;- }-- else if (PRIV(strcmp_c8)(name, STRING_script) == 0 ||- PRIV(strcmp_c8)(name, STRING_sc) == 0)- ptscript = PT_SC;-- else if (PRIV(strcmp_c8)(name, STRING_scriptextensions) == 0 ||- PRIV(strcmp_c8)(name, STRING_scx) == 0)- ptscript = PT_SCX;-- else- {- *errorcodeptr = ERR47;- return FALSE;- }-- /* Adjust the string in name[] as needed */-- memmove(name + offset, vptr + 1, (name + i - vptr)*sizeof(PCRE2_UCHAR));- if (offset != 0) memmove(name, sname, offset*sizeof(PCRE2_UCHAR));- }--/* Search for a recognized property using binary chop. */--bot = 0;-top = PRIV(utt_size);--while (bot < top)- {- int r;- i = (bot + top) >> 1;- r = PRIV(strcmp_c8)(name, PRIV(utt_names) + PRIV(utt)[i].name_offset);-- /* When a matching property is found, some extra checking is needed when the- \p{xx:yy} syntax is used and xx is either sc or scx. */-- if (r == 0)- {- *pdataptr = PRIV(utt)[i].value;- if (vptr == NULL || ptscript == PT_NOTSCRIPT)- {- *ptypeptr = PRIV(utt)[i].type;- return TRUE;- }-- switch (PRIV(utt)[i].type)- {- case PT_SC:- *ptypeptr = PT_SC;- return TRUE;-- case PT_SCX:- *ptypeptr = ptscript;- return TRUE;- }-- break; /* Non-script found */- }-- if (r > 0) bot = i + 1; else top = i;- }--*errorcodeptr = ERR47; /* Unrecognized property */-return FALSE;--ERROR_RETURN: /* Malformed \P or \p */-*errorcodeptr = ERR46;-*ptrptr = ptr;-return FALSE;-}-#endif----/*************************************************-* Check for POSIX class syntax *-*************************************************/--/* This function is called when the sequence "[:" or "[." or "[=" is-encountered in a character class. It checks whether this is followed by a-sequence of characters terminated by a matching ":]" or ".]" or "=]". If we-reach an unescaped ']' without the special preceding character, return FALSE.--Originally, this function only recognized a sequence of letters between the-terminators, but it seems that Perl recognizes any sequence of characters,-though of course unknown POSIX names are subsequently rejected. Perl gives an-"Unknown POSIX class" error for [:f\oo:] for example, where previously PCRE-didn't consider this to be a POSIX class. Likewise for [:1234:].--The problem in trying to be exactly like Perl is in the handling of escapes. We-have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX-class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code-below handles the special cases \\ and \], but does not try to do any other-escape processing. This makes it different from Perl for cases such as-[:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does-not recognize "l\ower". This is a lesser evil than not diagnosing bad classes-when Perl does, I think.--A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not.-It seems that the appearance of a nested POSIX class supersedes an apparent-external class. For example, [:a[:digit:]b:] matches "a", "b", ":", or-a digit. This is handled by returning FALSE if the start of a new group with-the same terminator is encountered, since the next closing sequence must close-the nested group, not the outer one.--In Perl, unescaped square brackets may also appear as part of class names. For-example, [:a[:abc]b:] gives unknown POSIX class "[:abc]b:]". However, for-[:a[:abc]b][b:] it gives unknown POSIX class "[:abc]b][b:]", which does not-seem right at all. PCRE does not allow closing square brackets in POSIX class-names.--Arguments:- ptr pointer to the character after the initial [ (colon, dot, equals)- ptrend pointer to the end of the pattern- endptr where to return a pointer to the terminating ':', '.', or '='--Returns: TRUE or FALSE-*/--static BOOL-check_posix_syntax(PCRE2_SPTR ptr, PCRE2_SPTR ptrend, PCRE2_SPTR *endptr)-{-PCRE2_UCHAR terminator; /* Don't combine these lines; the Solaris cc */-terminator = *ptr++; /* compiler warns about "non-constant" initializer. */--for (; ptrend - ptr >= 2; ptr++)- {- if (*ptr == CHAR_BACKSLASH &&- (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET || ptr[1] == CHAR_BACKSLASH))- ptr++;-- else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) ||- *ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;-- else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)- {- *endptr = ptr;- return TRUE;- }- }--return FALSE;-}----/*************************************************-* Check POSIX class name *-*************************************************/--/* This function is called to check the name given in a POSIX-style class entry-such as [:alnum:].--Arguments:- ptr points to the first letter- len the length of the name--Returns: a value representing the name, or -1 if unknown-*/--static int-check_posix_name(PCRE2_SPTR ptr, int len)-{-const char *pn = posix_names;-int yield = 0;-while (posix_name_lengths[yield] != 0)- {- if (len == posix_name_lengths[yield] &&- PRIV(strncmp_c8)(ptr, pn, (unsigned int)len) == 0) return yield;- pn += posix_name_lengths[yield] + 1;- yield++;- }-return -1;-}----/*************************************************-* Read a subpattern or VERB name *-*************************************************/--/* This function is called from parse_regex() below whenever it needs to read-the name of a subpattern or a (*VERB) or an (*alpha_assertion). The initial-pointer must be to the character before the name. If that character is '*' we-are reading a verb or alpha assertion name. The pointer is updated to point-after the name, for a VERB or alpha assertion name, or after tha name's-terminator for a subpattern name. Returning both the offset and the name-pointer is redundant information, but some callers use one and some the other,-so it is simplest just to return both.--Arguments:- ptrptr points to the character pointer variable- ptrend points to the end of the input string- utf true if the input is UTF-encoded- terminator the terminator of a subpattern name must be this- offsetptr where to put the offset from the start of the pattern- nameptr where to put a pointer to the name in the input- namelenptr where to put the length of the name- errcodeptr where to put an error code- cb pointer to the compile data block--Returns: TRUE if a name was read- FALSE otherwise, with error code set-*/--static BOOL-read_name(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, BOOL utf, uint32_t terminator,- PCRE2_SIZE *offsetptr, PCRE2_SPTR *nameptr, uint32_t *namelenptr,- int *errorcodeptr, compile_block *cb)-{-PCRE2_SPTR ptr = *ptrptr;-BOOL is_group = (*ptr != CHAR_ASTERISK);--if (++ptr >= ptrend) /* No characters in name */- {- *errorcodeptr = is_group? ERR62: /* Subpattern name expected */- ERR60; /* Verb not recognized or malformed */- goto FAILED;- }--*nameptr = ptr;-*offsetptr = (PCRE2_SIZE)(ptr - cb->start_pattern);--/* In UTF mode, a group name may contain letters and decimal digits as defined-by Unicode properties, and underscores, but must not start with a digit. */--#ifdef SUPPORT_UNICODE-if (utf && is_group)- {- uint32_t c, type;-- GETCHAR(c, ptr);- type = UCD_CHARTYPE(c);-- if (type == ucp_Nd)- {- *errorcodeptr = ERR44;- goto FAILED;- }-- for(;;)- {- if (type != ucp_Nd && PRIV(ucp_gentype)[type] != ucp_L &&- c != CHAR_UNDERSCORE) break;- ptr++;- FORWARDCHARTEST(ptr, ptrend);- if (ptr >= ptrend) break;- GETCHAR(c, ptr);- type = UCD_CHARTYPE(c);- }- }-else-#else-(void)utf; /* Avoid compiler warning */-#endif /* SUPPORT_UNICODE */--/* Handle non-group names and group names in non-UTF modes. A group name must-not start with a digit. If either of the others start with a digit it just-won't be recognized. */-- {- if (is_group && IS_DIGIT(*ptr))- {- *errorcodeptr = ERR44;- goto FAILED;- }-- while (ptr < ptrend && MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype_word) != 0)- {- ptr++;- }- }--/* Check name length */--if (ptr > *nameptr + MAX_NAME_SIZE)- {- *errorcodeptr = ERR48;- goto FAILED;- }-*namelenptr = (uint32_t)(ptr - *nameptr);--/* Subpattern names must not be empty, and their terminator is checked here.-(What follows a verb or alpha assertion name is checked separately.) */--if (is_group)- {- if (ptr == *nameptr)- {- *errorcodeptr = ERR62; /* Subpattern name expected */- goto FAILED;- }- if (ptr >= ptrend || *ptr != (PCRE2_UCHAR)terminator)- {- *errorcodeptr = ERR42;- goto FAILED;- }- ptr++;- }--*ptrptr = ptr;-return TRUE;--FAILED:-*ptrptr = ptr;-return FALSE;-}----/*************************************************-* Manage callouts at start of cycle *-*************************************************/--/* At the start of a new item in parse_regex() we are able to record the-details of the previous item in a prior callout, and also to set up an-automatic callout if enabled. Avoid having two adjacent automatic callouts,-which would otherwise happen for items such as \Q that contribute nothing to-the parsed pattern.--Arguments:- ptr current pattern pointer- pcalloutptr points to a pointer to previous callout, or NULL- auto_callout TRUE if auto_callouts are enabled- parsed_pattern the parsed pattern pointer- cb compile block--Returns: possibly updated parsed_pattern pointer.-*/--static uint32_t *-manage_callouts(PCRE2_SPTR ptr, uint32_t **pcalloutptr, BOOL auto_callout,- uint32_t *parsed_pattern, compile_block *cb)-{-uint32_t *previous_callout = *pcalloutptr;--if (previous_callout != NULL) previous_callout[2] = (uint32_t)(ptr -- cb->start_pattern - (PCRE2_SIZE)previous_callout[1]);--if (!auto_callout) previous_callout = NULL; else- {- if (previous_callout == NULL ||- previous_callout != parsed_pattern - 4 ||- previous_callout[3] != 255)- {- previous_callout = parsed_pattern; /* Set up new automatic callout */- parsed_pattern += 4;- previous_callout[0] = META_CALLOUT_NUMBER;- previous_callout[2] = 0;- previous_callout[3] = 255;- }- previous_callout[1] = (uint32_t)(ptr - cb->start_pattern);- }--*pcalloutptr = previous_callout;-return parsed_pattern;-}----/*************************************************-* Parse regex and identify named groups *-*************************************************/--/* This function is called first of all. It scans the pattern and does two-things: (1) It identifies capturing groups and makes a table of named capturing-groups so that information about them is fully available to both the compiling-scans. (2) It writes a parsed version of the pattern with comments omitted and-escapes processed into the parsed_pattern vector.--Arguments:- ptr points to the start of the pattern- options compiling dynamic options (may change during the scan)- has_lookbehind points to a boolean, set TRUE if a lookbehind is found- cb pointer to the compile data block--Returns: zero on success or a non-zero error code, with the- error offset placed in the cb field-*/--/* A structure and some flags for dealing with nested groups. */--typedef struct nest_save {- uint16_t nest_depth;- uint16_t reset_group;- uint16_t max_group;- uint16_t flags;- uint32_t options;-} nest_save;--#define NSF_RESET 0x0001u-#define NSF_CONDASSERT 0x0002u-#define NSF_ATOMICSR 0x0004u--/* Options that are changeable within the pattern must be tracked during-parsing. Some (e.g. PCRE2_EXTENDED) are implemented entirely during parsing,-but all must be tracked so that META_OPTIONS items set the correct values for-the main compiling phase. */--#define PARSE_TRACKED_OPTIONS (PCRE2_CASELESS|PCRE2_DOTALL|PCRE2_DUPNAMES| \- PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_MULTILINE|PCRE2_NO_AUTO_CAPTURE| \- PCRE2_UNGREEDY)--/* States used for analyzing ranges in character classes. The two OK values-must be last. */--enum { RANGE_NO, RANGE_STARTED, RANGE_OK_ESCAPED, RANGE_OK_LITERAL };--/* Only in 32-bit mode can there be literals > META_END. A macro encapsulates-the storing of literal values in the main parsed pattern, where they can always-be quantified. */--#if PCRE2_CODE_UNIT_WIDTH == 32-#define PARSED_LITERAL(c, p) \- { \- if (c >= META_END) *p++ = META_BIGVALUE; \- *p++ = c; \- okquantifier = TRUE; \- }-#else-#define PARSED_LITERAL(c, p) *p++ = c; okquantifier = TRUE;-#endif--/* Here's the actual function. */--static int parse_regex(PCRE2_SPTR ptr, uint32_t options, BOOL *has_lookbehind,- compile_block *cb)-{-uint32_t c;-uint32_t delimiter;-uint32_t namelen;-uint32_t class_range_state;-uint32_t *verblengthptr = NULL; /* Value avoids compiler warning */-uint32_t *verbstartptr = NULL;-uint32_t *previous_callout = NULL;-uint32_t *parsed_pattern = cb->parsed_pattern;-uint32_t *parsed_pattern_end = cb->parsed_pattern_end;-uint32_t meta_quantifier = 0;-uint32_t add_after_mark = 0;-uint32_t extra_options = cb->cx->extra_options;-uint16_t nest_depth = 0;-int after_manual_callout = 0;-int expect_cond_assert = 0;-int errorcode = 0;-int escape;-int i;-BOOL inescq = FALSE;-BOOL inverbname = FALSE;-BOOL utf = (options & PCRE2_UTF) != 0;-BOOL auto_callout = (options & PCRE2_AUTO_CALLOUT) != 0;-BOOL isdupname;-BOOL negate_class;-BOOL okquantifier = FALSE;-PCRE2_SPTR thisptr;-PCRE2_SPTR name;-PCRE2_SPTR ptrend = cb->end_pattern;-PCRE2_SPTR verbnamestart = NULL; /* Value avoids compiler warning */-named_group *ng;-nest_save *top_nest, *end_nests;--/* Insert leading items for word and line matching (features provided for the-benefit of pcre2grep). */--if ((extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)- {- *parsed_pattern++ = META_CIRCUMFLEX;- *parsed_pattern++ = META_NOCAPTURE;- }-else if ((extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)- {- *parsed_pattern++ = META_ESCAPE + ESC_b;- *parsed_pattern++ = META_NOCAPTURE;- }--/* If the pattern is actually a literal string, process it separately to avoid-cluttering up the main loop. */--if ((options & PCRE2_LITERAL) != 0)- {- while (ptr < ptrend)- {- if (parsed_pattern >= parsed_pattern_end)- {- errorcode = ERR63; /* Internal error (parsed pattern overflow) */- goto FAILED;- }- thisptr = ptr;- GETCHARINCTEST(c, ptr);- if (auto_callout)- parsed_pattern = manage_callouts(thisptr, &previous_callout,- auto_callout, parsed_pattern, cb);- PARSED_LITERAL(c, parsed_pattern);- }- goto PARSED_END;- }--/* Process a real regex which may contain meta-characters. */--top_nest = NULL;-end_nests = (nest_save *)(cb->start_workspace + cb->workspace_size);--/* The size of the nest_save structure might not be a factor of the size of the-workspace. Therefore we must round down end_nests so as to correctly avoid-creating a nest_save that spans the end of the workspace. */--end_nests = (nest_save *)((char *)end_nests -- ((cb->workspace_size * sizeof(PCRE2_UCHAR)) % sizeof(nest_save)));--/* PCRE2_EXTENDED_MORE implies PCRE2_EXTENDED */--if ((options & PCRE2_EXTENDED_MORE) != 0) options |= PCRE2_EXTENDED;--/* Now scan the pattern */--while (ptr < ptrend)- {- int prev_expect_cond_assert;- uint32_t min_repeat, max_repeat;- uint32_t set, unset, *optset;- uint32_t terminator;- uint32_t prev_meta_quantifier;- BOOL prev_okquantifier;- PCRE2_SPTR tempptr;- PCRE2_SIZE offset;-- if (parsed_pattern >= parsed_pattern_end)- {- errorcode = ERR63; /* Internal error (parsed pattern overflow) */- goto FAILED;- }-- if (nest_depth > cb->cx->parens_nest_limit)- {- errorcode = ERR19;- goto FAILED; /* Parentheses too deeply nested */- }-- /* Get next input character, save its position for callout handling. */-- thisptr = ptr;- GETCHARINCTEST(c, ptr);-- /* Copy quoted literals until \E, allowing for the possibility of automatic- callouts, except when processing a (*VERB) "name". */-- if (inescq)- {- if (c == CHAR_BACKSLASH && ptr < ptrend && *ptr == CHAR_E)- {- inescq = FALSE;- ptr++; /* Skip E */- }- else- {- if (expect_cond_assert > 0) /* A literal is not allowed if we are */- { /* expecting a conditional assertion, */- ptr--; /* but an empty \Q\E sequence is OK. */- errorcode = ERR28;- goto FAILED;- }- if (inverbname)- { /* Don't use PARSED_LITERAL() because it */-#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */- if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;-#endif- *parsed_pattern++ = c;- }- else- {- if (after_manual_callout-- <= 0)- parsed_pattern = manage_callouts(thisptr, &previous_callout,- auto_callout, parsed_pattern, cb);- PARSED_LITERAL(c, parsed_pattern);- }- meta_quantifier = 0;- }- continue; /* Next character */- }-- /* If we are processing the "name" part of a (*VERB:NAME) item, all- characters up to the closing parenthesis are literals except when- PCRE2_ALT_VERBNAMES is set. That causes backslash interpretation, but only \Q- and \E and escaped characters are allowed (no character types such as \d). If- PCRE2_EXTENDED is also set, we must ignore white space and # comments. Do- this by not entering the special (*VERB:NAME) processing - they are then- picked up below. Note that c is a character, not a code unit, so we must not- use MAX_255 to test its size because MAX_255 tests code units and is assumed- TRUE in 8-bit mode. */-- if (inverbname &&- (- /* EITHER: not both options set */- ((options & (PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) !=- (PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) ||-#ifdef SUPPORT_UNICODE- /* OR: character > 255 AND not Unicode Pattern White Space */- (c > 255 && (c|1) != 0x200f && (c|1) != 0x2029) ||-#endif- /* OR: not a # comment or isspace() white space */- (c < 256 && c != CHAR_NUMBER_SIGN && (cb->ctypes[c] & ctype_space) == 0-#ifdef SUPPORT_UNICODE- /* and not CHAR_NEL when Unicode is supported */- && c != CHAR_NEL-#endif- )))- {- PCRE2_SIZE verbnamelength;-- switch(c)- {- default: /* Don't use PARSED_LITERAL() because it */-#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */- if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;-#endif- *parsed_pattern++ = c;- break;-- case CHAR_RIGHT_PARENTHESIS:- inverbname = FALSE;- /* This is the length in characters */- verbnamelength = (PCRE2_SIZE)(parsed_pattern - verblengthptr - 1);- /* But the limit on the length is in code units */- if (ptr - verbnamestart - 1 > (int)MAX_MARK)- {- ptr--;- errorcode = ERR76;- goto FAILED;- }- *verblengthptr = (uint32_t)verbnamelength;-- /* If this name was on a verb such as (*ACCEPT) which does not continue,- a (*MARK) was generated for the name. We now add the original verb as the- next item. */-- if (add_after_mark != 0)- {- *parsed_pattern++ = add_after_mark;- add_after_mark = 0;- }- break;-- case CHAR_BACKSLASH:- if ((options & PCRE2_ALT_VERBNAMES) != 0)- {- escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,- cb->cx->extra_options, FALSE, cb);- if (errorcode != 0) goto FAILED;- }- else escape = 0; /* Treat all as literal */-- switch(escape)- {- case 0: /* Don't use PARSED_LITERAL() because it */-#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */- if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;-#endif- *parsed_pattern++ = c;- break;-- case ESC_Q:- inescq = TRUE;- break;-- case ESC_E: /* Ignore */- break;-- default:- errorcode = ERR40; /* Invalid in verb name */- goto FAILED;- }- }- continue; /* Next character in pattern */- }-- /* Not a verb name character. At this point we must process everything that- must not change the quantification state. This is mainly comments, but we- handle \Q and \E here as well, so that an item such as A\Q\E+ is treated as- A+, as in Perl. An isolated \E is ignored. */-- if (c == CHAR_BACKSLASH && ptr < ptrend)- {- if (*ptr == CHAR_Q || *ptr == CHAR_E)- {- inescq = *ptr == CHAR_Q;- ptr++;- continue;- }- }-- /* Skip over whitespace and # comments in extended mode. Note that c is a- character, not a code unit, so we must not use MAX_255 to test its size- because MAX_255 tests code units and is assumed TRUE in 8-bit mode. The- whitespace characters are those designated as "Pattern White Space" by- Unicode, which are the isspace() characters plus CHAR_NEL (newline), which is- U+0085 in Unicode, plus U+200E, U+200F, U+2028, and U+2029. These are a- subset of space characters that match \h and \v. */-- if ((options & PCRE2_EXTENDED) != 0)- {- if (c < 256 && (cb->ctypes[c] & ctype_space) != 0) continue;-#ifdef SUPPORT_UNICODE- if (c == CHAR_NEL || (c|1) == 0x200f || (c|1) == 0x2029) continue;-#endif- if (c == CHAR_NUMBER_SIGN)- {- while (ptr < ptrend)- {- if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */- { /* IS_NEWLINE sets cb->nllen. */- ptr += cb->nllen;- break;- }- ptr++;-#ifdef SUPPORT_UNICODE- if (utf) FORWARDCHARTEST(ptr, ptrend);-#endif- }- continue; /* Next character in pattern */- }- }-- /* Skip over bracketed comments */-- if (c == CHAR_LEFT_PARENTHESIS && ptrend - ptr >= 2 &&- ptr[0] == CHAR_QUESTION_MARK && ptr[1] == CHAR_NUMBER_SIGN)- {- while (++ptr < ptrend && *ptr != CHAR_RIGHT_PARENTHESIS);- if (ptr >= ptrend)- {- errorcode = ERR18; /* A special error for missing ) in a comment */- goto FAILED; /* to make it easier to debug. */- }- ptr++;- continue; /* Next character in pattern */- }-- /* If the next item is not a quantifier, fill in length of any previous- callout and create an auto callout if required. */-- if (c != CHAR_ASTERISK && c != CHAR_PLUS && c != CHAR_QUESTION_MARK &&- (c != CHAR_LEFT_CURLY_BRACKET ||- (tempptr = ptr,- !read_repeat_counts(&tempptr, ptrend, NULL, NULL, &errorcode))))- {- if (after_manual_callout-- <= 0)- parsed_pattern = manage_callouts(thisptr, &previous_callout, auto_callout,- parsed_pattern, cb);- }-- /* If expect_cond_assert is 2, we have just passed (?( and are expecting an- assertion, possibly preceded by a callout. If the value is 1, we have just- had the callout and expect an assertion. There must be at least 3 more- characters in all cases. When expect_cond_assert is 2, we know that the- current character is an opening parenthesis, as otherwise we wouldn't be- here. However, when it is 1, we need to check, and it's easiest just to check- always. Note that expect_cond_assert may be negative, since all callouts just- decrement it. */-- if (expect_cond_assert > 0)- {- BOOL ok = c == CHAR_LEFT_PARENTHESIS && ptrend - ptr >= 3 &&- (ptr[0] == CHAR_QUESTION_MARK || ptr[0] == CHAR_ASTERISK);- if (ok)- {- if (ptr[0] == CHAR_ASTERISK) /* New alpha assertion format, possibly */- {- ok = MAX_255(ptr[1]) && (cb->ctypes[ptr[1]] & ctype_lcletter) != 0;- }- else switch(ptr[1]) /* Traditional symbolic format */- {- case CHAR_C:- ok = expect_cond_assert == 2;- break;-- case CHAR_EQUALS_SIGN:- case CHAR_EXCLAMATION_MARK:- break;-- case CHAR_LESS_THAN_SIGN:- ok = ptr[2] == CHAR_EQUALS_SIGN || ptr[2] == CHAR_EXCLAMATION_MARK;- break;-- default:- ok = FALSE;- }- }-- if (!ok)- {- ptr--; /* Adjust error offset */- errorcode = ERR28;- goto FAILED;- }- }-- /* Remember whether we are expecting a conditional assertion, and set the- default for this item. */-- prev_expect_cond_assert = expect_cond_assert;- expect_cond_assert = 0;-- /* Remember quantification status for the previous significant item, then set- default for this item. */-- prev_okquantifier = okquantifier;- prev_meta_quantifier = meta_quantifier;- okquantifier = FALSE;- meta_quantifier = 0;-- /* If the previous significant item was a quantifier, adjust the parsed code- if there is a following modifier. The base meta value is always followed by- the PLUS and QUERY values, in that order. We do this here rather than after- reading a quantifier so that intervening comments and /x whitespace can be- ignored without having to replicate code. */-- if (prev_meta_quantifier != 0 && (c == CHAR_QUESTION_MARK || c == CHAR_PLUS))- {- parsed_pattern[(prev_meta_quantifier == META_MINMAX)? -3 : -1] =- prev_meta_quantifier + ((c == CHAR_QUESTION_MARK)?- 0x00020000u : 0x00010000u);- continue; /* Next character in pattern */- }--- /* Process the next item in the main part of a pattern. */-- switch(c)- {- default: /* Non-special character */- PARSED_LITERAL(c, parsed_pattern);- break;--- /* ---- Escape sequence ---- */-- case CHAR_BACKSLASH:- tempptr = ptr;- escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,- cb->cx->extra_options, FALSE, cb);- if (errorcode != 0)- {- ESCAPE_FAILED:- if ((extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)- goto FAILED;- ptr = tempptr;- if (ptr >= ptrend) c = CHAR_BACKSLASH; else- {- GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */- }- escape = 0; /* Treat as literal character */- }-- /* The escape was a data escape or literal character. */-- if (escape == 0)- {- PARSED_LITERAL(c, parsed_pattern);- }-- /* The escape was a back (or forward) reference. We keep the offset in- order to give a more useful diagnostic for a bad forward reference. For- references to groups numbered less than 10 we can't use more than two items- in parsed_pattern because they may be just two characters in the input (and- in a 64-bit world an offset may need two elements). So for them, the offset- of the first occurrent is held in a special vector. */-- else if (escape < 0)- {- offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 1);- escape = -escape;- *parsed_pattern++ = META_BACKREF | (uint32_t)escape;- if (escape < 10)- {- if (cb->small_ref_offset[escape] == PCRE2_UNSET)- cb->small_ref_offset[escape] = offset;- }- else- {- PUTOFFSET(offset, parsed_pattern);- }- okquantifier = TRUE;- }-- /* The escape was a character class such as \d etc. or other special- escape indicator such as \A or \X. Most of them generate just a single- parsed item, but \P and \p are followed by a 16-bit type and a 16-bit- value. They are supported only when Unicode is available. The type and- value are packed into a single 32-bit value so that the whole sequences- uses only two elements in the parsed_vector. This is because the same- coding is used if \d (for example) is turned into \p{Nd} when PCRE2_UCP is- set.-- There are also some cases where the escape sequence is followed by a name:- \k{name}, \k<name>, and \k'name' are backreferences by name, and \g<name>- and \g'name' are subroutine calls by name; \g{name} is a synonym for- \k{name}. Note that \g<number> and \g'number' are handled by check_escape()- and returned as a negative value (handled above). A name is coded as an- offset into the pattern and a length. */-- else switch (escape)- {- case ESC_C:-#ifdef NEVER_BACKSLASH_C- errorcode = ERR85;- goto ESCAPE_FAILED;-#else- if ((options & PCRE2_NEVER_BACKSLASH_C) != 0)- {- errorcode = ERR83;- goto ESCAPE_FAILED;- }-#endif- okquantifier = TRUE;- *parsed_pattern++ = META_ESCAPE + escape;- break;-- case ESC_X:-#ifndef SUPPORT_UNICODE- errorcode = ERR45; /* Supported only with Unicode support */- goto ESCAPE_FAILED;-#endif- case ESC_H:- case ESC_h:- case ESC_N:- case ESC_R:- case ESC_V:- case ESC_v:- okquantifier = TRUE;- *parsed_pattern++ = META_ESCAPE + escape;- break;-- default: /* \A, \B, \b, \G, \K, \Z, \z cannot be quantified. */- *parsed_pattern++ = META_ESCAPE + escape;- break;-- /* Escapes that change in UCP mode. Note that PCRE2_UCP will never be set- without Unicode support because it is checked when pcre2_compile() is- called. */-- case ESC_d:- case ESC_D:- case ESC_s:- case ESC_S:- case ESC_w:- case ESC_W:- okquantifier = TRUE;- if ((options & PCRE2_UCP) == 0)- {- *parsed_pattern++ = META_ESCAPE + escape;- }- else- {- *parsed_pattern++ = META_ESCAPE +- ((escape == ESC_d || escape == ESC_s || escape == ESC_w)?- ESC_p : ESC_P);- switch(escape)- {- case ESC_d:- case ESC_D:- *parsed_pattern++ = (PT_PC << 16) | ucp_Nd;- break;-- case ESC_s:- case ESC_S:- *parsed_pattern++ = PT_SPACE << 16;- break;-- case ESC_w:- case ESC_W:- *parsed_pattern++ = PT_WORD << 16;- break;- }- }- break;-- /* Unicode property matching */-- case ESC_P:- case ESC_p:-#ifdef SUPPORT_UNICODE- {- BOOL negated;- uint16_t ptype = 0, pdata = 0;- if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))- goto ESCAPE_FAILED;- if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P;- *parsed_pattern++ = META_ESCAPE + escape;- *parsed_pattern++ = (ptype << 16) | pdata;- okquantifier = TRUE;- }-#else- errorcode = ERR45;- goto ESCAPE_FAILED;-#endif- break; /* End \P and \p */-- /* When \g is used with quotes or angle brackets as delimiters, it is a- numerical or named subroutine call, and control comes here. When used- with brace delimiters it is a numberical back reference and does not come- here because check_escape() returns it directly as a reference. \k is- always a named back reference. */-- case ESC_g:- case ESC_k:- if (ptr >= ptrend || (*ptr != CHAR_LEFT_CURLY_BRACKET &&- *ptr != CHAR_LESS_THAN_SIGN && *ptr != CHAR_APOSTROPHE))- {- errorcode = (escape == ESC_g)? ERR57 : ERR69;- goto ESCAPE_FAILED;- }- terminator = (*ptr == CHAR_LESS_THAN_SIGN)?- CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)?- CHAR_APOSTROPHE : CHAR_RIGHT_CURLY_BRACKET;-- /* For a non-braced \g, check for a numerical recursion. */-- if (escape == ESC_g && terminator != CHAR_RIGHT_CURLY_BRACKET)- {- PCRE2_SPTR p = ptr + 1;-- if (read_number(&p, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &i,- &errorcode))- {- if (p >= ptrend || *p != terminator)- {- errorcode = ERR57;- goto ESCAPE_FAILED;- }- ptr = p;- goto SET_RECURSION;- }- if (errorcode != 0) goto ESCAPE_FAILED;- }-- /* Not a numerical recursion */-- if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,- &errorcode, cb)) goto ESCAPE_FAILED;-- /* \k and \g when used with braces are back references, whereas \g used- with quotes or angle brackets is a recursion */-- *parsed_pattern++ =- (escape == ESC_k || terminator == CHAR_RIGHT_CURLY_BRACKET)?- META_BACKREF_BYNAME : META_RECURSE_BYNAME;- *parsed_pattern++ = namelen;-- PUTOFFSET(offset, parsed_pattern);- okquantifier = TRUE;- break; /* End special escape processing */- }- break; /* End escape sequence processing */--- /* ---- Single-character special items ---- */-- case CHAR_CIRCUMFLEX_ACCENT:- *parsed_pattern++ = META_CIRCUMFLEX;- break;-- case CHAR_DOLLAR_SIGN:- *parsed_pattern++ = META_DOLLAR;- break;-- case CHAR_DOT:- *parsed_pattern++ = META_DOT;- okquantifier = TRUE;- break;--- /* ---- Single-character quantifiers ---- */-- case CHAR_ASTERISK:- meta_quantifier = META_ASTERISK;- goto CHECK_QUANTIFIER;-- case CHAR_PLUS:- meta_quantifier = META_PLUS;- goto CHECK_QUANTIFIER;-- case CHAR_QUESTION_MARK:- meta_quantifier = META_QUERY;- goto CHECK_QUANTIFIER;--- /* ---- Potential {n,m} quantifier ---- */-- case CHAR_LEFT_CURLY_BRACKET:- if (!read_repeat_counts(&ptr, ptrend, &min_repeat, &max_repeat,- &errorcode))- {- if (errorcode != 0) goto FAILED; /* Error in quantifier. */- PARSED_LITERAL(c, parsed_pattern); /* Not a quantifier */- break; /* No more quantifier processing */- }- meta_quantifier = META_MINMAX;- /* Fall through */--- /* ---- Quantifier post-processing ---- */-- /* Check that a quantifier is allowed after the previous item. */-- CHECK_QUANTIFIER:- if (!prev_okquantifier)- {- errorcode = ERR9;- goto FAILED_BACK;- }-- /* Most (*VERB)s are not allowed to be quantified, but an ungreedy- quantifier can be useful for (*ACCEPT) - meaning "succeed on backtrack", a- sort of negated (*COMMIT). We therefore allow (*ACCEPT) to be quantified by- wrapping it in non-capturing brackets, but we have to allow for a preceding- (*MARK) for when (*ACCEPT) has an argument. */-- if (parsed_pattern[-1] == META_ACCEPT)- {- uint32_t *p;- for (p = parsed_pattern - 1; p >= verbstartptr; p--) p[1] = p[0];- *verbstartptr = META_NOCAPTURE;- parsed_pattern[1] = META_KET;- parsed_pattern += 2;- }-- /* Now we can put the quantifier into the parsed pattern vector. At this- stage, we have only the basic quantifier. The check for a following + or ?- modifier happens at the top of the loop, after any intervening comments- have been removed. */-- *parsed_pattern++ = meta_quantifier;- if (c == CHAR_LEFT_CURLY_BRACKET)- {- *parsed_pattern++ = min_repeat;- *parsed_pattern++ = max_repeat;- }- break;--- /* ---- Character class ---- */-- case CHAR_LEFT_SQUARE_BRACKET:- okquantifier = TRUE;-- /* In another (POSIX) regex library, the ugly syntax [[:<:]] and [[:>:]] is- used for "start of word" and "end of word". As these are otherwise illegal- sequences, we don't break anything by recognizing them. They are replaced- by \b(?=\w) and \b(?<=\w) respectively. Sequences like [a[:<:]] are- erroneous and are handled by the normal code below. */-- if (ptrend - ptr >= 6 &&- (PRIV(strncmp_c8)(ptr, STRING_WEIRD_STARTWORD, 6) == 0 ||- PRIV(strncmp_c8)(ptr, STRING_WEIRD_ENDWORD, 6) == 0))- {- *parsed_pattern++ = META_ESCAPE + ESC_b;-- if (ptr[2] == CHAR_LESS_THAN_SIGN)- {- *parsed_pattern++ = META_LOOKAHEAD;- }- else- {- *parsed_pattern++ = META_LOOKBEHIND;- *has_lookbehind = TRUE;-- /* The offset is used only for the "non-fixed length" error; this won't- occur here, so just store zero. */-- PUTOFFSET((PCRE2_SIZE)0, parsed_pattern);- }-- if ((options & PCRE2_UCP) == 0)- *parsed_pattern++ = META_ESCAPE + ESC_w;- else- {- *parsed_pattern++ = META_ESCAPE + ESC_p;- *parsed_pattern++ = PT_WORD << 16;- }- *parsed_pattern++ = META_KET;- ptr += 6;- break;- }-- /* PCRE supports POSIX class stuff inside a class. Perl gives an error if- they are encountered at the top level, so we'll do that too. */-- if (ptr < ptrend && (*ptr == CHAR_COLON || *ptr == CHAR_DOT ||- *ptr == CHAR_EQUALS_SIGN) &&- check_posix_syntax(ptr, ptrend, &tempptr))- {- errorcode = (*ptr-- == CHAR_COLON)? ERR12 : ERR13;- goto FAILED;- }-- /* Process a regular character class. If the first character is '^', set- the negation flag. If the first few characters (either before or after ^)- are \Q\E or \E or space or tab in extended-more mode, we skip them too.- This makes for compatibility with Perl. */-- negate_class = FALSE;- while (ptr < ptrend)- {- GETCHARINCTEST(c, ptr);- if (c == CHAR_BACKSLASH)- {- if (ptr < ptrend && *ptr == CHAR_E) ptr++;- else if (ptrend - ptr >= 3 &&- PRIV(strncmp_c8)(ptr, STR_Q STR_BACKSLASH STR_E, 3) == 0)- ptr += 3;- else- break;- }- else if ((options & PCRE2_EXTENDED_MORE) != 0 &&- (c == CHAR_SPACE || c == CHAR_HT)) /* Note: just these two */- continue;- else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT)- negate_class = TRUE;- else break;- }-- /* Now the real contents of the class; c has the first "real" character.- Empty classes are permitted only if the option is set. */-- if (c == CHAR_RIGHT_SQUARE_BRACKET &&- (cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)- {- *parsed_pattern++ = negate_class? META_CLASS_EMPTY_NOT : META_CLASS_EMPTY;- break; /* End of class processing */- }-- /* Process a non-empty class. */-- *parsed_pattern++ = negate_class? META_CLASS_NOT : META_CLASS;- class_range_state = RANGE_NO;-- /* In an EBCDIC environment, Perl treats alphabetic ranges specially- because there are holes in the encoding, and simply using the range A-Z- (for example) would include the characters in the holes. This applies only- to ranges where both values are literal; [\xC1-\xE9] is different to [A-Z]- in this respect. In order to accommodate this, we keep track of whether- character values are literal or not, and a state variable for handling- ranges. */-- /* Loop for the contents of the class */-- for (;;)- {- BOOL char_is_literal = TRUE;-- /* Inside \Q...\E everything is literal except \E */-- if (inescq)- {- if (c == CHAR_BACKSLASH && ptr < ptrend && *ptr == CHAR_E)- {- inescq = FALSE; /* Reset literal state */- ptr++; /* Skip the 'E' */- goto CLASS_CONTINUE;- }- goto CLASS_LITERAL;- }-- /* Skip over space and tab (only) in extended-more mode. */-- if ((options & PCRE2_EXTENDED_MORE) != 0 &&- (c == CHAR_SPACE || c == CHAR_HT))- goto CLASS_CONTINUE;-- /* Handle POSIX class names. Perl allows a negation extension of the- form [:^name:]. A square bracket that doesn't match the syntax is- treated as a literal. We also recognize the POSIX constructions- [.ch.] and [=ch=] ("collating elements") and fault them, as Perl- 5.6 and 5.8 do. */-- if (c == CHAR_LEFT_SQUARE_BRACKET &&- ptrend - ptr >= 3 &&- (*ptr == CHAR_COLON || *ptr == CHAR_DOT ||- *ptr == CHAR_EQUALS_SIGN) &&- check_posix_syntax(ptr, ptrend, &tempptr))- {- BOOL posix_negate = FALSE;- int posix_class;-- /* Perl treats a hyphen before a POSIX class as a literal, not the- start of a range. However, it gives a warning in its warning mode. PCRE- does not have a warning mode, so we give an error, because this is- likely an error on the user's part. */-- if (class_range_state == RANGE_STARTED)- {- errorcode = ERR50;- goto FAILED;- }-- if (*ptr != CHAR_COLON)- {- errorcode = ERR13;- goto FAILED_BACK;- }-- if (*(++ptr) == CHAR_CIRCUMFLEX_ACCENT)- {- posix_negate = TRUE;- ptr++;- }-- posix_class = check_posix_name(ptr, (int)(tempptr - ptr));- if (posix_class < 0)- {- errorcode = ERR30;- goto FAILED;- }- ptr = tempptr + 2;-- /* Perl treats a hyphen after a POSIX class as a literal, not the- start of a range. However, it gives a warning in its warning mode- unless the hyphen is the last character in the class. PCRE does not- have a warning mode, so we give an error, because this is likely an- error on the user's part. */-- if (ptr < ptrend - 1 && *ptr == CHAR_MINUS &&- ptr[1] != CHAR_RIGHT_SQUARE_BRACKET)- {- errorcode = ERR50;- goto FAILED;- }-- /* Set "a hyphen is not the start of a range" for the -] case, and also- in case the POSIX class is followed by \E or \Q\E (possibly repeated -- fuzzers do that kind of thing) and *then* a hyphen. This causes that- hyphen to be treated as a literal. I don't think it's worth setting up- special apparatus to do otherwise. */-- class_range_state = RANGE_NO;-- /* When PCRE2_UCP is set, some of the POSIX classes are converted to- use Unicode properties \p or \P or, in one case, \h or \H. The- substitutes table has two values per class, containing the type and- value of a \p or \P item. The special cases are specified with a- negative type: a non-zero value causes \h or \H to be used, and a zero- value falls through to behave like a non-UCP POSIX class. */--#ifdef SUPPORT_UNICODE- if ((options & PCRE2_UCP) != 0)- {- int ptype = posix_substitutes[2*posix_class];- int pvalue = posix_substitutes[2*posix_class + 1];- if (ptype >= 0)- {- *parsed_pattern++ = META_ESCAPE + (posix_negate? ESC_P : ESC_p);- *parsed_pattern++ = (ptype << 16) | pvalue;- goto CLASS_CONTINUE;- }-- if (pvalue != 0)- {- *parsed_pattern++ = META_ESCAPE + (posix_negate? ESC_H : ESC_h);- goto CLASS_CONTINUE;- }-- /* Fall through */- }-#endif /* SUPPORT_UNICODE */-- /* Non-UCP POSIX class */-- *parsed_pattern++ = posix_negate? META_POSIX_NEG : META_POSIX;- *parsed_pattern++ = posix_class;- }-- /* Handle potential start of range */-- else if (c == CHAR_MINUS && class_range_state >= RANGE_OK_ESCAPED)- {- *parsed_pattern++ = (class_range_state == RANGE_OK_LITERAL)?- META_RANGE_LITERAL : META_RANGE_ESCAPED;- class_range_state = RANGE_STARTED;- }-- /* Handle a literal character */-- else if (c != CHAR_BACKSLASH)- {- CLASS_LITERAL:- if (class_range_state == RANGE_STARTED)- {- if (c == parsed_pattern[-2]) /* Optimize one-char range */- parsed_pattern--;- else if (parsed_pattern[-2] > c) /* Check range is in order */- {- errorcode = ERR8;- goto FAILED_BACK;- }- else- {- if (!char_is_literal && parsed_pattern[-1] == META_RANGE_LITERAL)- parsed_pattern[-1] = META_RANGE_ESCAPED;- PARSED_LITERAL(c, parsed_pattern);- }- class_range_state = RANGE_NO;- }- else /* Potential start of range */- {- class_range_state = char_is_literal?- RANGE_OK_LITERAL : RANGE_OK_ESCAPED;- PARSED_LITERAL(c, parsed_pattern);- }- }-- /* Handle escapes in a class */-- else- {- tempptr = ptr;- escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,- cb->cx->extra_options, TRUE, cb);-- if (errorcode != 0)- {- if ((extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)- goto FAILED;- ptr = tempptr;- if (ptr >= ptrend) c = CHAR_BACKSLASH; else- {- GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */- }- escape = 0; /* Treat as literal character */- }-- switch(escape)- {- case 0: /* Escaped character code point is in c */- char_is_literal = FALSE;- goto CLASS_LITERAL;-- case ESC_b:- c = CHAR_BS; /* \b is backspace in a class */- char_is_literal = FALSE;- goto CLASS_LITERAL;-- case ESC_Q:- inescq = TRUE; /* Enter literal mode */- goto CLASS_CONTINUE;-- case ESC_E: /* Ignore orphan \E */- goto CLASS_CONTINUE;-- case ESC_B: /* Always an error in a class */- case ESC_R:- case ESC_X:- errorcode = ERR7;- ptr--;- goto FAILED;- }-- /* The second part of a range can be a single-character escape- sequence (detected above), but not any of the other escapes. Perl- treats a hyphen as a literal in such circumstances. However, in Perl's- warning mode, a warning is given, so PCRE now faults it, as it is- almost certainly a mistake on the user's part. */-- if (class_range_state == RANGE_STARTED)- {- errorcode = ERR50;- goto FAILED; /* Not CLASS_ESCAPE_FAILED; always an error */- }-- /* Of the remaining escapes, only those that define characters are- allowed in a class. None may start a range. */-- class_range_state = RANGE_NO;- switch(escape)- {- case ESC_N:- errorcode = ERR71;- goto FAILED;-- case ESC_H:- case ESC_h:- case ESC_V:- case ESC_v:- *parsed_pattern++ = META_ESCAPE + escape;- break;-- /* These escapes are converted to Unicode property tests when- PCRE2_UCP is set. */-- case ESC_d:- case ESC_D:- case ESC_s:- case ESC_S:- case ESC_w:- case ESC_W:- if ((options & PCRE2_UCP) == 0)- {- *parsed_pattern++ = META_ESCAPE + escape;- }- else- {- *parsed_pattern++ = META_ESCAPE +- ((escape == ESC_d || escape == ESC_s || escape == ESC_w)?- ESC_p : ESC_P);- switch(escape)- {- case ESC_d:- case ESC_D:- *parsed_pattern++ = (PT_PC << 16) | ucp_Nd;- break;-- case ESC_s:- case ESC_S:- *parsed_pattern++ = PT_SPACE << 16;- break;-- case ESC_w:- case ESC_W:- *parsed_pattern++ = PT_WORD << 16;- break;- }- }- break;-- /* Explicit Unicode property matching */-- case ESC_P:- case ESC_p:-#ifdef SUPPORT_UNICODE- {- BOOL negated;- uint16_t ptype = 0, pdata = 0;- if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))- goto FAILED;- if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P;- *parsed_pattern++ = META_ESCAPE + escape;- *parsed_pattern++ = (ptype << 16) | pdata;- }-#else- errorcode = ERR45;- goto FAILED;-#endif- break; /* End \P and \p */-- default: /* All others are not allowed in a class */- errorcode = ERR7;- ptr--;- goto FAILED;- }-- /* Perl gives a warning unless a following hyphen is the last character- in the class. PCRE throws an error. */-- if (ptr < ptrend - 1 && *ptr == CHAR_MINUS &&- ptr[1] != CHAR_RIGHT_SQUARE_BRACKET)- {- errorcode = ERR50;- goto FAILED;- }- }-- /* Proceed to next thing in the class. */-- CLASS_CONTINUE:- if (ptr >= ptrend)- {- errorcode = ERR6; /* Missing terminating ']' */- goto FAILED;- }- GETCHARINCTEST(c, ptr);- if (c == CHAR_RIGHT_SQUARE_BRACKET && !inescq) break;- } /* End of class-processing loop */-- /* -] at the end of a class is a literal '-' */-- if (class_range_state == RANGE_STARTED)- {- parsed_pattern[-1] = CHAR_MINUS;- class_range_state = RANGE_NO;- }-- *parsed_pattern++ = META_CLASS_END;- break; /* End of character class */--- /* ---- Opening parenthesis ---- */-- case CHAR_LEFT_PARENTHESIS:- if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;-- /* If ( is not followed by ? it is either a capture or a special verb or an- alpha assertion or a positive non-atomic lookahead. */-- if (*ptr != CHAR_QUESTION_MARK)- {- const char *vn;-- /* Handle capturing brackets (or non-capturing if auto-capture is turned- off). */-- if (*ptr != CHAR_ASTERISK)- {- nest_depth++;- if ((options & PCRE2_NO_AUTO_CAPTURE) == 0)- {- if (cb->bracount >= MAX_GROUP_NUMBER)- {- errorcode = ERR97;- goto FAILED;- }- cb->bracount++;- *parsed_pattern++ = META_CAPTURE | cb->bracount;- }- else *parsed_pattern++ = META_NOCAPTURE;- }-- /* Do nothing for (* followed by end of pattern or ) so it gives a "bad- quantifier" error rather than "(*MARK) must have an argument". */-- else if (ptrend - ptr <= 1 || (c = ptr[1]) == CHAR_RIGHT_PARENTHESIS)- break;-- /* Handle "alpha assertions" such as (*pla:...). Most of these are- synonyms for the historical symbolic assertions, but the script run and- non-atomic lookaround ones are new. They are distinguished by starting- with a lower case letter. Checking both ends of the alphabet makes this- work in all character codes. */-- else if (CHMAX_255(c) && (cb->ctypes[c] & ctype_lcletter) != 0)- {- uint32_t meta;-- vn = alasnames;- if (!read_name(&ptr, ptrend, utf, 0, &offset, &name, &namelen,- &errorcode, cb)) goto FAILED;- if (ptr >= ptrend || *ptr != CHAR_COLON)- {- errorcode = ERR95; /* Malformed */- goto FAILED;- }-- /* Scan the table of alpha assertion names */-- for (i = 0; i < alascount; i++)- {- if (namelen == alasmeta[i].len &&- PRIV(strncmp_c8)(name, vn, namelen) == 0)- break;- vn += alasmeta[i].len + 1;- }-- if (i >= alascount)- {- errorcode = ERR95; /* Alpha assertion not recognized */- goto FAILED;- }-- /* Check for expecting an assertion condition. If so, only atomic- lookaround assertions are valid. */-- meta = alasmeta[i].meta;- if (prev_expect_cond_assert > 0 &&- (meta < META_LOOKAHEAD || meta > META_LOOKBEHINDNOT))- {- errorcode = (meta == META_LOOKAHEAD_NA || meta == META_LOOKBEHIND_NA)?- ERR98 : ERR28; /* (Atomic) assertion expected */- goto FAILED;- }-- /* The lookaround alphabetic synonyms can mostly be handled by jumping- to the code that handles the traditional symbolic forms. */-- switch(meta)- {- default:- errorcode = ERR89; /* Unknown code; should never occur because */- goto FAILED; /* the meta values come from a table above. */-- case META_ATOMIC:- goto ATOMIC_GROUP;-- case META_LOOKAHEAD:- goto POSITIVE_LOOK_AHEAD;-- case META_LOOKAHEAD_NA:- goto POSITIVE_NONATOMIC_LOOK_AHEAD;-- case META_LOOKAHEADNOT:- goto NEGATIVE_LOOK_AHEAD;-- case META_LOOKBEHIND:- case META_LOOKBEHINDNOT:- case META_LOOKBEHIND_NA:- *parsed_pattern++ = meta;- ptr--;- goto POST_LOOKBEHIND;-- /* The script run facilities are handled here. Unicode support is- required (give an error if not, as this is a security issue). Always- record a META_SCRIPT_RUN item. Then, for the atomic version, insert- META_ATOMIC and remember that we need two META_KETs at the end. */-- case META_SCRIPT_RUN:- case META_ATOMIC_SCRIPT_RUN:-#ifdef SUPPORT_UNICODE- *parsed_pattern++ = META_SCRIPT_RUN;- nest_depth++;- ptr++;- if (meta == META_ATOMIC_SCRIPT_RUN)- {- *parsed_pattern++ = META_ATOMIC;- if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);- else if (++top_nest >= end_nests)- {- errorcode = ERR84;- goto FAILED;- }- top_nest->nest_depth = nest_depth;- top_nest->flags = NSF_ATOMICSR;- top_nest->options = options & PARSE_TRACKED_OPTIONS;- }- break;-#else /* SUPPORT_UNICODE */- errorcode = ERR96;- goto FAILED;-#endif- }- }--- /* ---- Handle (*VERB) and (*VERB:NAME) ---- */-- else- {- vn = verbnames;- if (!read_name(&ptr, ptrend, utf, 0, &offset, &name, &namelen,- &errorcode, cb)) goto FAILED;- if (ptr >= ptrend || (*ptr != CHAR_COLON &&- *ptr != CHAR_RIGHT_PARENTHESIS))- {- errorcode = ERR60; /* Malformed */- goto FAILED;- }-- /* Scan the table of verb names */-- for (i = 0; i < verbcount; i++)- {- if (namelen == verbs[i].len &&- PRIV(strncmp_c8)(name, vn, namelen) == 0)- break;- vn += verbs[i].len + 1;- }-- if (i >= verbcount)- {- errorcode = ERR60; /* Verb not recognized */- goto FAILED;- }-- /* An empty argument is treated as no argument. */-- if (*ptr == CHAR_COLON && ptr + 1 < ptrend &&- ptr[1] == CHAR_RIGHT_PARENTHESIS)- ptr++; /* Advance to the closing parens */-- /* Check for mandatory non-empty argument; this is (*MARK) */-- if (verbs[i].has_arg > 0 && *ptr != CHAR_COLON)- {- errorcode = ERR66;- goto FAILED;- }-- /* Remember where this verb, possibly with a preceding (*MARK), starts,- for handling quantified (*ACCEPT). */-- verbstartptr = parsed_pattern;- okquantifier = (verbs[i].meta == META_ACCEPT);-- /* It appears that Perl allows any characters whatsoever, other than a- closing parenthesis, to appear in arguments ("names"), so we no longer- insist on letters, digits, and underscores. Perl does not, however, do- any interpretation within arguments, and has no means of including a- closing parenthesis. PCRE supports escape processing but only when it- is requested by an option. We set inverbname TRUE here, and let the- main loop take care of this so that escape and \x processing is done by- the main code above. */-- if (*ptr++ == CHAR_COLON) /* Skip past : or ) */- {- /* Some optional arguments can be treated as a preceding (*MARK) */-- if (verbs[i].has_arg < 0)- {- add_after_mark = verbs[i].meta;- *parsed_pattern++ = META_MARK;- }-- /* The remaining verbs with arguments (except *MARK) need a different- opcode. */-- else- {- *parsed_pattern++ = verbs[i].meta +- ((verbs[i].meta != META_MARK)? 0x00010000u:0);- }-- /* Set up for reading the name in the main loop. */-- verblengthptr = parsed_pattern++;- verbnamestart = ptr;- inverbname = TRUE;- }- else /* No verb "name" argument */- {- *parsed_pattern++ = verbs[i].meta;- }- } /* End of (*VERB) handling */- break; /* Done with this parenthesis */- } /* End of groups that don't start with (? */--- /* ---- Items starting (? ---- */-- /* The type of item is determined by what follows (?. Handle (?| and option- changes under "default" because both need a new block on the nest stack.- Comments starting with (?# are handled above. Note that there is some- ambiguity about the sequence (?- because if a digit follows it's a relative- recursion or subroutine call whereas otherwise it's an option unsetting. */-- if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;-- switch(*ptr)- {- default:- if (*ptr == CHAR_MINUS && ptrend - ptr > 1 && IS_DIGIT(ptr[1]))- goto RECURSION_BYNUMBER; /* The + case is handled by CHAR_PLUS */-- /* We now have either (?| or a (possibly empty) option setting,- optionally followed by a non-capturing group. */-- nest_depth++;- if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);- else if (++top_nest >= end_nests)- {- errorcode = ERR84;- goto FAILED;- }- top_nest->nest_depth = nest_depth;- top_nest->flags = 0;- top_nest->options = options & PARSE_TRACKED_OPTIONS;-- /* Start of non-capturing group that resets the capture count for each- branch. */-- if (*ptr == CHAR_VERTICAL_LINE)- {- top_nest->reset_group = (uint16_t)cb->bracount;- top_nest->max_group = (uint16_t)cb->bracount;- top_nest->flags |= NSF_RESET;- cb->external_flags |= PCRE2_DUPCAPUSED;- *parsed_pattern++ = META_NOCAPTURE;- ptr++;- }-- /* Scan for options imnsxJU to be set or unset. */-- else- {- BOOL hyphenok = TRUE;- uint32_t oldoptions = options;-- top_nest->reset_group = 0;- top_nest->max_group = 0;- set = unset = 0;- optset = &set;-- /* ^ at the start unsets imnsx and disables the subsequent use of - */-- if (ptr < ptrend && *ptr == CHAR_CIRCUMFLEX_ACCENT)- {- options &= ~(PCRE2_CASELESS|PCRE2_MULTILINE|PCRE2_NO_AUTO_CAPTURE|- PCRE2_DOTALL|PCRE2_EXTENDED|PCRE2_EXTENDED_MORE);- hyphenok = FALSE;- ptr++;- }-- while (ptr < ptrend && *ptr != CHAR_RIGHT_PARENTHESIS &&- *ptr != CHAR_COLON)- {- switch (*ptr++)- {- case CHAR_MINUS:- if (!hyphenok)- {- errorcode = ERR94;- ptr--; /* Correct the offset */- goto FAILED;- }- optset = &unset;- hyphenok = FALSE;- break;-- case CHAR_J: /* Record that it changed in the external options */- *optset |= PCRE2_DUPNAMES;- cb->external_flags |= PCRE2_JCHANGED;- break;-- case CHAR_i: *optset |= PCRE2_CASELESS; break;- case CHAR_m: *optset |= PCRE2_MULTILINE; break;- case CHAR_n: *optset |= PCRE2_NO_AUTO_CAPTURE; break;- case CHAR_s: *optset |= PCRE2_DOTALL; break;- case CHAR_U: *optset |= PCRE2_UNGREEDY; break;-- /* If x appears twice it sets the extended extended option. */-- case CHAR_x:- *optset |= PCRE2_EXTENDED;- if (ptr < ptrend && *ptr == CHAR_x)- {- *optset |= PCRE2_EXTENDED_MORE;- ptr++;- }- break;-- default:- errorcode = ERR11;- ptr--; /* Correct the offset */- goto FAILED;- }- }-- /* If we are setting extended without extended-more, ensure that any- existing extended-more gets unset. Also, unsetting extended must also- unset extended-more. */-- if ((set & (PCRE2_EXTENDED|PCRE2_EXTENDED_MORE)) == PCRE2_EXTENDED ||- (unset & PCRE2_EXTENDED) != 0)- unset |= PCRE2_EXTENDED_MORE;-- options = (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.- In this case, if the previous level set up a nest block, discard the- one we have just created. Otherwise adjust it for the previous level.- If the options ended with ':' we are starting a non-capturing group,- possibly with an options setting. */-- if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;- if (*ptr++ == CHAR_RIGHT_PARENTHESIS)- {- nest_depth--; /* This is not a nested group after all. */- if (top_nest > (nest_save *)(cb->start_workspace) &&- (top_nest-1)->nest_depth == nest_depth) top_nest--;- else top_nest->nest_depth = nest_depth;- }- else *parsed_pattern++ = META_NOCAPTURE;-- /* If nothing changed, no need to record. */-- if (options != oldoptions)- {- *parsed_pattern++ = META_OPTIONS;- *parsed_pattern++ = options;- }- } /* End options processing */- break; /* End default case after (? */--- /* ---- Python syntax support ---- */-- case CHAR_P:- if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;-- /* (?P<name> is the same as (?<name>, which defines a named group. */-- if (*ptr == CHAR_LESS_THAN_SIGN)- {- terminator = CHAR_GREATER_THAN_SIGN;- goto DEFINE_NAME;- }-- /* (?P>name) is the same as (?&name), which is a recursion or subroutine- call. */-- if (*ptr == CHAR_GREATER_THAN_SIGN) goto RECURSE_BY_NAME;-- /* (?P=name) is the same as \k<name>, a back reference by name. Anything- else after (?P is an error. */-- if (*ptr != CHAR_EQUALS_SIGN)- {- errorcode = ERR41;- goto FAILED;- }- if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,- &namelen, &errorcode, cb)) goto FAILED;- *parsed_pattern++ = META_BACKREF_BYNAME;- *parsed_pattern++ = namelen;- PUTOFFSET(offset, parsed_pattern);- okquantifier = TRUE;- break; /* End of (?P processing */--- /* ---- Recursion/subroutine calls by number ---- */-- case CHAR_R:- i = 0; /* (?R) == (?R0) */- ptr++;- if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)- {- errorcode = ERR58;- goto FAILED;- }- goto SET_RECURSION;-- /* An item starting (?- followed by a digit comes here via the "default"- case because (?- followed by a non-digit is an options setting. */-- case CHAR_PLUS:- if (ptrend - ptr < 2 || !IS_DIGIT(ptr[1]))- {- errorcode = ERR29; /* Missing number */- goto FAILED;- }- /* Fall through */-- case CHAR_0: case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4:- case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:- RECURSION_BYNUMBER:- if (!read_number(&ptr, ptrend,- (IS_DIGIT(*ptr))? -1:(int)(cb->bracount), /* + and - are relative */- MAX_GROUP_NUMBER, ERR61,- &i, &errorcode)) goto FAILED;- if (i < 0) /* NB (?0) is permitted */- {- errorcode = ERR15; /* Unknown group */- goto FAILED_BACK;- }- if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)- goto UNCLOSED_PARENTHESIS;-- SET_RECURSION:- *parsed_pattern++ = META_RECURSE | (uint32_t)i;- offset = (PCRE2_SIZE)(ptr - cb->start_pattern);- ptr++;- PUTOFFSET(offset, parsed_pattern);- okquantifier = TRUE;- break; /* End of recursive call by number handling */--- /* ---- Recursion/subroutine calls by name ---- */-- case CHAR_AMPERSAND:- RECURSE_BY_NAME:- if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,- &namelen, &errorcode, cb)) goto FAILED;- *parsed_pattern++ = META_RECURSE_BYNAME;- *parsed_pattern++ = namelen;- PUTOFFSET(offset, parsed_pattern);- okquantifier = TRUE;- break;-- /* ---- Callout with numerical or string argument ---- */-- case CHAR_C:- if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;-- /* If the previous item was a condition starting (?(? an assertion,- optionally preceded by a callout, is expected. This is checked later on,- during actual compilation. However we need to identify this kind of- assertion in this pass because it must not be qualified. The value of- expect_cond_assert is set to 2 after (?(? is processed. We decrement it- for a callout - still leaving a positive value that identifies the- assertion. Multiple callouts or any other items will make it zero or- less, which doesn't matter because they will cause an error later. */-- expect_cond_assert = prev_expect_cond_assert - 1;-- /* If previous_callout is not NULL, it means this follows a previous- callout. If it was a manual callout, do nothing; this means its "length- of next pattern item" field will remain zero. If it was an automatic- callout, abolish it. */-- if (previous_callout != NULL && (options & PCRE2_AUTO_CALLOUT) != 0 &&- previous_callout == parsed_pattern - 4 &&- parsed_pattern[-1] == 255)- parsed_pattern = previous_callout;-- /* Save for updating next pattern item length, and skip one item before- completing. */-- previous_callout = parsed_pattern;- after_manual_callout = 1;-- /* Handle a string argument; specific delimiter is required. */-- if (*ptr != CHAR_RIGHT_PARENTHESIS && !IS_DIGIT(*ptr))- {- PCRE2_SIZE calloutlength;- PCRE2_SPTR startptr = ptr;-- delimiter = 0;- for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)- {- if (*ptr == PRIV(callout_start_delims)[i])- {- delimiter = PRIV(callout_end_delims)[i];- break;- }- }- if (delimiter == 0)- {- errorcode = ERR82;- goto FAILED;- }-- *parsed_pattern = META_CALLOUT_STRING;- parsed_pattern += 3; /* Skip pattern info */-- for (;;)- {- if (++ptr >= ptrend)- {- errorcode = ERR81;- ptr = startptr; /* To give a more useful message */- goto FAILED;- }- if (*ptr == delimiter && (++ptr >= ptrend || *ptr != delimiter))- break;- }-- calloutlength = (PCRE2_SIZE)(ptr - startptr);- if (calloutlength > UINT32_MAX)- {- errorcode = ERR72;- goto FAILED;- }- *parsed_pattern++ = (uint32_t)calloutlength;- offset = (PCRE2_SIZE)(startptr - cb->start_pattern);- PUTOFFSET(offset, parsed_pattern);- }-- /* Handle a callout with an optional numerical argument, which must be- less than or equal to 255. A missing argument gives 0. */-- else- {- int n = 0;- *parsed_pattern = META_CALLOUT_NUMBER; /* Numerical callout */- parsed_pattern += 3; /* Skip pattern info */- while (ptr < ptrend && IS_DIGIT(*ptr))- {- n = n * 10 + *ptr++ - CHAR_0;- if (n > 255)- {- errorcode = ERR38;- goto FAILED;- }- }- *parsed_pattern++ = n;- }-- /* Both formats must have a closing parenthesis */-- if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)- {- errorcode = ERR39;- goto FAILED;- }- ptr++;-- /* Remember the offset to the next item in the pattern, and set a default- length. This should get updated after the next item is read. */-- previous_callout[1] = (uint32_t)(ptr - cb->start_pattern);- previous_callout[2] = 0;- break; /* End callout */--- /* ---- Conditional group ---- */-- /* A condition can be an assertion, a number (referring to a numbered- group's having been set), a name (referring to a named group), or 'R',- referring to overall recursion. R<digits> and R&name are also permitted- for recursion state tests. Numbers may be preceded by + or - to specify a- relative group number.-- There are several syntaxes for testing a named group: (?(name)) is used- by Python; Perl 5.10 onwards uses (?(<name>) or (?('name')).-- There are two unfortunate ambiguities. 'R' can be the recursive thing or- the name 'R' (and similarly for 'R' followed by digits). 'DEFINE' can be- the Perl DEFINE feature or the Python named test. We look for a name- first; if not found, we try the other case.-- For compatibility with auto-callouts, we allow a callout to be specified- before a condition that is an assertion. */-- case CHAR_LEFT_PARENTHESIS:- if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;- nest_depth++;-- /* If the next character is ? or * there must be an assertion next- (optionally preceded by a callout). We do not check this here, but- instead we set expect_cond_assert to 2. If this is still greater than- zero (callouts decrement it) when the next assertion is read, it will be- marked as a condition that must not be repeated. A value greater than- zero also causes checking that an assertion (possibly with callout)- follows. */-- if (*ptr == CHAR_QUESTION_MARK || *ptr == CHAR_ASTERISK)- {- *parsed_pattern++ = META_COND_ASSERT;- ptr--; /* Pull pointer back to the opening parenthesis. */- expect_cond_assert = 2;- break; /* End of conditional */- }-- /* Handle (?([+-]number)... */-- if (read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &i,- &errorcode))- {- if (i <= 0)- {- errorcode = ERR15;- goto FAILED;- }- *parsed_pattern++ = META_COND_NUMBER;- offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);- PUTOFFSET(offset, parsed_pattern);- *parsed_pattern++ = i;- }- else if (errorcode != 0) goto FAILED; /* Number too big */-- /* No number found. Handle the special case (?(VERSION[>]=n.m)... */-- else if (ptrend - ptr >= 10 &&- PRIV(strncmp_c8)(ptr, STRING_VERSION, 7) == 0 &&- ptr[7] != CHAR_RIGHT_PARENTHESIS)- {- uint32_t ge = 0;- int major = 0;- int minor = 0;-- ptr += 7;- if (*ptr == CHAR_GREATER_THAN_SIGN)- {- ge = 1;- ptr++;- }-- /* NOTE: cannot write IS_DIGIT(*(++ptr)) here because IS_DIGIT- references its argument twice. */-- if (*ptr != CHAR_EQUALS_SIGN || (ptr++, !IS_DIGIT(*ptr)))- goto BAD_VERSION_CONDITION;-- if (!read_number(&ptr, ptrend, -1, 1000, ERR79, &major, &errorcode))- goto FAILED;-- if (ptr >= ptrend) goto BAD_VERSION_CONDITION;- if (*ptr == CHAR_DOT)- {- if (++ptr >= ptrend || !IS_DIGIT(*ptr)) goto BAD_VERSION_CONDITION;- minor = (*ptr++ - CHAR_0) * 10;- if (ptr >= ptrend) goto BAD_VERSION_CONDITION;- if (IS_DIGIT(*ptr)) minor += *ptr++ - CHAR_0;- if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)- goto BAD_VERSION_CONDITION;- }-- *parsed_pattern++ = META_COND_VERSION;- *parsed_pattern++ = ge;- *parsed_pattern++ = major;- *parsed_pattern++ = minor;- }-- /* All the remaining cases now require us to read a name. We cannot at- this stage distinguish ambiguous cases such as (?(R12) which might be a- recursion test by number or a name, because the named groups have not yet- all been identified. Those cases are treated as names, but given a- different META code. */-- else- {- BOOL was_r_ampersand = FALSE;-- if (*ptr == CHAR_R && ptrend - ptr > 1 && ptr[1] == CHAR_AMPERSAND)- {- terminator = CHAR_RIGHT_PARENTHESIS;- was_r_ampersand = TRUE;- ptr++;- }- else if (*ptr == CHAR_LESS_THAN_SIGN)- terminator = CHAR_GREATER_THAN_SIGN;- else if (*ptr == CHAR_APOSTROPHE)- terminator = CHAR_APOSTROPHE;- else- {- terminator = CHAR_RIGHT_PARENTHESIS;- ptr--; /* Point to char before name */- }- if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,- &errorcode, cb)) goto FAILED;-- /* Handle (?(R&name) */-- if (was_r_ampersand)- {- *parsed_pattern = META_COND_RNAME;- ptr--; /* Back to closing parens */- }-- /* Handle (?(name). If the name is "DEFINE" we identify it with a- special code. Likewise if the name consists of R followed only by- digits. Otherwise, handle it like a quoted name. */-- else if (terminator == CHAR_RIGHT_PARENTHESIS)- {- if (namelen == 6 && PRIV(strncmp_c8)(name, STRING_DEFINE, 6) == 0)- *parsed_pattern = META_COND_DEFINE;- else- {- for (i = 1; i < (int)namelen; i++)- if (!IS_DIGIT(name[i])) break;- *parsed_pattern = (*name == CHAR_R && i >= (int)namelen)?- META_COND_RNUMBER : META_COND_NAME;- }- ptr--; /* Back to closing parens */- }-- /* Handle (?('name') or (?(<name>) */-- else *parsed_pattern = META_COND_NAME;-- /* All these cases except DEFINE end with the name length and offset;- DEFINE just has an offset (for the "too many branches" error). */-- if (*parsed_pattern++ != META_COND_DEFINE) *parsed_pattern++ = namelen;- PUTOFFSET(offset, parsed_pattern);- } /* End cases that read a name */-- /* Check the closing parenthesis of the condition */-- if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)- {- errorcode = ERR24;- goto FAILED;- }- ptr++;- break; /* End of condition processing */--- /* ---- Atomic group ---- */-- case CHAR_GREATER_THAN_SIGN:- ATOMIC_GROUP: /* Come from (*atomic: */- *parsed_pattern++ = META_ATOMIC;- nest_depth++;- ptr++;- break;--- /* ---- Lookahead assertions ---- */-- case CHAR_EQUALS_SIGN:- POSITIVE_LOOK_AHEAD: /* Come from (*pla: */- *parsed_pattern++ = META_LOOKAHEAD;- ptr++;- goto POST_ASSERTION;-- case CHAR_ASTERISK:- POSITIVE_NONATOMIC_LOOK_AHEAD: /* Come from (?* */- *parsed_pattern++ = META_LOOKAHEAD_NA;- ptr++;- goto POST_ASSERTION;-- case CHAR_EXCLAMATION_MARK:- NEGATIVE_LOOK_AHEAD: /* Come from (*nla: */- *parsed_pattern++ = META_LOOKAHEADNOT;- ptr++;- goto POST_ASSERTION;--- /* ---- Lookbehind assertions ---- */-- /* (?< followed by = or ! or * is a lookbehind assertion. Otherwise (?<- is the start of the name of a capturing group. */-- case CHAR_LESS_THAN_SIGN:- if (ptrend - ptr <= 1 ||- (ptr[1] != CHAR_EQUALS_SIGN &&- ptr[1] != CHAR_EXCLAMATION_MARK &&- ptr[1] != CHAR_ASTERISK))- {- terminator = CHAR_GREATER_THAN_SIGN;- goto DEFINE_NAME;- }- *parsed_pattern++ = (ptr[1] == CHAR_EQUALS_SIGN)?- META_LOOKBEHIND : (ptr[1] == CHAR_EXCLAMATION_MARK)?- META_LOOKBEHINDNOT : META_LOOKBEHIND_NA;-- POST_LOOKBEHIND: /* Come from (*plb: (*naplb: and (*nlb: */- *has_lookbehind = TRUE;- offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);- PUTOFFSET(offset, parsed_pattern);- ptr += 2;- /* Fall through */-- /* If the previous item was a condition starting (?(? an assertion,- optionally preceded by a callout, is expected. This is checked later on,- during actual compilation. However we need to identify this kind of- assertion in this pass because it must not be qualified. The value of- expect_cond_assert is set to 2 after (?(? is processed. We decrement it- for a callout - still leaving a positive value that identifies the- assertion. Multiple callouts or any other items will make it zero or- less, which doesn't matter because they will cause an error later. */-- POST_ASSERTION:- nest_depth++;- if (prev_expect_cond_assert > 0)- {- if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);- else if (++top_nest >= end_nests)- {- errorcode = ERR84;- goto FAILED;- }- top_nest->nest_depth = nest_depth;- top_nest->flags = NSF_CONDASSERT;- top_nest->options = options & PARSE_TRACKED_OPTIONS;- }- break;--- /* ---- Define a named group ---- */-- /* A named group may be defined as (?'name') or (?<name>). In the latter- case we jump to DEFINE_NAME from the disambiguation of (?< above with the- terminator set to '>'. */-- case CHAR_APOSTROPHE:- terminator = CHAR_APOSTROPHE; /* Terminator */-- DEFINE_NAME:- if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,- &errorcode, cb)) goto FAILED;-- /* We have a name for this capturing group. It is also assigned a number,- which is its primary means of identification. */-- if (cb->bracount >= MAX_GROUP_NUMBER)- {- errorcode = ERR97;- goto FAILED;- }- cb->bracount++;- *parsed_pattern++ = META_CAPTURE | cb->bracount;- nest_depth++;-- /* Check not too many names */-- if (cb->names_found >= MAX_NAME_COUNT)- {- errorcode = ERR49;- goto FAILED;- }-- /* Adjust the entry size to accommodate the longest name found. */-- if (namelen + IMM2_SIZE + 1 > cb->name_entry_size)- cb->name_entry_size = (uint16_t)(namelen + IMM2_SIZE + 1);-- /* Scan the list to check for duplicates. For duplicate names, if the- number is the same, break the loop, which causes the name to be- discarded; otherwise, if DUPNAMES is not set, give an error.- If it is set, allow the name with a different number, but continue- scanning in case this is a duplicate with the same number. For- non-duplicate names, give an error if the number is duplicated. */-- isdupname = FALSE;- ng = cb->named_groups;- for (i = 0; i < cb->names_found; i++, ng++)- {- if (namelen == ng->length &&- PRIV(strncmp)(name, ng->name, (PCRE2_SIZE)namelen) == 0)- {- if (ng->number == cb->bracount) break;- if ((options & PCRE2_DUPNAMES) == 0)- {- errorcode = ERR43;- goto FAILED;- }- isdupname = ng->isdup = TRUE; /* Mark as a duplicate */- cb->dupnames = TRUE; /* Duplicate names exist */- }- else if (ng->number == cb->bracount)- {- errorcode = ERR65;- goto FAILED;- }- }-- if (i < cb->names_found) break; /* Ignore duplicate with same number */-- /* Increase the list size if necessary */-- if (cb->names_found >= cb->named_group_list_size)- {- uint32_t newsize = cb->named_group_list_size * 2;- named_group *newspace =- cb->cx->memctl.malloc(newsize * sizeof(named_group),- cb->cx->memctl.memory_data);- if (newspace == NULL)- {- errorcode = ERR21;- goto FAILED;- }-- memcpy(newspace, cb->named_groups,- cb->named_group_list_size * sizeof(named_group));- if (cb->named_group_list_size > NAMED_GROUP_LIST_SIZE)- cb->cx->memctl.free((void *)cb->named_groups,- cb->cx->memctl.memory_data);- cb->named_groups = newspace;- cb->named_group_list_size = newsize;- }-- /* Add this name to the list */-- cb->named_groups[cb->names_found].name = name;- cb->named_groups[cb->names_found].length = (uint16_t)namelen;- cb->named_groups[cb->names_found].number = cb->bracount;- cb->named_groups[cb->names_found].isdup = (uint16_t)isdupname;- cb->names_found++;- break;- } /* End of (? switch */- break; /* End of ( handling */--- /* ---- Branch terminators ---- */-- /* Alternation: reset the capture count if we are in a (?| group. */-- case CHAR_VERTICAL_LINE:- if (top_nest != NULL && top_nest->nest_depth == nest_depth &&- (top_nest->flags & NSF_RESET) != 0)- {- if (cb->bracount > top_nest->max_group)- top_nest->max_group = (uint16_t)cb->bracount;- cb->bracount = top_nest->reset_group;- }- *parsed_pattern++ = META_ALT;- break;-- /* End of group; reset the capture count to the maximum if we are in a (?|- group and/or reset the options that are tracked during parsing. Disallow- quantifier for a condition that is an assertion. */-- case CHAR_RIGHT_PARENTHESIS:- okquantifier = TRUE;- if (top_nest != NULL && top_nest->nest_depth == nest_depth)- {- options = (options & ~PARSE_TRACKED_OPTIONS) | top_nest->options;- if ((top_nest->flags & NSF_RESET) != 0 &&- top_nest->max_group > cb->bracount)- cb->bracount = top_nest->max_group;- if ((top_nest->flags & NSF_CONDASSERT) != 0)- okquantifier = FALSE;-- if ((top_nest->flags & NSF_ATOMICSR) != 0)- {- *parsed_pattern++ = META_KET;- }-- if (top_nest == (nest_save *)(cb->start_workspace)) top_nest = NULL;- else top_nest--;- }- if (nest_depth == 0) /* Unmatched closing parenthesis */- {- errorcode = ERR22;- goto FAILED_BACK;- }- nest_depth--;- *parsed_pattern++ = META_KET;- break;- } /* End of switch on pattern character */- } /* End of main character scan loop */--/* End of pattern reached. Check for missing ) at the end of a verb name. */--if (inverbname && ptr >= ptrend)- {- errorcode = ERR60;- goto FAILED;- }--/* Manage callout for the final item */--PARSED_END:-parsed_pattern = manage_callouts(ptr, &previous_callout, auto_callout,- parsed_pattern, cb);--/* Insert trailing items for word and line matching (features provided for the-benefit of pcre2grep). */--if ((extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)- {- *parsed_pattern++ = META_KET;- *parsed_pattern++ = META_DOLLAR;- }-else if ((extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)- {- *parsed_pattern++ = META_KET;- *parsed_pattern++ = META_ESCAPE + ESC_b;- }--/* Terminate the parsed pattern, then return success if all groups are closed.-Otherwise we have unclosed parentheses. */--if (parsed_pattern >= parsed_pattern_end)- {- errorcode = ERR63; /* Internal error (parsed pattern overflow) */- goto FAILED;- }--*parsed_pattern = META_END;-if (nest_depth == 0) return 0;--UNCLOSED_PARENTHESIS:-errorcode = ERR14;--/* Come here for all failures. */--FAILED:-cb->erroroffset = (PCRE2_SIZE)(ptr - cb->start_pattern);-return errorcode;--/* Some errors need to indicate the previous character. */--FAILED_BACK:-ptr--;-goto FAILED;--/* This failure happens several times. */--BAD_VERSION_CONDITION:-errorcode = ERR79;-goto FAILED;-}----/*************************************************-* Find first significant opcode *-*************************************************/--/* This is called by several functions that scan a compiled expression looking-for a fixed first character, or an anchoring opcode etc. It skips over things-that do not influence this. For some calls, it makes sense to skip negative-forward and all backward assertions, and also the \b assertion; for others it-does not.--Arguments:- code pointer to the start of the group- skipassert TRUE if certain assertions are to be skipped--Returns: pointer to the first significant opcode-*/--static const PCRE2_UCHAR*-first_significant_code(PCRE2_SPTR code, BOOL skipassert)-{-for (;;)- {- switch ((int)*code)- {- case OP_ASSERT_NOT:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT:- case OP_ASSERTBACK_NA:- if (!skipassert) return code;- do code += GET(code, 1); while (*code == OP_ALT);- code += PRIV(OP_lengths)[*code];- break;-- case OP_WORD_BOUNDARY:- case OP_NOT_WORD_BOUNDARY:- if (!skipassert) return code;- /* Fall through */-- case OP_CALLOUT:- case OP_CREF:- case OP_DNCREF:- case OP_RREF:- case OP_DNRREF:- case OP_FALSE:- case OP_TRUE:- code += PRIV(OP_lengths)[*code];- break;-- case OP_CALLOUT_STR:- code += GET(code, 1 + 2*LINK_SIZE);- break;-- case OP_SKIPZERO:- code += 2 + GET(code, 2) + LINK_SIZE;- break;-- case OP_COND:- case OP_SCOND:- if (code[1+LINK_SIZE] != OP_FALSE || /* Not DEFINE */- code[GET(code, 1)] != OP_KET) /* More than one branch */- return code;- code += GET(code, 1) + 1 + LINK_SIZE;- break;-- case OP_MARK:- case OP_COMMIT_ARG:- case OP_PRUNE_ARG:- case OP_SKIP_ARG:- case OP_THEN_ARG:- code += code[1] + PRIV(OP_lengths)[*code];- break;-- default:- return code;- }- }-/* Control never reaches here */-}----#ifdef SUPPORT_UNICODE-/*************************************************-* Get othercase range *-*************************************************/--/* This function is passed the start and end of a class range in UCP mode. It-searches up the characters, looking for ranges of characters in the "other"-case. Each call returns the next one, updating the start address. A character-with multiple other cases is returned on its own with a special return value.--Arguments:- cptr points to starting character value; updated- d end value- ocptr where to put start of othercase range- odptr where to put end of othercase range--Yield: -1 when no more- 0 when a range is returned- >0 the CASESET offset for char with multiple other cases- in this case, ocptr contains the original-*/--static int-get_othercase_range(uint32_t *cptr, uint32_t d, uint32_t *ocptr,- uint32_t *odptr)-{-uint32_t c, othercase, next;-unsigned int co;--/* Find the first character that has an other case. If it has multiple other-cases, return its case offset value. */--for (c = *cptr; c <= d; c++)- {- if ((co = UCD_CASESET(c)) != 0)- {- *ocptr = c++; /* Character that has the set */- *cptr = c; /* Rest of input range */- return (int)co;- }- if ((othercase = UCD_OTHERCASE(c)) != c) break;- }--if (c > d) return -1; /* Reached end of range */--/* Found a character that has a single other case. Search for the end of the-range, which is either the end of the input range, or a character that has zero-or more than one other cases. */--*ocptr = othercase;-next = othercase + 1;--for (++c; c <= d; c++)- {- if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break;- next++;- }--*odptr = next - 1; /* End of othercase range */-*cptr = c; /* Rest of input range */-return 0;-}-#endif /* SUPPORT_UNICODE */----/*************************************************-* Add a character or range to a class (internal) *-*************************************************/--/* This function packages up the logic of adding a character or range of-characters to a class. The character values in the arguments will be within the-valid values for the current mode (8-bit, 16-bit, UTF, etc). This function is-called only from within the "add to class" group of functions, some of which-are recursive and mutually recursive. The external entry point is-add_to_class().--Arguments:- classbits the bit map for characters < 256- uchardptr points to the pointer for extra data- options the options word- cb compile data- start start of range character- end end of range character--Returns: the number of < 256 characters added- the pointer to extra data is updated-*/--static unsigned int-add_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr,- uint32_t options, compile_block *cb, uint32_t start, uint32_t end)-{-uint32_t c;-uint32_t classbits_end = (end <= 0xff ? end : 0xff);-unsigned int n8 = 0;--/* If caseless matching is required, scan the range and process alternate-cases. In Unicode, there are 8-bit characters that have alternate cases that-are greater than 255 and vice-versa. Sometimes we can just extend the original-range. */--if ((options & PCRE2_CASELESS) != 0)- {-#ifdef SUPPORT_UNICODE- if ((options & (PCRE2_UTF|PCRE2_UCP)) != 0)- {- int rc;- uint32_t oc, od;-- options &= ~PCRE2_CASELESS; /* Remove for recursive calls */- c = start;-- while ((rc = get_othercase_range(&c, end, &oc, &od)) >= 0)- {- /* Handle a single character that has more than one other case. */-- if (rc > 0) n8 += add_list_to_class_internal(classbits, uchardptr, options, cb,- PRIV(ucd_caseless_sets) + rc, oc);-- /* Do nothing if the other case range is within the original range. */-- else if (oc >= cb->class_range_start && od <= cb->class_range_end) continue;-- /* Extend the original range if there is overlap, noting that if oc < c, we- can't have od > end because a subrange is always shorter than the basic- range. Otherwise, use a recursive call to add the additional range. */-- else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */- else if (od > end && oc <= end + 1)- {- end = od; /* Extend upwards */- if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff);- }- else n8 += add_to_class_internal(classbits, uchardptr, options, cb, oc, od);- }- }- else-#endif /* SUPPORT_UNICODE */-- /* Not UTF mode */-- for (c = start; c <= classbits_end; c++)- {- SETBIT(classbits, cb->fcc[c]);- n8++;- }- }--/* Now handle the originally supplied range. Adjust the final value according-to the bit length - this means that the same lists of (e.g.) horizontal spaces-can be used in all cases. */--if ((options & PCRE2_UTF) == 0 && end > MAX_NON_UTF_CHAR)- end = MAX_NON_UTF_CHAR;--if (start > cb->class_range_start && end < cb->class_range_end) return n8;--/* Use the bitmap for characters < 256. Otherwise use extra data.*/--for (c = start; c <= classbits_end; c++)- {- /* Regardless of start, c will always be <= 255. */- SETBIT(classbits, c);- n8++;- }--#ifdef SUPPORT_WIDE_CHARS-if (start <= 0xff) start = 0xff + 1;--if (end >= start)- {- PCRE2_UCHAR *uchardata = *uchardptr;--#ifdef SUPPORT_UNICODE- if ((options & PCRE2_UTF) != 0)- {- if (start < end)- {- *uchardata++ = XCL_RANGE;- uchardata += PRIV(ord2utf)(start, uchardata);- uchardata += PRIV(ord2utf)(end, uchardata);- }- else if (start == end)- {- *uchardata++ = XCL_SINGLE;- uchardata += PRIV(ord2utf)(start, uchardata);- }- }- else-#endif /* SUPPORT_UNICODE */-- /* Without UTF support, character values are constrained by the bit length,- and can only be > 256 for 16-bit and 32-bit libraries. */--#if PCRE2_CODE_UNIT_WIDTH == 8- {}-#else- if (start < end)- {- *uchardata++ = XCL_RANGE;- *uchardata++ = start;- *uchardata++ = end;- }- else if (start == end)- {- *uchardata++ = XCL_SINGLE;- *uchardata++ = start;- }-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */- *uchardptr = uchardata; /* Updata extra data pointer */- }-#else /* SUPPORT_WIDE_CHARS */- (void)uchardptr; /* Avoid compiler warning */-#endif /* SUPPORT_WIDE_CHARS */--return n8; /* Number of 8-bit characters */-}----#ifdef SUPPORT_UNICODE-/*************************************************-* Add a list of characters to a class (internal) *-*************************************************/--/* This function is used for adding a list of case-equivalent characters to a-class when in UTF mode. This function is called only from within-add_to_class_internal(), with which it is mutually recursive.--Arguments:- classbits the bit map for characters < 256- uchardptr points to the pointer for extra data- options the options word- cb contains pointers to tables etc.- p points to row of 32-bit values, terminated by NOTACHAR- except character to omit; this is used when adding lists of- case-equivalent characters to avoid including the one we- already know about--Returns: the number of < 256 characters added- the pointer to extra data is updated-*/--static unsigned int-add_list_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr,- uint32_t options, compile_block *cb, const uint32_t *p, unsigned int except)-{-unsigned int n8 = 0;-while (p[0] < NOTACHAR)- {- unsigned int n = 0;- if (p[0] != except)- {- while(p[n+1] == p[0] + n + 1) n++;- n8 += add_to_class_internal(classbits, uchardptr, options, cb, p[0], p[n]);- }- p += n + 1;- }-return n8;-}-#endif----/*************************************************-* External entry point for add range to class *-*************************************************/--/* This function sets the overall range so that the internal functions can try-to avoid duplication when handling case-independence.--Arguments:- classbits the bit map for characters < 256- uchardptr points to the pointer for extra data- options the options word- cb compile data- start start of range character- end end of range character--Returns: the number of < 256 characters added- the pointer to extra data is updated-*/--static unsigned int-add_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,- compile_block *cb, uint32_t start, uint32_t end)-{-cb->class_range_start = start;-cb->class_range_end = end;-return add_to_class_internal(classbits, uchardptr, options, cb, start, end);-}---/*************************************************-* External entry point for add list to class *-*************************************************/--/* This function is used for adding a list of horizontal or vertical whitespace-characters to a class. The list must be in order so that ranges of characters-can be detected and handled appropriately. This function sets the overall range-so that the internal functions can try to avoid duplication when handling-case-independence.--Arguments:- classbits the bit map for characters < 256- uchardptr points to the pointer for extra data- options the options word- cb contains pointers to tables etc.- p points to row of 32-bit values, terminated by NOTACHAR- except character to omit; this is used when adding lists of- case-equivalent characters to avoid including the one we- already know about--Returns: the number of < 256 characters added- the pointer to extra data is updated-*/--static unsigned int-add_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,- compile_block *cb, const uint32_t *p, unsigned int except)-{-unsigned int n8 = 0;-while (p[0] < NOTACHAR)- {- unsigned int n = 0;- if (p[0] != except)- {- while(p[n+1] == p[0] + n + 1) n++;- cb->class_range_start = p[0];- cb->class_range_end = p[n];- n8 += add_to_class_internal(classbits, uchardptr, options, cb, p[0], p[n]);- }- p += n + 1;- }-return n8;-}----/*************************************************-* Add characters not in a list to a class *-*************************************************/--/* This function is used for adding the complement of a list of horizontal or-vertical whitespace to a class. The list must be in order.--Arguments:- classbits the bit map for characters < 256- uchardptr points to the pointer for extra data- options the options word- cb contains pointers to tables etc.- p points to row of 32-bit values, terminated by NOTACHAR--Returns: the number of < 256 characters added- the pointer to extra data is updated-*/--static unsigned int-add_not_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr,- uint32_t options, compile_block *cb, const uint32_t *p)-{-BOOL utf = (options & PCRE2_UTF) != 0;-unsigned int n8 = 0;-if (p[0] > 0)- n8 += add_to_class(classbits, uchardptr, options, cb, 0, p[0] - 1);-while (p[0] < NOTACHAR)- {- while (p[1] == p[0] + 1) p++;- n8 += add_to_class(classbits, uchardptr, options, cb, p[0] + 1,- (p[1] == NOTACHAR) ? (utf ? 0x10ffffu : 0xffffffffu) : p[1] - 1);- p++;- }-return n8;-}----/*************************************************-* Find details of duplicate group names *-*************************************************/--/* This is called from compile_branch() when it needs to know the index and-count of duplicates in the names table when processing named backreferences,-either directly, or as conditions.--Arguments:- name points to the name- length the length of the name- indexptr where to put the index- countptr where to put the count of duplicates- errorcodeptr where to put an error code- cb the compile block--Returns: TRUE if OK, FALSE if not, error code set-*/--static BOOL-find_dupname_details(PCRE2_SPTR name, uint32_t length, int *indexptr,- int *countptr, int *errorcodeptr, compile_block *cb)-{-uint32_t i, groupnumber;-int count;-PCRE2_UCHAR *slot = cb->name_table;--/* Find the first entry in the table */--for (i = 0; i < cb->names_found; i++)- {- if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) == 0 &&- slot[IMM2_SIZE+length] == 0) break;- slot += cb->name_entry_size;- }--/* This should not occur, because this function is called only when we know we-have duplicate names. Give an internal error. */--if (i >= cb->names_found)- {- *errorcodeptr = ERR53;- cb->erroroffset = name - cb->start_pattern;- return FALSE;- }--/* Record the index and then see how many duplicates there are, updating the-backref map and maximum back reference as we do. */--*indexptr = i;-count = 0;--for (;;)- {- count++;- groupnumber = GET2(slot,0);- cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;- if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;- if (++i >= cb->names_found) break;- slot += cb->name_entry_size;- if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) != 0 ||- (slot+IMM2_SIZE)[length] != 0) break;- }--*countptr = count;-return TRUE;-}----/*************************************************-* Compile one branch *-*************************************************/--/* Scan the parsed pattern, compiling it into the a vector of PCRE2_UCHAR. If-the options are changed during the branch, the pointer is used to change the-external options bits. This function is used during the pre-compile phase when-we are trying to find out the amount of memory needed, as well as during the-real compile phase. The value of lengthptr distinguishes the two phases.--Arguments:- optionsptr pointer to the option bits- codeptr points to the pointer to the current code point- pptrptr points to the current parsed pattern pointer- errorcodeptr points to error code variable- firstcuptr place to put the first required code unit- firstcuflagsptr place to put the first code unit flags- reqcuptr place to put the last required code unit- reqcuflagsptr place to put the last required code unit flags- bcptr points to current branch chain- cb contains pointers to tables etc.- lengthptr NULL during the real compile phase- points to length accumulator during pre-compile phase--Returns: 0 There's been an error, *errorcodeptr is non-zero- +1 Success, this branch must match at least one character- -1 Success, this branch may match an empty string-*/--static int-compile_branch(uint32_t *optionsptr, PCRE2_UCHAR **codeptr, uint32_t **pptrptr,- int *errorcodeptr, uint32_t *firstcuptr, uint32_t *firstcuflagsptr,- uint32_t *reqcuptr, uint32_t *reqcuflagsptr, branch_chain *bcptr,- compile_block *cb, PCRE2_SIZE *lengthptr)-{-int bravalue = 0;-int okreturn = -1;-int group_return = 0;-uint32_t repeat_min = 0, repeat_max = 0; /* To please picky compilers */-uint32_t greedy_default, greedy_non_default;-uint32_t repeat_type, op_type;-uint32_t options = *optionsptr; /* May change dynamically */-uint32_t firstcu, reqcu;-uint32_t zeroreqcu, zerofirstcu;-uint32_t escape;-uint32_t *pptr = *pptrptr;-uint32_t meta, meta_arg;-uint32_t firstcuflags, reqcuflags;-uint32_t zeroreqcuflags, zerofirstcuflags;-uint32_t req_caseopt, reqvary, tempreqvary;-PCRE2_SIZE offset = 0;-PCRE2_SIZE length_prevgroup = 0;-PCRE2_UCHAR *code = *codeptr;-PCRE2_UCHAR *last_code = code;-PCRE2_UCHAR *orig_code = code;-PCRE2_UCHAR *tempcode;-PCRE2_UCHAR *previous = NULL;-PCRE2_UCHAR op_previous;-BOOL groupsetfirstcu = FALSE;-BOOL had_accept = FALSE;-BOOL matched_char = FALSE;-BOOL previous_matched_char = FALSE;-BOOL reset_caseful = FALSE;-const uint8_t *cbits = cb->cbits;-uint8_t classbits[32];--/* We can fish out the UTF setting once and for all into a BOOL, but we must-not do this for other options (e.g. PCRE2_EXTENDED) because they may change-dynamically as we process the pattern. */--#ifdef SUPPORT_UNICODE-BOOL utf = (options & PCRE2_UTF) != 0;-BOOL ucp = (options & PCRE2_UCP) != 0;-#else /* No Unicode support */-BOOL utf = FALSE;-#endif--/* Helper variables for OP_XCLASS opcode (for characters > 255). We define-class_uchardata always so that it can be passed to add_to_class() always,-though it will not be used in non-UTF 8-bit cases. This avoids having to supply-alternative calls for the different cases. */--PCRE2_UCHAR *class_uchardata;-#ifdef SUPPORT_WIDE_CHARS-BOOL xclass;-PCRE2_UCHAR *class_uchardata_base;-#endif--/* Set up the default and non-default settings for greediness */--greedy_default = ((options & PCRE2_UNGREEDY) != 0);-greedy_non_default = greedy_default ^ 1;--/* Initialize no first unit, no required unit. REQ_UNSET means "no char-matching encountered yet". It gets changed to REQ_NONE if we hit something that-matches a non-fixed first unit; reqcu just remains unset if we never find one.--When we hit a repeat whose minimum is zero, we may have to adjust these values-to take the zero repeat into account. This is implemented by setting them to-zerofirstcu and zeroreqcu when such a repeat is encountered. The individual-item types that can be repeated set these backoff variables appropriately. */--firstcu = reqcu = zerofirstcu = zeroreqcu = 0;-firstcuflags = reqcuflags = zerofirstcuflags = zeroreqcuflags = REQ_UNSET;--/* The variable req_caseopt contains either the REQ_CASELESS bit or zero,-according to the current setting of the caseless flag. The REQ_CASELESS value-leaves the lower 28 bit empty. It is added into the firstcu or reqcu variables-to record the case status of the value. This is used only for ASCII characters.-*/--req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0;--/* Switch on next META item until the end of the branch */--for (;; pptr++)- {-#ifdef SUPPORT_WIDE_CHARS- BOOL xclass_has_prop;-#endif- BOOL negate_class;- BOOL should_flip_negation;- BOOL match_all_or_no_wide_chars;- BOOL possessive_quantifier;- BOOL note_group_empty;- int class_has_8bitchar;- uint32_t mclength;- uint32_t skipunits;- uint32_t subreqcu, subfirstcu;- uint32_t groupnumber;- uint32_t verbarglen, verbculen;- uint32_t subreqcuflags, subfirstcuflags;- open_capitem *oc;- PCRE2_UCHAR mcbuffer[8];-- /* Get next META item in the pattern and its potential argument. */-- meta = META_CODE(*pptr);- meta_arg = META_DATA(*pptr);-- /* If we are in the pre-compile phase, accumulate the length used for the- previous cycle of this loop, unless the next item is a quantifier. */-- if (lengthptr != NULL)- {- if (code > cb->start_workspace + cb->workspace_size -- WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */- {- *errorcodeptr = (code >= cb->start_workspace + cb->workspace_size)?- ERR52 : ERR86;- return 0;- }-- /* There is at least one situation where code goes backwards: this is the- case of a zero quantifier after a class (e.g. [ab]{0}). When the quantifier- is processed, the whole class is eliminated. However, it is created first,- so we have to allow memory for it. Therefore, don't ever reduce the length- at this point. */-- if (code < last_code) code = last_code;-- /* If the next thing is not a quantifier, we add the length of the previous- item into the total, and reset the code pointer to the start of the- workspace. Otherwise leave the previous item available to be quantified. */-- if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)- {- if (OFLOW_MAX - *lengthptr < (PCRE2_SIZE)(code - orig_code))- {- *errorcodeptr = ERR20; /* Integer overflow */- return 0;- }- *lengthptr += (PCRE2_SIZE)(code - orig_code);- if (*lengthptr > MAX_PATTERN_SIZE)- {- *errorcodeptr = ERR20; /* Pattern is too large */- return 0;- }- code = orig_code;- }-- /* Remember where this code item starts so we can catch the "backwards"- case above next time round. */-- last_code = code;- }-- /* Process the next parsed pattern item. If it is not a quantifier, remember- where it starts so that it can be quantified when a quantifier follows.- Checking for the legality of quantifiers happens in parse_regex(), except for- a quantifier after an assertion that is a condition. */-- if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)- {- previous = code;- if (matched_char && !had_accept) okreturn = 1;- }-- previous_matched_char = matched_char;- matched_char = FALSE;- note_group_empty = FALSE;- skipunits = 0; /* Default value for most subgroups */-- switch(meta)- {- /* ===================================================================*/- /* The branch terminates at pattern end or | or ) */-- case META_END:- case META_ALT:- case META_KET:- *firstcuptr = firstcu;- *firstcuflagsptr = firstcuflags;- *reqcuptr = reqcu;- *reqcuflagsptr = reqcuflags;- *codeptr = code;- *pptrptr = pptr;- return okreturn;--- /* ===================================================================*/- /* Handle single-character metacharacters. In multiline mode, ^ disables- the setting of any following char as a first character. */-- case META_CIRCUMFLEX:- if ((options & PCRE2_MULTILINE) != 0)- {- if (firstcuflags == REQ_UNSET)- zerofirstcuflags = firstcuflags = REQ_NONE;- *code++ = OP_CIRCM;- }- else *code++ = OP_CIRC;- break;-- case META_DOLLAR:- *code++ = ((options & PCRE2_MULTILINE) != 0)? OP_DOLLM : OP_DOLL;- break;-- /* There can never be a first char if '.' is first, whatever happens about- repeats. The value of reqcu doesn't change either. */-- case META_DOT:- matched_char = TRUE;- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;- zerofirstcu = firstcu;- zerofirstcuflags = firstcuflags;- zeroreqcu = reqcu;- zeroreqcuflags = reqcuflags;- *code++ = ((options & PCRE2_DOTALL) != 0)? OP_ALLANY: OP_ANY;- break;--- /* ===================================================================*/- /* Empty character classes are allowed if PCRE2_ALLOW_EMPTY_CLASS is set.- Otherwise, an initial ']' is taken as a data character. When empty classes- are allowed, [] must always fail, so generate OP_FAIL, whereas [^] must- match any character, so generate OP_ALLANY. */-- case META_CLASS_EMPTY:- case META_CLASS_EMPTY_NOT:- matched_char = TRUE;- *code++ = (meta == META_CLASS_EMPTY_NOT)? OP_ALLANY : OP_FAIL;- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;- zerofirstcu = firstcu;- zerofirstcuflags = firstcuflags;- break;--- /* ===================================================================*/- /* Non-empty character class. If the included characters are all < 256, we- build a 32-byte bitmap of the permitted characters, except in the special- case where there is only one such character. For negated classes, we build- the map as usual, then invert it at the end. However, we use a different- opcode so that data characters > 255 can be handled correctly.-- If the class contains characters outside the 0-255 range, a different- opcode is compiled. It may optionally have a bit map for characters < 256,- but those above are are explicitly listed afterwards. A flag code unit- tells whether the bitmap is present, and whether this is a negated class or- not. */-- case META_CLASS_NOT:- case META_CLASS:- matched_char = TRUE;- negate_class = meta == META_CLASS_NOT;-- /* We can optimize the case of a single character in a class by generating- OP_CHAR or OP_CHARI if it's positive, or OP_NOT or OP_NOTI if it's- negative. In the negative case there can be no first char if this item is- first, whatever repeat count may follow. In the case of reqcu, save the- previous value for reinstating. */-- /* NOTE: at present this optimization is not effective if the only- character in a class in 32-bit, non-UCP mode has its top bit set. */-- if (pptr[1] < META_END && pptr[2] == META_CLASS_END)- {-#ifdef SUPPORT_UNICODE- uint32_t d;-#endif- uint32_t c = pptr[1];-- pptr += 2; /* Move on to class end */- if (meta == META_CLASS) /* A positive one-char class can be */- { /* handled as a normal literal character. */- meta = c; /* Set up the character */- goto NORMAL_CHAR_SET;- }-- /* Handle a negative one-character class */-- zeroreqcu = reqcu;- zeroreqcuflags = reqcuflags;- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;- zerofirstcu = firstcu;- zerofirstcuflags = firstcuflags;-- /* For caseless UTF or UCP mode, check whether this character has more- than one other case. If so, generate a special OP_NOTPROP item instead of- OP_NOTI. */--#ifdef SUPPORT_UNICODE- if ((utf||ucp) && (options & PCRE2_CASELESS) != 0 &&- (d = UCD_CASESET(c)) != 0)- {- *code++ = OP_NOTPROP;- *code++ = PT_CLIST;- *code++ = d;- break; /* We are finished with this class */- }-#endif- /* Char has only one other case, or UCP not available */-- *code++ = ((options & PCRE2_CASELESS) != 0)? OP_NOTI: OP_NOT;- code += PUTCHAR(c, code);- break; /* We are finished with this class */- } /* End of 1-char optimization */-- /* Handle character classes that contain more than just one literal- character. If there are exactly two characters in a positive class, see if- they are case partners. This can be optimized to generate a caseless single- character match (which also sets first/required code units if relevant). */-- if (meta == META_CLASS && pptr[1] < META_END && pptr[2] < META_END &&- pptr[3] == META_CLASS_END)- {- uint32_t c = pptr[1];--#ifdef SUPPORT_UNICODE- if (UCD_CASESET(c) == 0)-#endif- {- uint32_t d;--#ifdef SUPPORT_UNICODE- if ((utf || ucp) && c > 127) d = UCD_OTHERCASE(c); else-#endif- {-#if PCRE2_CODE_UNIT_WIDTH != 8- if (c > 255) d = c; else-#endif- d = TABLE_GET(c, cb->fcc, c);- }-- if (c != d && pptr[2] == d)- {- pptr += 3; /* Move on to class end */- meta = c;- if ((options & PCRE2_CASELESS) == 0)- {- reset_caseful = TRUE;- options |= PCRE2_CASELESS;- req_caseopt = REQ_CASELESS;- }- goto CLASS_CASELESS_CHAR;- }- }- }-- /* If a non-extended class contains a negative special such as \S, we need- to flip the negation flag at the end, so that support for characters > 255- works correctly (they are all included in the class). An extended class may- need to insert specific matching or non-matching code for wide characters.- */-- should_flip_negation = match_all_or_no_wide_chars = FALSE;-- /* Extended class (xclass) will be used when characters > 255- might match. */--#ifdef SUPPORT_WIDE_CHARS- xclass = FALSE;- class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */- class_uchardata_base = class_uchardata; /* Save the start */-#endif-- /* For optimization purposes, we track some properties of the class:- class_has_8bitchar will be non-zero if the class contains at least one- character with a code point less than 256; xclass_has_prop will be TRUE if- Unicode property checks are present in the class. */-- class_has_8bitchar = 0;-#ifdef SUPPORT_WIDE_CHARS- xclass_has_prop = FALSE;-#endif-- /* Initialize the 256-bit (32-byte) bit map to all zeros. We build the map- in a temporary bit of memory, in case the class contains fewer than two- 8-bit characters because in that case the compiled code doesn't use the bit- map. */-- memset(classbits, 0, 32 * sizeof(uint8_t));-- /* Process items until META_CLASS_END is reached. */-- while ((meta = *(++pptr)) != META_CLASS_END)- {- /* Handle POSIX classes such as [:alpha:] etc. */-- if (meta == META_POSIX || meta == META_POSIX_NEG)- {- BOOL local_negate = (meta == META_POSIX_NEG);- int posix_class = *(++pptr);- int taboffset, tabopt;- uint8_t pbits[32];-- should_flip_negation = local_negate; /* Note negative special */-- /* If matching is caseless, upper and lower are converted to alpha.- This relies on the fact that the class table starts with alpha,- lower, upper as the first 3 entries. */-- if ((options & PCRE2_CASELESS) != 0 && posix_class <= 2)- posix_class = 0;-- /* When PCRE2_UCP is set, some of the POSIX classes are converted to- different escape sequences that use Unicode properties \p or \P.- Others that are not available via \p or \P have to generate- XCL_PROP/XCL_NOTPROP directly, which is done here. */--#ifdef SUPPORT_UNICODE- if ((options & PCRE2_UCP) != 0) switch(posix_class)- {- case PC_GRAPH:- case PC_PRINT:- case PC_PUNCT:- *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;- *class_uchardata++ = (PCRE2_UCHAR)- ((posix_class == PC_GRAPH)? PT_PXGRAPH :- (posix_class == PC_PRINT)? PT_PXPRINT : PT_PXPUNCT);- *class_uchardata++ = 0;- xclass_has_prop = TRUE;- goto CONTINUE_CLASS;-- /* 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. However, if we are in- a negated POSIX class, characters with code points greater than- 255 must either all match or all not match, depending on whether- the whole class is not or is negated. For example, for- [[:^ascii:]... they must all match, whereas for [^[:^xdigit:]...- they must not.-- In the special case where there are no xclass items, this is- automatically handled by the use of OP_CLASS or OP_NCLASS, but an- explicit range is needed for OP_XCLASS. Setting a flag here- causes the range to be generated later when it is known that- OP_XCLASS is required. In the 8-bit library this is relevant only in- utf mode, since no wide characters can exist otherwise. */-- default:-#if PCRE2_CODE_UNIT_WIDTH == 8- if (utf)-#endif- match_all_or_no_wide_chars |= local_negate;- break;- }-#endif /* SUPPORT_UNICODE */-- /* In the non-UCP case, or when UCP makes no difference, we build the- bit map for the POSIX class in a chunk of local store because we may- be adding and subtracting from it, and we don't want to subtract bits- that may be in the main map already. At the end we or the result into- the bit map that is being built. */-- posix_class *= 3;-- /* Copy in the first table (always present) */-- memcpy(pbits, cbits + posix_class_maps[posix_class],- 32 * sizeof(uint8_t));-- /* If there is a second table, add or remove it as required. */-- taboffset = posix_class_maps[posix_class + 1];- tabopt = posix_class_maps[posix_class + 2];-- if (taboffset >= 0)- {- if (tabopt >= 0)- for (int i = 0; i < 32; i++) pbits[i] |= cbits[(int)i + taboffset];- else- for (int i = 0; i < 32; i++) pbits[i] &= ~cbits[(int)i + taboffset];- }-- /* Now see if we need to remove any special characters. An option- value of 1 removes vertical space and 2 removes underscore. */-- if (tabopt < 0) tabopt = -tabopt;- if (tabopt == 1) pbits[1] &= ~0x3c;- else if (tabopt == 2) pbits[11] &= 0x7f;-- /* Add the POSIX table or its complement into the main table that is- being built and we are done. */-- if (local_negate)- for (int i = 0; i < 32; i++) classbits[i] |= (uint8_t)(~pbits[i]);- else- for (int i = 0; i < 32; i++) classbits[i] |= pbits[i];-- /* Every class contains at least one < 256 character. */-- class_has_8bitchar = 1;- goto CONTINUE_CLASS; /* End of POSIX handling */- }-- /* Other than POSIX classes, the only items we should encounter are- \d-type escapes and literal characters (possibly as ranges). */-- if (meta == META_BIGVALUE)- {- meta = *(++pptr);- goto CLASS_LITERAL;- }-- /* Any other non-literal must be an escape */-- if (meta >= META_END)- {- if (META_CODE(meta) != META_ESCAPE)- {-#ifdef DEBUG_SHOW_PARSED- fprintf(stderr, "** Unrecognized parsed pattern item 0x%.8x "- "in character class\n", meta);-#endif- *errorcodeptr = ERR89; /* Internal error - unrecognized. */- return 0;- }- escape = META_DATA(meta);-- /* Every class contains at least one < 256 character. */-- class_has_8bitchar++;-- switch(escape)- {- case ESC_d:- for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_digit];- break;-- case ESC_D:- should_flip_negation = TRUE;- for (int i = 0; i < 32; i++)- classbits[i] |= (uint8_t)(~cbits[i+cbit_digit]);- break;-- case ESC_w:- for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_word];- break;-- case ESC_W:- should_flip_negation = TRUE;- for (int i = 0; i < 32; i++)- classbits[i] |= (uint8_t)(~cbits[i+cbit_word]);- break;-- /* Perl 5.004 onwards omitted VT from \s, but restored it at Perl- 5.18. Before PCRE 8.34, we had to preserve the VT bit if it was- previously set by something earlier in the character class.- Luckily, the value of CHAR_VT is 0x0b in both ASCII and EBCDIC, so- we could just adjust the appropriate bit. From PCRE 8.34 we no- longer treat \s and \S specially. */-- case ESC_s:- for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_space];- break;-- case ESC_S:- should_flip_negation = TRUE;- for (int i = 0; i < 32; i++)- classbits[i] |= (uint8_t)(~cbits[i+cbit_space]);- break;-- /* When adding the horizontal or vertical space lists to a class, or- their complements, disable PCRE2_CASELESS, because it justs wastes- time, and in the "not-x" UTF cases can create unwanted duplicates in- the XCLASS list (provoked by characters that have more than one other- case and by both cases being in the same "not-x" sublist). */-- case ESC_h:- (void)add_list_to_class(classbits, &class_uchardata,- options & ~PCRE2_CASELESS, cb, PRIV(hspace_list), NOTACHAR);- break;-- case ESC_H:- (void)add_not_list_to_class(classbits, &class_uchardata,- options & ~PCRE2_CASELESS, cb, PRIV(hspace_list));- break;-- case ESC_v:- (void)add_list_to_class(classbits, &class_uchardata,- options & ~PCRE2_CASELESS, cb, PRIV(vspace_list), NOTACHAR);- break;-- case ESC_V:- (void)add_not_list_to_class(classbits, &class_uchardata,- options & ~PCRE2_CASELESS, cb, PRIV(vspace_list));- break;-- /* If Unicode is not supported, \P and \p are not allowed and are- faulted at parse time, so will never appear here. */--#ifdef SUPPORT_UNICODE- case ESC_p:- case ESC_P:- {- uint32_t ptype = *(++pptr) >> 16;- uint32_t pdata = *pptr & 0xffff;- *class_uchardata++ = (escape == ESC_p)? XCL_PROP : XCL_NOTPROP;- *class_uchardata++ = ptype;- *class_uchardata++ = pdata;- xclass_has_prop = TRUE;- class_has_8bitchar--; /* Undo! */- }- break;-#endif- }-- goto CONTINUE_CLASS;- } /* End handling \d-type escapes */-- /* A literal character may be followed by a range meta. At parse time- there are checks for out-of-order characters, for ranges where the two- characters are equal, and for hyphens that cannot indicate a range. At- this point, therefore, no checking is needed. */-- else- {- uint32_t c, d;-- CLASS_LITERAL:- c = d = meta;-- /* Remember if \r or \n were explicitly used */-- if (c == CHAR_CR || c == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;-- /* Process a character range */-- if (pptr[1] == META_RANGE_LITERAL || pptr[1] == META_RANGE_ESCAPED)- {-#ifdef EBCDIC- BOOL range_is_literal = (pptr[1] == META_RANGE_LITERAL);-#endif- pptr += 2;- d = *pptr;- if (d == META_BIGVALUE) d = *(++pptr);-- /* Remember an explicit \r or \n, and add the range to the class. */-- if (d == CHAR_CR || d == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;-- /* In an EBCDIC environment, Perl treats alphabetic ranges specially- because there are holes in the encoding, and simply using the range- A-Z (for example) would include the characters in the holes. This- applies only to literal ranges; [\xC1-\xE9] is different to [A-Z]. */--#ifdef EBCDIC- if (range_is_literal &&- (cb->ctypes[c] & ctype_letter) != 0 &&- (cb->ctypes[d] & ctype_letter) != 0 &&- (c <= CHAR_z) == (d <= CHAR_z))- {- uint32_t uc = (d <= CHAR_z)? 0 : 64;- uint32_t C = c - uc;- uint32_t D = d - uc;-- if (C <= CHAR_i)- {- class_has_8bitchar +=- add_to_class(classbits, &class_uchardata, options, cb, C + uc,- ((D < CHAR_i)? D : CHAR_i) + uc);- C = CHAR_j;- }-- if (C <= D && C <= CHAR_r)- {- class_has_8bitchar +=- add_to_class(classbits, &class_uchardata, options, cb, C + uc,- ((D < CHAR_r)? D : CHAR_r) + uc);- C = CHAR_s;- }-- if (C <= D)- {- class_has_8bitchar +=- add_to_class(classbits, &class_uchardata, options, cb, C + uc,- D + uc);- }- }- else-#endif- /* Not an EBCDIC special range */-- class_has_8bitchar +=- add_to_class(classbits, &class_uchardata, options, cb, c, d);- goto CONTINUE_CLASS; /* Go get the next char in the class */- } /* End of range handling */--- /* Handle a single character. */-- class_has_8bitchar +=- add_to_class(classbits, &class_uchardata, options, cb, meta, meta);- }-- /* Continue to the next item in the class. */-- CONTINUE_CLASS:--#ifdef SUPPORT_WIDE_CHARS- /* If any wide characters or Unicode properties have been encountered,- set xclass = TRUE. Then, in the pre-compile phase, accumulate the length- of the extra data and reset the pointer. This is so that very large- classes that contain a zillion wide characters or Unicode property tests- do not overwrite the workspace (which is on the stack). */-- if (class_uchardata > class_uchardata_base)- {- xclass = TRUE;- if (lengthptr != NULL)- {- *lengthptr += class_uchardata - class_uchardata_base;- class_uchardata = class_uchardata_base;- }- }-#endif-- continue; /* Needed to avoid error when not supporting wide chars */- } /* End of main class-processing loop */-- /* If this class is the first thing in the branch, there can be no first- char setting, whatever the repeat count. Any reqcu setting must remain- unchanged after any kind of repeat. */-- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;- zerofirstcu = firstcu;- zerofirstcuflags = firstcuflags;- zeroreqcu = reqcu;- zeroreqcuflags = reqcuflags;-- /* If there are characters with values > 255, or Unicode property settings- (\p or \P), we have to compile an extended class, with its own opcode,- unless there were no property settings and there was a negated special such- as \S in the class, and PCRE2_UCP is not set, because in that case all- characters > 255 are in or not in the class, so any that were explicitly- given as well can be ignored.-- In the UCP case, if certain negated POSIX classes ([:^ascii:] or- [^:xdigit:]) were present in a class, we either have to match or not match- all wide characters (depending on whether the whole class is or is not- negated). This requirement is indicated by match_all_or_no_wide_chars being- true. We do this by including an explicit range, which works in both cases.- This applies only in UTF and 16-bit and 32-bit non-UTF modes, since there- cannot be any wide characters in 8-bit non-UTF mode.-- When there *are* properties in a positive UTF-8 or any 16-bit or 32_bit- class where \S etc is present without PCRE2_UCP, causing an extended class- to be compiled, we make sure that all characters > 255 are included by- forcing match_all_or_no_wide_chars to be true.-- If, when generating an xclass, there are no characters < 256, we can omit- the bitmap in the actual compiled code. */--#ifdef SUPPORT_WIDE_CHARS /* Defined for 16/32 bits, or 8-bit with Unicode */- if (xclass && (-#ifdef SUPPORT_UNICODE- (options & PCRE2_UCP) != 0 ||-#endif- xclass_has_prop || !should_flip_negation))- {- if (match_all_or_no_wide_chars || (-#if PCRE2_CODE_UNIT_WIDTH == 8- utf &&-#endif- should_flip_negation && !negate_class && (options & PCRE2_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)(MAX_UTF_CODE_POINT, class_uchardata);- }- else /* Can only happen for the 16-bit & 32-bit libraries */- {-#if PCRE2_CODE_UNIT_WIDTH == 16- *class_uchardata++ = 0x100;- *class_uchardata++ = 0xffffu;-#elif PCRE2_CODE_UNIT_WIDTH == 32- *class_uchardata++ = 0x100;- *class_uchardata++ = 0xffffffffu;-#endif- }- }- *class_uchardata++ = XCL_END; /* Marks the end of extra data */- *code++ = OP_XCLASS;- code += LINK_SIZE;- *code = negate_class? XCL_NOT:0;- if (xclass_has_prop) *code |= XCL_HASPROP;-- /* If the map is required, move up the extra data to make room for it;- otherwise just move the code pointer to the end of the extra data. */-- if (class_has_8bitchar > 0)- {- *code++ |= XCL_MAP;- (void)memmove(code + (32 / sizeof(PCRE2_UCHAR)), code,- CU2BYTES(class_uchardata - code));- if (negate_class && !xclass_has_prop)- {- /* Using 255 ^ instead of ~ avoids clang sanitize warning. */- for (int i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];- }- memcpy(code, classbits, 32);- code = class_uchardata + (32 / sizeof(PCRE2_UCHAR));- }- else code = class_uchardata;-- /* Now fill in the complete length of the item */-- PUT(previous, 1, (int)(code - previous));- break; /* End of class handling */- }-#endif /* SUPPORT_WIDE_CHARS */-- /* If there are no characters > 255, or they are all to be included or- excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the- whole class was negated and whether there were negative specials such as \S- (non-UCP) in the class. Then copy the 32-byte map into the code vector,- negating it if necessary. */-- *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;- if (lengthptr == NULL) /* Save time in the pre-compile phase */- {- if (negate_class)- {- /* Using 255 ^ instead of ~ avoids clang sanitize warning. */- for (int i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];- }- memcpy(code, classbits, 32);- }- code += 32 / sizeof(PCRE2_UCHAR);- break; /* End of class processing */--- /* ===================================================================*/- /* Deal with (*VERB)s. */-- /* Check for open captures before ACCEPT and close those that are within- the same assertion level, also converting ACCEPT to ASSERT_ACCEPT in an- assertion. In the first pass, just accumulate the length required;- otherwise hitting (*ACCEPT) inside many nested parentheses can cause- workspace overflow. Do not set firstcu after *ACCEPT. */-- case META_ACCEPT:- cb->had_accept = had_accept = TRUE;- for (oc = cb->open_caps;- oc != NULL && oc->assert_depth >= cb->assert_depth;- oc = oc->next)- {- if (lengthptr != NULL)- {- *lengthptr += CU2BYTES(1) + IMM2_SIZE;- }- else- {- *code++ = OP_CLOSE;- PUT2INC(code, 0, oc->number);- }- }- *code++ = (cb->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;- break;-- case META_PRUNE:- case META_SKIP:- cb->had_pruneorskip = TRUE;- /* Fall through */- case META_COMMIT:- case META_FAIL:- *code++ = verbops[(meta - META_MARK) >> 16];- break;-- case META_THEN:- cb->external_flags |= PCRE2_HASTHEN;- *code++ = OP_THEN;- break;-- /* Handle verbs with arguments. Arguments can be very long, especially in- 16- and 32-bit modes, and can overflow the workspace in the first pass.- However, the argument length is constrained to be small enough to fit in- one code unit. This check happens in parse_regex(). In the first pass,- instead of putting the argument into memory, we just update the length- counter and set up an empty argument. */-- case META_THEN_ARG:- cb->external_flags |= PCRE2_HASTHEN;- goto VERB_ARG;-- case META_PRUNE_ARG:- case META_SKIP_ARG:- cb->had_pruneorskip = TRUE;- /* Fall through */- case META_MARK:- case META_COMMIT_ARG:- VERB_ARG:- *code++ = verbops[(meta - META_MARK) >> 16];- /* The length is in characters. */- verbarglen = *(++pptr);- verbculen = 0;- tempcode = code++;- for (int i = 0; i < (int)verbarglen; i++)- {- meta = *(++pptr);-#ifdef SUPPORT_UNICODE- if (utf) mclength = PRIV(ord2utf)(meta, mcbuffer); else-#endif- {- mclength = 1;- mcbuffer[0] = meta;- }- if (lengthptr != NULL) *lengthptr += mclength; else- {- memcpy(code, mcbuffer, CU2BYTES(mclength));- code += mclength;- verbculen += mclength;- }- }-- *tempcode = verbculen; /* Fill in the code unit length */- *code++ = 0; /* Terminating zero */- break;--- /* ===================================================================*/- /* Handle options change. The new setting must be passed back for use in- subsequent branches. Reset the greedy defaults and the case value for- firstcu and reqcu. */-- case META_OPTIONS:- *optionsptr = options = *(++pptr);- greedy_default = ((options & PCRE2_UNGREEDY) != 0);- greedy_non_default = greedy_default ^ 1;- req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0;- break;--- /* ===================================================================*/- /* Handle conditional subpatterns. The case of (?(Rdigits) is ambiguous- because it could be a numerical check on recursion, or a name check on a- group's being set. The pre-pass sets up META_COND_RNUMBER as a name so that- we can handle it either way. We first try for a name; if not found, process- the number. */-- case META_COND_RNUMBER: /* (?(Rdigits) */- case META_COND_NAME: /* (?(name) or (?'name') or ?(<name>) */- case META_COND_RNAME: /* (?(R&name) - test for recursion */- bravalue = OP_COND;- {- int count, index;- unsigned int i;- PCRE2_SPTR name;- named_group *ng = cb->named_groups;- uint32_t length = *(++pptr);-- GETPLUSOFFSET(offset, pptr);- name = cb->start_pattern + offset;-- /* In the first pass, the names generated in the pre-pass are available,- but the main name table has not yet been created. Scan the list of names- generated in the pre-pass in order to get a number and whether or not- this name is duplicated. If it is not duplicated, we can handle it as a- numerical group. */-- for (i = 0; i < cb->names_found; i++, ng++)- {- if (length == ng->length &&- PRIV(strncmp)(name, ng->name, length) == 0)- {- if (!ng->isdup)- {- code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;- PUT2(code, 2+LINK_SIZE, ng->number);- if (ng->number > cb->top_backref) cb->top_backref = ng->number;- skipunits = 1+IMM2_SIZE;- goto GROUP_PROCESS_NOTE_EMPTY;- }- break; /* Found a duplicated name */- }- }-- /* If the name was not found we have a bad reference, unless we are- dealing with R<digits>, which is treated as a recursion test by number.- */-- if (i >= cb->names_found)- {- groupnumber = 0;- if (meta == META_COND_RNUMBER)- {- for (i = 1; i < length; i++)- {- groupnumber = groupnumber * 10 + name[i] - CHAR_0;- if (groupnumber > MAX_GROUP_NUMBER)- {- *errorcodeptr = ERR61;- cb->erroroffset = offset + i;- return 0;- }- }- }-- if (meta != META_COND_RNUMBER || groupnumber > cb->bracount)- {- *errorcodeptr = ERR15;- cb->erroroffset = offset;- return 0;- }-- /* (?Rdigits) treated as a recursion reference by number. A value of- zero (which is the result of both (?R) and (?R0)) means "any", and is- translated into RREF_ANY (which is 0xffff). */-- if (groupnumber == 0) groupnumber = RREF_ANY;- code[1+LINK_SIZE] = OP_RREF;- PUT2(code, 2+LINK_SIZE, groupnumber);- skipunits = 1+IMM2_SIZE;- goto GROUP_PROCESS_NOTE_EMPTY;- }-- /* A duplicated name was found. Note that if an R<digits> name is found- (META_COND_RNUMBER), it is a reference test, not a recursion test. */-- code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;-- /* We have a duplicated name. In the compile pass we have to search the- main table in order to get the index and count values. */-- count = 0; /* Values for first pass (avoids compiler warning) */- index = 0;- if (lengthptr == NULL && !find_dupname_details(name, length, &index,- &count, errorcodeptr, cb)) return 0;-- /* Add one to the opcode to change CREF/RREF into DNCREF/DNRREF and- insert appropriate data values. */-- code[1+LINK_SIZE]++;- skipunits = 1+2*IMM2_SIZE;- PUT2(code, 2+LINK_SIZE, index);- PUT2(code, 2+LINK_SIZE+IMM2_SIZE, count);- }- goto GROUP_PROCESS_NOTE_EMPTY;-- /* The DEFINE condition is always false. Its internal groups may never- be called, so matched_char must remain false, hence the jump to- GROUP_PROCESS rather than GROUP_PROCESS_NOTE_EMPTY. */-- case META_COND_DEFINE:- bravalue = OP_COND;- GETPLUSOFFSET(offset, pptr);- code[1+LINK_SIZE] = OP_DEFINE;- skipunits = 1;- goto GROUP_PROCESS;-- /* Conditional test of a group's being set. */-- case META_COND_NUMBER:- bravalue = OP_COND;- GETPLUSOFFSET(offset, pptr);- groupnumber = *(++pptr);- if (groupnumber > cb->bracount)- {- *errorcodeptr = ERR15;- cb->erroroffset = offset;- return 0;- }- if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;- offset -= 2; /* Point at initial ( for too many branches error */- code[1+LINK_SIZE] = OP_CREF;- skipunits = 1+IMM2_SIZE;- PUT2(code, 2+LINK_SIZE, groupnumber);- goto GROUP_PROCESS_NOTE_EMPTY;-- /* Test for the PCRE2 version. */-- case META_COND_VERSION:- bravalue = OP_COND;- if (pptr[1] > 0)- code[1+LINK_SIZE] = ((PCRE2_MAJOR > pptr[2]) ||- (PCRE2_MAJOR == pptr[2] && PCRE2_MINOR >= pptr[3]))?- OP_TRUE : OP_FALSE;- else- code[1+LINK_SIZE] = (PCRE2_MAJOR == pptr[2] && PCRE2_MINOR == pptr[3])?- OP_TRUE : OP_FALSE;- skipunits = 1;- pptr += 3;- goto GROUP_PROCESS_NOTE_EMPTY;-- /* The condition is an assertion, possibly preceded by a callout. */-- case META_COND_ASSERT:- bravalue = OP_COND;- goto GROUP_PROCESS_NOTE_EMPTY;--- /* ===================================================================*/- /* Handle all kinds of nested bracketed groups. The non-capturing,- non-conditional cases are here; others come to GROUP_PROCESS via goto. */-- case META_LOOKAHEAD:- bravalue = OP_ASSERT;- cb->assert_depth += 1;- goto GROUP_PROCESS;-- case META_LOOKAHEAD_NA:- bravalue = OP_ASSERT_NA;- cb->assert_depth += 1;- goto GROUP_PROCESS;-- /* Optimize (?!) to (*FAIL) unless it is quantified - which is a weird- thing to do, but Perl allows all assertions to be quantified, and when- they contain capturing parentheses there may be a potential use for- this feature. Not that that applies to a quantified (?!) but we allow- it for uniformity. */-- case META_LOOKAHEADNOT:- if (pptr[1] == META_KET &&- (pptr[2] < META_ASTERISK || pptr[2] > META_MINMAX_QUERY))- {- *code++ = OP_FAIL;- pptr++;- }- else- {- bravalue = OP_ASSERT_NOT;- cb->assert_depth += 1;- goto GROUP_PROCESS;- }- break;-- case META_LOOKBEHIND:- bravalue = OP_ASSERTBACK;- cb->assert_depth += 1;- goto GROUP_PROCESS;-- case META_LOOKBEHINDNOT:- bravalue = OP_ASSERTBACK_NOT;- cb->assert_depth += 1;- goto GROUP_PROCESS;-- case META_LOOKBEHIND_NA:- bravalue = OP_ASSERTBACK_NA;- cb->assert_depth += 1;- goto GROUP_PROCESS;-- case META_ATOMIC:- bravalue = OP_ONCE;- goto GROUP_PROCESS_NOTE_EMPTY;-- case META_SCRIPT_RUN:- bravalue = OP_SCRIPT_RUN;- goto GROUP_PROCESS_NOTE_EMPTY;-- case META_NOCAPTURE:- bravalue = OP_BRA;- /* Fall through */-- /* Process nested bracketed regex. The nesting depth is maintained for the- benefit of the stackguard function. The test for too deep nesting is now- done in parse_regex(). Assertion and DEFINE groups come to GROUP_PROCESS;- others come to GROUP_PROCESS_NOTE_EMPTY, to indicate that we need to take- note of whether or not they may match an empty string. */-- GROUP_PROCESS_NOTE_EMPTY:- note_group_empty = TRUE;-- GROUP_PROCESS:- cb->parens_depth += 1;- *code = bravalue;- pptr++;- tempcode = code;- tempreqvary = cb->req_varyopt; /* Save value before group */- length_prevgroup = 0; /* Initialize for pre-compile phase */-- if ((group_return =- compile_regex(- options, /* The option state */- &tempcode, /* Where to put code (updated) */- &pptr, /* Input pointer (updated) */- errorcodeptr, /* Where to put an error message */- skipunits, /* Skip over bracket number */- &subfirstcu, /* For possible first char */- &subfirstcuflags,- &subreqcu, /* For possible last char */- &subreqcuflags,- bcptr, /* Current branch chain */- cb, /* Compile data block */- (lengthptr == NULL)? NULL : /* Actual compile phase */- &length_prevgroup /* Pre-compile phase */- )) == 0)- return 0; /* Error */-- cb->parens_depth -= 1;-- /* If that was a non-conditional significant group (not an assertion, not a- DEFINE) that matches at least one character, then the current item matches- a character. Conditionals are handled below. */-- if (note_group_empty && bravalue != OP_COND && group_return > 0)- matched_char = TRUE;-- /* If we've just compiled an assertion, pop the assert depth. */-- if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NA)- cb->assert_depth -= 1;-- /* At the end of compiling, code is still pointing to the start of the- group, while tempcode has been updated to point past the end of the group.- The parsed pattern pointer (pptr) is on the closing META_KET.-- If this is a conditional bracket, check that there are no more than- two branches in the group, or just one if it's a DEFINE group. We do this- in the real compile phase, not in the pre-pass, where the whole group may- not be available. */-- if (bravalue == OP_COND && lengthptr == NULL)- {- PCRE2_UCHAR *tc = code;- int condcount = 0;-- do {- condcount++;- tc += GET(tc,1);- }- while (*tc != OP_KET);-- /* A DEFINE group is never obeyed inline (the "condition" is always- false). It must have only one branch. Having checked this, change the- opcode to OP_FALSE. */-- if (code[LINK_SIZE+1] == OP_DEFINE)- {- if (condcount > 1)- {- cb->erroroffset = offset;- *errorcodeptr = ERR54;- return 0;- }- code[LINK_SIZE+1] = OP_FALSE;- bravalue = OP_DEFINE; /* A flag to suppress char handling below */- }-- /* A "normal" conditional group. If there is just one branch, we must not- make use of its firstcu or reqcu, because this is equivalent to an- empty second branch. Also, it may match an empty string. If there are two- branches, this item must match a character if the group must. */-- else- {- if (condcount > 2)- {- cb->erroroffset = offset;- *errorcodeptr = ERR27;- return 0;- }- if (condcount == 1) subfirstcuflags = subreqcuflags = REQ_NONE;- else if (group_return > 0) matched_char = TRUE;- }- }-- /* In the pre-compile phase, update the length by the length of the group,- less the brackets at either end. Then reduce the compiled code to just a- set of non-capturing brackets so that it doesn't use much memory if it is- duplicated by a quantifier.*/-- if (lengthptr != NULL)- {- if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE)- {- *errorcodeptr = ERR20;- return 0;- }- *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE;- code++; /* This already contains bravalue */- PUTINC(code, 0, 1 + LINK_SIZE);- *code++ = OP_KET;- PUTINC(code, 0, 1 + LINK_SIZE);- break; /* No need to waste time with special character handling */- }-- /* Otherwise update the main code pointer to the end of the group. */-- code = tempcode;-- /* For a DEFINE group, required and first character settings are not- relevant. */-- if (bravalue == OP_DEFINE) break;-- /* Handle updating of the required and first code units for other types of- group. Update for normal brackets of all kinds, and conditions with two- branches (see code above). If the bracket is followed by a quantifier with- zero repeat, we have to back off. Hence the definition of zeroreqcu and- zerofirstcu outside the main loop so that they can be accessed for the back- off. */-- zeroreqcu = reqcu;- zeroreqcuflags = reqcuflags;- zerofirstcu = firstcu;- zerofirstcuflags = firstcuflags;- groupsetfirstcu = FALSE;-- if (bravalue >= OP_ONCE) /* Not an assertion */- {- /* If we have not yet set a firstcu in this branch, take it from the- subpattern, remembering that it was set here so that a repeat of more- than one can replicate it as reqcu if necessary. If the subpattern has- no firstcu, set "none" for the whole branch. In both cases, a zero- repeat forces firstcu to "none". */-- if (firstcuflags == REQ_UNSET && subfirstcuflags != REQ_UNSET)- {- if (subfirstcuflags < REQ_NONE)- {- firstcu = subfirstcu;- firstcuflags = subfirstcuflags;- groupsetfirstcu = TRUE;- }- else firstcuflags = REQ_NONE;- zerofirstcuflags = REQ_NONE;- }-- /* If firstcu was previously set, convert the subpattern's firstcu- into reqcu if there wasn't one, using the vary flag that was in- existence beforehand. */-- else if (subfirstcuflags < REQ_NONE && subreqcuflags >= REQ_NONE)- {- subreqcu = subfirstcu;- subreqcuflags = subfirstcuflags | tempreqvary;- }-- /* If the subpattern set a required code unit (or set a first code unit- that isn't really the first code unit - see above), set it. */-- if (subreqcuflags < REQ_NONE)- {- reqcu = subreqcu;- reqcuflags = subreqcuflags;- }- }-- /* For a forward assertion, we take the reqcu, if set, provided that the- group has also set a firstcu. 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 firstcu for an assertion, however- because it leads to incorrect effect for patterns such as /(?=a)a.+/ when- the "real" "a" would then become a reqcu instead of a firstcu. This is- overcome by a scan at the end if there's no firstcu, looking for an- asserted first char. A similar effect for patterns like /(?=.*X)X$/ means- we must only take the reqcu when the group also set a firstcu. Otherwise,- in that example, 'X' ends up set for both. */-- else if ((bravalue == OP_ASSERT || bravalue == OP_ASSERT_NA) &&- subreqcuflags < REQ_NONE && subfirstcuflags < REQ_NONE)- {- reqcu = subreqcu;- reqcuflags = subreqcuflags;- }-- break; /* End of nested group handling */--- /* ===================================================================*/- /* Handle named backreferences and recursions. */-- case META_BACKREF_BYNAME:- case META_RECURSE_BYNAME:- {- int count, index;- PCRE2_SPTR name;- BOOL is_dupname = FALSE;- named_group *ng = cb->named_groups;- uint32_t length = *(++pptr);-- GETPLUSOFFSET(offset, pptr);- name = cb->start_pattern + offset;-- /* In the first pass, the names generated in the pre-pass are available,- but the main name table has not yet been created. Scan the list of names- generated in the pre-pass in order to get a number and whether or not- this name is duplicated. */-- groupnumber = 0;- for (unsigned int i = 0; i < cb->names_found; i++, ng++)- {- if (length == ng->length &&- PRIV(strncmp)(name, ng->name, length) == 0)- {- is_dupname = ng->isdup;- groupnumber = ng->number;-- /* For a recursion, that's all that is needed. We can now go to- the code that handles numerical recursion, applying it to the first- group with the given name. */-- if (meta == META_RECURSE_BYNAME)- {- meta_arg = groupnumber;- goto HANDLE_NUMERICAL_RECURSION;- }-- /* For a back reference, update the back reference map and the- maximum back reference. */-- cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;- if (groupnumber > cb->top_backref)- cb->top_backref = groupnumber;- }- }-- /* If the name was not found we have a bad reference. */-- if (groupnumber == 0)- {- *errorcodeptr = ERR15;- cb->erroroffset = offset;- return 0;- }-- /* If a back reference name is not duplicated, we can handle it as- a numerical reference. */-- if (!is_dupname)- {- meta_arg = groupnumber;- goto HANDLE_SINGLE_REFERENCE;- }-- /* If a back reference name is duplicated, we generate a different- opcode to a numerical back reference. In the second pass we must- search for the index and count in the final name table. */-- count = 0; /* Values for first pass (avoids compiler warning) */- index = 0;- if (lengthptr == NULL && !find_dupname_details(name, length, &index,- &count, errorcodeptr, cb)) return 0;-- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;- *code++ = ((options & PCRE2_CASELESS) != 0)? OP_DNREFI : OP_DNREF;- PUT2INC(code, 0, index);- PUT2INC(code, 0, count);- }- break;--- /* ===================================================================*/- /* Handle a numerical callout. */-- case META_CALLOUT_NUMBER:- code[0] = OP_CALLOUT;- PUT(code, 1, pptr[1]); /* Offset to next pattern item */- PUT(code, 1 + LINK_SIZE, pptr[2]); /* Length of next pattern item */- code[1 + 2*LINK_SIZE] = pptr[3];- pptr += 3;- code += PRIV(OP_lengths)[OP_CALLOUT];- break;--- /* ===================================================================*/- /* Handle a callout with a string argument. In the pre-pass we just compute- the length without generating anything. The length in pptr[3] includes both- delimiters; in the actual compile only the first one is copied, but a- terminating zero is added. Any doubled delimiters within the string make- this an overestimate, but it is not worth bothering about. */-- case META_CALLOUT_STRING:- if (lengthptr != NULL)- {- *lengthptr += pptr[3] + (1 + 4*LINK_SIZE);- pptr += 3;- SKIPOFFSET(pptr);- }-- /* In the real compile we can copy the string. The starting delimiter is- included so that the client can discover it if they want. We also pass the- start offset to help a script language give better error messages. */-- else- {- PCRE2_SPTR pp;- uint32_t delimiter;- uint32_t length = pptr[3];- PCRE2_UCHAR *callout_string = code + (1 + 4*LINK_SIZE);-- code[0] = OP_CALLOUT_STR;- PUT(code, 1, pptr[1]); /* Offset to next pattern item */- PUT(code, 1 + LINK_SIZE, pptr[2]); /* Length of next pattern item */-- pptr += 3;- GETPLUSOFFSET(offset, pptr); /* Offset to string in pattern */- pp = cb->start_pattern + offset;- delimiter = *callout_string++ = *pp++;- if (delimiter == CHAR_LEFT_CURLY_BRACKET)- delimiter = CHAR_RIGHT_CURLY_BRACKET;- PUT(code, 1 + 3*LINK_SIZE, (int)(offset + 1)); /* One after delimiter */-- /* The syntax of the pattern was checked in the parsing scan. The length- includes both delimiters, but we have passed the opening one just above,- so we reduce length before testing it. The test is for > 1 because we do- not want to copy the final delimiter. This also ensures that pp[1] is- accessible. */-- while (--length > 1)- {- if (*pp == delimiter && pp[1] == delimiter)- {- *callout_string++ = delimiter;- pp += 2;- length--;- }- else *callout_string++ = *pp++;- }- *callout_string++ = CHAR_NUL;-- /* Set the length of the entire item, the advance to its end. */-- PUT(code, 1 + 2*LINK_SIZE, (int)(callout_string - code));- code = callout_string;- }- break;--- /* ===================================================================*/- /* Handle repetition. The different types are all sorted out in the parsing- pass. */-- case META_MINMAX_PLUS:- case META_MINMAX_QUERY:- case META_MINMAX:- repeat_min = *(++pptr);- repeat_max = *(++pptr);- goto REPEAT;-- case META_ASTERISK:- case META_ASTERISK_PLUS:- case META_ASTERISK_QUERY:- repeat_min = 0;- repeat_max = REPEAT_UNLIMITED;- goto REPEAT;-- case META_PLUS:- case META_PLUS_PLUS:- case META_PLUS_QUERY:- repeat_min = 1;- repeat_max = REPEAT_UNLIMITED;- goto REPEAT;-- case META_QUERY:- case META_QUERY_PLUS:- case META_QUERY_QUERY:- repeat_min = 0;- repeat_max = 1;-- REPEAT:- if (previous_matched_char && repeat_min > 0) matched_char = TRUE;-- /* Remember whether this is a variable length repeat, and default to- single-char opcodes. */-- reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY;- op_type = 0;-- /* Adjust first and required code units for a zero repeat. */-- if (repeat_min == 0)- {- firstcu = zerofirstcu;- firstcuflags = zerofirstcuflags;- reqcu = zeroreqcu;- reqcuflags = zeroreqcuflags;- }-- /* Note the greediness and possessiveness. */-- switch (meta)- {- case META_MINMAX_PLUS:- case META_ASTERISK_PLUS:- case META_PLUS_PLUS:- case META_QUERY_PLUS:- repeat_type = 0; /* Force greedy */- possessive_quantifier = TRUE;- break;-- case META_MINMAX_QUERY:- case META_ASTERISK_QUERY:- case META_PLUS_QUERY:- case META_QUERY_QUERY:- repeat_type = greedy_non_default;- possessive_quantifier = FALSE;- break;-- default:- repeat_type = greedy_default;- possessive_quantifier = FALSE;- break;- }-- /* Save start of previous item, in case we have to move it up in order to- insert something before it, and remember what it was. */-- tempcode = previous;- op_previous = *previous;-- /* Now handle repetition for the different types of item. If the repeat- minimum and the repeat maximum are both 1, we can ignore the quantifier for- non-parenthesized items, as they have only one alternative. For anything in- parentheses, we must not ignore if {1} is possessive. */-- switch (op_previous)- {- /* If previous was a character or negated character match, abolish the- item and generate a repeat item instead. If a char item has a minimum of- more than one, ensure that it is set in reqcu - it might not be if a- sequence such as x{3} is the first thing in a branch because the x will- have gone into firstcu instead. */-- case OP_CHAR:- case OP_CHARI:- case OP_NOT:- case OP_NOTI:- if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;- op_type = chartypeoffset[op_previous - OP_CHAR];-- /* Deal with UTF characters that take up more than one code unit. */--#ifdef MAYBE_UTF_MULTI- if (utf && NOT_FIRSTCU(code[-1]))- {- PCRE2_UCHAR *lastchar = code - 1;- BACKCHAR(lastchar);- mclength = (uint32_t)(code - lastchar); /* Length of UTF character */- memcpy(mcbuffer, lastchar, CU2BYTES(mclength)); /* Save the char */- }- else-#endif /* MAYBE_UTF_MULTI */-- /* Handle the case of a single code unit - either with no UTF support, or- with UTF disabled, or for a single-code-unit UTF character. In the latter- case, for a repeated positive match, get the caseless flag for the- required code unit from the previous character, because a class like [Aa]- sets a caseless A but by now the req_caseopt flag has been reset. */-- {- mcbuffer[0] = code[-1];- mclength = 1;- if (op_previous <= OP_CHARI && repeat_min > 1)- {- reqcu = mcbuffer[0];- reqcuflags = cb->req_varyopt;- if (op_previous == OP_CHARI) reqcuflags |= REQ_CASELESS;- }- }- goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */-- /* If previous was a character class or a back reference, we put the- repeat stuff after it, but just skip the item if the repeat was {0,0}. */--#ifdef SUPPORT_WIDE_CHARS- case OP_XCLASS:-#endif- case OP_CLASS:- case OP_NCLASS:- case OP_REF:- case OP_REFI:- case OP_DNREF:- case OP_DNREFI:-- if (repeat_max == 0)- {- code = previous;- goto END_REPEAT;- }- if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;-- if (repeat_min == 0 && repeat_max == REPEAT_UNLIMITED)- *code++ = OP_CRSTAR + repeat_type;- else if (repeat_min == 1 && repeat_max == REPEAT_UNLIMITED)- *code++ = OP_CRPLUS + repeat_type;- else if (repeat_min == 0 && repeat_max == 1)- *code++ = OP_CRQUERY + repeat_type;- else- {- *code++ = OP_CRRANGE + repeat_type;- PUT2INC(code, 0, repeat_min);- if (repeat_max == REPEAT_UNLIMITED) repeat_max = 0; /* 2-byte encoding for max */- PUT2INC(code, 0, repeat_max);- }- break;-- /* If previous is OP_FAIL, it was generated by an empty class []- (PCRE2_ALLOW_EMPTY_CLASS is set). The other ways in which OP_FAIL can be- generated, that is by (*FAIL) or (?!), disallow a quantifier at parse- time. We can just ignore this repeat. */-- case OP_FAIL:- goto END_REPEAT;-- /* Prior to 10.30, repeated recursions were wrapped in OP_ONCE brackets- because pcre2_match() could not handle backtracking into recursively- called groups. Now that this backtracking is available, we no longer need- to do this. However, we still need to replicate recursions as we do for- groups so as to have independent backtracking points. We can replicate- for the minimum number of repeats directly. For optional repeats we now- wrap the recursion in OP_BRA brackets and make use of the bracket- repetition. */-- case OP_RECURSE:- if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)- goto END_REPEAT;-- /* Generate unwrapped repeats for a non-zero minimum, except when the- minimum is 1 and the maximum unlimited, because that can be handled with- OP_BRA terminated by OP_KETRMAX/MIN. When the maximum is equal to the- minimum, we just need to generate the appropriate additional copies.- Otherwise we need to generate one more, to simulate the situation when- the minimum is zero. */-- if (repeat_min > 0 && (repeat_min != 1 || repeat_max != REPEAT_UNLIMITED))- {- int replicate = repeat_min;- if (repeat_min == repeat_max) replicate--;-- /* In the pre-compile phase, we don't actually do the replication. We- just adjust the length as if we had. Do some paranoid checks for- potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit- integer type when available, otherwise double. */-- if (lengthptr != NULL)- {- PCRE2_SIZE delta = replicate*(1 + LINK_SIZE);- if ((INT64_OR_DOUBLE)replicate*- (INT64_OR_DOUBLE)(1 + LINK_SIZE) >- (INT64_OR_DOUBLE)INT_MAX ||- OFLOW_MAX - *lengthptr < delta)- {- *errorcodeptr = ERR20;- return 0;- }- *lengthptr += delta;- }-- else for (int i = 0; i < replicate; i++)- {- memcpy(code, previous, CU2BYTES(1 + LINK_SIZE));- previous = code;- code += 1 + LINK_SIZE;- }-- /* If the number of repeats is fixed, we are done. Otherwise, adjust- the counts and fall through. */-- if (repeat_min == repeat_max) break;- if (repeat_max != REPEAT_UNLIMITED) repeat_max -= repeat_min;- repeat_min = 0;- }-- /* Wrap the recursion call in OP_BRA brackets. */-- (void)memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(1 + LINK_SIZE));- op_previous = *previous = OP_BRA;- PUT(previous, 1, 2 + 2*LINK_SIZE);- previous[2 + 2*LINK_SIZE] = OP_KET;- PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE);- code += 2 + 2 * LINK_SIZE;- length_prevgroup = 3 + 3*LINK_SIZE;- group_return = -1; /* Set "may match empty string" */-- /* Now treat as a repeated OP_BRA. */- /* Fall through */-- /* If previous was a bracket group, we may have to replicate it in- certain cases. Note that at this point we can encounter only the "basic"- bracket opcodes such as BRA and CBRA, as this is the place where they get- converted into the more special varieties such as BRAPOS and SBRA.- Originally, PCRE did not allow repetition of assertions, but now it does,- for Perl compatibility. */-- case OP_ASSERT:- case OP_ASSERT_NOT:- case OP_ASSERT_NA:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT:- case OP_ASSERTBACK_NA:- case OP_ONCE:- case OP_SCRIPT_RUN:- case OP_BRA:- case OP_CBRA:- case OP_COND:- {- int len = (int)(code - previous);- PCRE2_UCHAR *bralink = NULL;- PCRE2_UCHAR *brazeroptr = NULL;-- if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)- goto END_REPEAT;-- /* Repeating a DEFINE group (or any group where the condition is always- FALSE and there is only one branch) is pointless, but Perl allows the- syntax, so we just ignore the repeat. */-- if (op_previous == OP_COND && previous[LINK_SIZE+1] == OP_FALSE &&- previous[GET(previous, 1)] != OP_ALT)- goto END_REPEAT;-- /* Perl allows all assertions to be quantified, and when they contain- capturing parentheses and/or are optional there are potential uses for- this feature. PCRE2 used to force the maximum quantifier to 1 on the- invalid grounds that further repetition was never useful. This was- always a bit pointless, since an assertion could be wrapped with a- repeated group to achieve the effect. General repetition is now- permitted, but if the maximum is unlimited it is set to one more than- the minimum. */-- if (op_previous < OP_ONCE) /* Assertion */- {- if (repeat_max == REPEAT_UNLIMITED) repeat_max = repeat_min + 1;- }-- /* The case of a zero minimum is special because of the need to stick- OP_BRAZERO in front of it, and because the group appears once in the- data, whereas in other cases it appears the minimum number of times. For- this reason, it is simplest to treat this case separately, as otherwise- the code gets far too messy. There are several special subcases when the- minimum is zero. */-- if (repeat_min == 0)- {- /* If the maximum is also zero, we used to just omit the group from- the output altogether, like this:-- ** if (repeat_max == 0)- ** {- ** code = previous;- ** goto END_REPEAT;- ** }-- However, that fails when a group or a subgroup within it is- referenced as a subroutine from elsewhere in the pattern, so now we- stick in OP_SKIPZERO in front of it so that it is skipped on- execution. As we don't have a list of which groups are referenced, we- cannot do this selectively.-- If the maximum is 1 or unlimited, we just have to stick in the- BRAZERO and do no more at this point. */-- if (repeat_max <= 1 || repeat_max == REPEAT_UNLIMITED)- {- (void)memmove(previous + 1, previous, CU2BYTES(len));- code++;- if (repeat_max == 0)- {- *previous++ = OP_SKIPZERO;- goto END_REPEAT;- }- brazeroptr = previous; /* Save for possessive optimizing */- *previous++ = OP_BRAZERO + repeat_type;- }-- /* If the maximum is greater than 1 and limited, we have to replicate- in a nested fashion, sticking OP_BRAZERO before each set of brackets.- The first one has to be handled carefully because it's the original- copy, which has to be moved up. The remainder can be handled by code- that is common with the non-zero minimum case below. We have to- adjust the value or repeat_max, since one less copy is required. */-- else- {- int linkoffset;- (void)memmove(previous + 2 + LINK_SIZE, previous, CU2BYTES(len));- code += 2 + LINK_SIZE;- *previous++ = OP_BRAZERO + repeat_type;- *previous++ = OP_BRA;-- /* We chain together the bracket link offset fields that have to be- filled in later when the ends of the brackets are reached. */-- linkoffset = (bralink == NULL)? 0 : (int)(previous - bralink);- bralink = previous;- PUTINC(previous, 0, linkoffset);- }-- if (repeat_max != REPEAT_UNLIMITED) repeat_max--;- }-- /* If the minimum is greater than zero, replicate the group as many- times as necessary, and adjust the maximum to the number of subsequent- copies that we need. */-- else- {- if (repeat_min > 1)- {- /* In the pre-compile phase, we don't actually do the replication.- We just adjust the length as if we had. Do some paranoid checks for- potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit- integer type when available, otherwise double. */-- if (lengthptr != NULL)- {- PCRE2_SIZE delta = (repeat_min - 1)*length_prevgroup;- if ((INT64_OR_DOUBLE)(repeat_min - 1)*- (INT64_OR_DOUBLE)length_prevgroup >- (INT64_OR_DOUBLE)INT_MAX ||- OFLOW_MAX - *lengthptr < delta)- {- *errorcodeptr = ERR20;- return 0;- }- *lengthptr += delta;- }-- /* This is compiling for real. If there is a set first code unit- for the group, and we have not yet set a "required code unit", set- it. */-- else- {- if (groupsetfirstcu && reqcuflags >= REQ_NONE)- {- reqcu = firstcu;- reqcuflags = firstcuflags;- }- for (uint32_t i = 1; i < repeat_min; i++)- {- memcpy(code, previous, CU2BYTES(len));- code += len;- }- }- }-- if (repeat_max != REPEAT_UNLIMITED) repeat_max -= repeat_min;- }-- /* This code is common to both the zero and non-zero minimum cases. If- the maximum is limited, it replicates the group in a nested fashion,- remembering the bracket starts on a stack. In the case of a zero- minimum, the first one was set up above. In all cases the repeat_max- now specifies the number of additional copies needed. Again, we must- remember to replicate entries on the forward reference list. */-- if (repeat_max != REPEAT_UNLIMITED)- {- /* In the pre-compile phase, we don't actually do the replication. We- just adjust the length as if we had. For each repetition we must add- 1 to the length for BRAZERO and for all but the last repetition we- must add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some- paranoid checks to avoid integer overflow. The INT64_OR_DOUBLE type- is a 64-bit integer type when available, otherwise double. */-- if (lengthptr != NULL && repeat_max > 0)- {- PCRE2_SIZE delta = repeat_max*(length_prevgroup + 1 + 2 + 2*LINK_SIZE) -- 2 - 2*LINK_SIZE; /* Last one doesn't nest */- if ((INT64_OR_DOUBLE)repeat_max *- (INT64_OR_DOUBLE)(length_prevgroup + 1 + 2 + 2*LINK_SIZE)- > (INT64_OR_DOUBLE)INT_MAX ||- OFLOW_MAX - *lengthptr < delta)- {- *errorcodeptr = ERR20;- return 0;- }- *lengthptr += delta;- }-- /* This is compiling for real */-- else for (uint32_t i = repeat_max; i >= 1; i--)- {- *code++ = OP_BRAZERO + repeat_type;-- /* All but the final copy start a new nesting, maintaining the- chain of brackets outstanding. */-- if (i != 1)- {- int linkoffset;- *code++ = OP_BRA;- linkoffset = (bralink == NULL)? 0 : (int)(code - bralink);- bralink = code;- PUTINC(code, 0, linkoffset);- }-- memcpy(code, previous, CU2BYTES(len));- code += len;- }-- /* Now chain through the pending brackets, and fill in their length- fields (which are holding the chain links pro tem). */-- while (bralink != NULL)- {- int oldlinkoffset;- int linkoffset = (int)(code - bralink + 1);- PCRE2_UCHAR *bra = code - linkoffset;- oldlinkoffset = GET(bra, 1);- bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;- *code++ = OP_KET;- PUTINC(code, 0, linkoffset);- PUT(bra, 1, linkoffset);- }- }-- /* If the maximum is unlimited, set a repeater in the final copy. For- SCRIPT_RUN and ONCE brackets, that's all we need to do. However,- possessively repeated ONCE brackets can be converted into non-capturing- brackets, as the behaviour of (?:xx)++ is the same as (?>xx)++ and this- saves having to deal with possessive ONCEs specially.-- Otherwise, when we are doing the actual compile phase, check to see- whether this group is one that could match an empty string. If so,- convert the initial operator to the S form (e.g. OP_BRA -> OP_SBRA) so- that runtime checking can be done. [This check is also applied to ONCE- and SCRIPT_RUN groups at runtime, but in a different way.]-- Then, if the quantifier was possessive and the bracket is not a- conditional, we convert the BRA code to the POS form, and the KET code- to KETRPOS. (It turns out to be convenient at runtime to detect this- kind of subpattern at both the start and at the end.) The use of- special opcodes makes it possible to reduce greatly the stack usage in- pcre2_match(). If the group is preceded by OP_BRAZERO, convert this to- OP_BRAPOSZERO.-- Then, if the minimum number of matches is 1 or 0, cancel the possessive- flag so that the default action below, of wrapping everything inside- atomic brackets, does not happen. When the minimum is greater than 1,- there will be earlier copies of the group, and so we still have to wrap- the whole thing. */-- else- {- PCRE2_UCHAR *ketcode = code - 1 - LINK_SIZE;- PCRE2_UCHAR *bracode = ketcode - GET(ketcode, 1);-- /* Convert possessive ONCE brackets to non-capturing */-- if (*bracode == OP_ONCE && possessive_quantifier) *bracode = OP_BRA;-- /* For non-possessive ONCE and for SCRIPT_RUN brackets, all we need- to do is to set the KET. */-- if (*bracode == OP_ONCE || *bracode == OP_SCRIPT_RUN)- *ketcode = OP_KETRMAX + repeat_type;-- /* Handle non-SCRIPT_RUN and non-ONCE brackets and possessive ONCEs- (which have been converted to non-capturing above). */-- else- {- /* In the compile phase, adjust the opcode if the group can match- an empty string. For a conditional group with only one branch, the- value of group_return will not show "could be empty", so we must- check that separately. */-- if (lengthptr == NULL)- {- if (group_return < 0) *bracode += OP_SBRA - OP_BRA;- if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT)- *bracode = OP_SCOND;- }-- /* Handle possessive quantifiers. */-- if (possessive_quantifier)- {- /* For COND brackets, we wrap the whole thing in a possessively- repeated non-capturing bracket, because we have not invented POS- versions of the COND opcodes. */-- if (*bracode == OP_COND || *bracode == OP_SCOND)- {- int nlen = (int)(code - bracode);- (void)memmove(bracode + 1 + LINK_SIZE, bracode, CU2BYTES(nlen));- code += 1 + LINK_SIZE;- nlen += 1 + LINK_SIZE;- *bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS;- *code++ = OP_KETRPOS;- PUTINC(code, 0, nlen);- PUT(bracode, 1, nlen);- }-- /* For non-COND brackets, we modify the BRA code and use KETRPOS. */-- else- {- *bracode += 1; /* Switch to xxxPOS opcodes */- *ketcode = OP_KETRPOS;- }-- /* If the minimum is zero, mark it as possessive, then unset the- possessive flag when the minimum is 0 or 1. */-- if (brazeroptr != NULL) *brazeroptr = OP_BRAPOSZERO;- if (repeat_min < 2) possessive_quantifier = FALSE;- }-- /* Non-possessive quantifier */-- else *ketcode = OP_KETRMAX + repeat_type;- }- }- }- break;-- /* 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 the the Unicode property types will be present only when- SUPPORT_UNICODE is defined, but we don't wrap the little bits of code- here because it just makes it horribly messy. */-- default:- if (op_previous >= OP_EODN) /* Not a character type - internal error */- {- *errorcodeptr = ERR10;- return 0;- }- else- {- int prop_type, prop_value;- PCRE2_UCHAR *oldcode;-- if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;-- op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */- mclength = 0; /* Not a character */-- if (op_previous == OP_PROP || op_previous == OP_NOTPROP)- {- prop_type = previous[1];- prop_value = previous[2];- }- else- {- /* Come here from just above with a character in mcbuffer/mclength. */- OUTPUT_SINGLE_REPEAT:- prop_type = prop_value = -1;- }-- /* At this point, if prop_type == prop_value == -1 we either have a- character in mcbuffer when mclength is greater than zero, or we have- mclength zero, in which case there is a non-property character type in- op_previous. If prop_type/value are not negative, we have a property- character type in op_previous. */-- oldcode = code; /* Save where we were */- code = previous; /* Usually overwrite previous item */-- /* If the maximum is zero then the minimum must also be zero; Perl allows- this case, so we do too - by simply omitting the item altogether. */-- if (repeat_max == 0) goto END_REPEAT;-- /* Combine the op_type with the repeat_type */-- repeat_type += op_type;-- /* A minimum of zero is handled either as the special case * or ?, or as- an UPTO, with the maximum given. */-- if (repeat_min == 0)- {- if (repeat_max == REPEAT_UNLIMITED) *code++ = OP_STAR + repeat_type;- else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;- else- {- *code++ = OP_UPTO + repeat_type;- PUT2INC(code, 0, repeat_max);- }- }-- /* A repeat minimum of 1 is optimized into some special cases. If the- maximum is unlimited, we use OP_PLUS. Otherwise, the original item is- left in place and, if the maximum is greater than 1, we use OP_UPTO with- one less than the maximum. */-- else if (repeat_min == 1)- {- if (repeat_max == REPEAT_UNLIMITED)- *code++ = OP_PLUS + repeat_type;- else- {- code = oldcode; /* Leave previous item in place */- if (repeat_max == 1) goto END_REPEAT;- *code++ = OP_UPTO + repeat_type;- PUT2INC(code, 0, repeat_max - 1);- }- }-- /* The case {n,n} is just an EXACT, while the general case {n,m} is- handled as an EXACT followed by an UPTO or STAR or QUERY. */-- else- {- *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */- PUT2INC(code, 0, repeat_min);-- /* Unless repeat_max equals repeat_min, fill in the data for EXACT,- and then generate the second opcode. For a repeated Unicode property- match, there are two extra values that define the required property,- and mclength is set zero to indicate this. */-- if (repeat_max != repeat_min)- {- if (mclength > 0)- {- memcpy(code, mcbuffer, CU2BYTES(mclength));- code += mclength;- }- else- {- *code++ = op_previous;- if (prop_type >= 0)- {- *code++ = prop_type;- *code++ = prop_value;- }- }-- /* Now set up the following opcode */-- if (repeat_max == REPEAT_UNLIMITED)- *code++ = OP_STAR + repeat_type;- else- {- repeat_max -= repeat_min;- if (repeat_max == 1)- {- *code++ = OP_QUERY + repeat_type;- }- else- {- *code++ = OP_UPTO + repeat_type;- PUT2INC(code, 0, repeat_max);- }- }- }- }-- /* Fill in the character or character type for the final opcode. */-- if (mclength > 0)- {- memcpy(code, mcbuffer, CU2BYTES(mclength));- code += mclength;- }- else- {- *code++ = op_previous;- if (prop_type >= 0)- {- *code++ = prop_type;- *code++ = prop_value;- }- }- }- break;- } /* End of switch on different op_previous values */--- /* If the character following a repeat is '+', possessive_quantifier is- TRUE. For some opcodes, there are special alternative opcodes for this- case. For anything else, we wrap the entire repeated item inside OP_ONCE- brackets. Logically, the '+' notation is just syntactic sugar, taken from- Sun's Java package, but the special opcodes can optimize it.-- Some (but not all) possessively repeated subpatterns have already been- completely handled in the code just above. For them, possessive_quantifier- is always FALSE at this stage. Note that the repeated item starts at- tempcode, not at previous, which might be the first part of a string whose- (former) last char we repeated. */-- if (possessive_quantifier)- {- int len;-- /* Possessifying an EXACT quantifier has no effect, so we can ignore it.- However, QUERY, STAR, or UPTO may follow (for quantifiers such as {5,6},- {5,}, or {5,10}). We skip over an EXACT item; if the length of what- remains is greater than zero, there's a further opcode that can be- handled. If not, do nothing, leaving the EXACT alone. */-- switch(*tempcode)- {- case OP_TYPEEXACT:- tempcode += PRIV(OP_lengths)[*tempcode] +- ((tempcode[1 + IMM2_SIZE] == OP_PROP- || tempcode[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);- break;-- /* CHAR opcodes are used for exacts whose count is 1. */-- case OP_CHAR:- case OP_CHARI:- case OP_NOT:- case OP_NOTI:- case OP_EXACT:- case OP_EXACTI:- case OP_NOTEXACT:- case OP_NOTEXACTI:- tempcode += PRIV(OP_lengths)[*tempcode];-#ifdef SUPPORT_UNICODE- if (utf && HAS_EXTRALEN(tempcode[-1]))- tempcode += GET_EXTRALEN(tempcode[-1]);-#endif- break;-- /* For the class opcodes, the repeat operator appears at the end;- adjust tempcode to point to it. */-- case OP_CLASS:- case OP_NCLASS:- tempcode += 1 + 32/sizeof(PCRE2_UCHAR);- break;--#ifdef SUPPORT_WIDE_CHARS- case OP_XCLASS:- tempcode += GET(tempcode, 1);- break;-#endif- }-- /* If tempcode is equal to code (which points to the end of the repeated- item), it means we have skipped an EXACT item but there is no following- QUERY, STAR, or UPTO; the value of len will be 0, and we do nothing. In- all other cases, tempcode will be pointing to the repeat opcode, and will- be less than code, so the value of len will be greater than 0. */-- len = (int)(code - tempcode);- if (len > 0)- {- unsigned int repcode = *tempcode;-- /* There is a table for possessifying opcodes, all of which are less- than OP_CALLOUT. A zero entry means there is no possessified version.- */-- if (repcode < OP_CALLOUT && opcode_possessify[repcode] > 0)- *tempcode = opcode_possessify[repcode];-- /* For opcode without a special possessified version, wrap the item in- ONCE brackets. */-- else- {- (void)memmove(tempcode + 1 + LINK_SIZE, tempcode, CU2BYTES(len));- code += 1 + LINK_SIZE;- len += 1 + LINK_SIZE;- tempcode[0] = OP_ONCE;- *code++ = OP_KET;- PUTINC(code, 0, len);- PUT(tempcode, 1, len);- }- }- }-- /* We set the "follows varying string" flag for subsequently encountered- reqcus if it isn't already set and we have just passed a varying length- item. */-- END_REPEAT:- cb->req_varyopt |= reqvary;- break;--- /* ===================================================================*/- /* Handle a 32-bit data character with a value greater than META_END. */-- case META_BIGVALUE:- pptr++;- goto NORMAL_CHAR;--- /* ===============================================================*/- /* Handle a back reference by number, which is the meta argument. The- pattern offsets for back references to group numbers less than 10 are held- in a special vector, to avoid using more than two parsed pattern elements- in 64-bit environments. We only need the offset to the first occurrence,- because if that doesn't fail, subsequent ones will also be OK. */-- case META_BACKREF:- if (meta_arg < 10) offset = cb->small_ref_offset[meta_arg];- else GETPLUSOFFSET(offset, pptr);-- if (meta_arg > cb->bracount)- {- cb->erroroffset = offset;- *errorcodeptr = ERR15; /* Non-existent subpattern */- return 0;- }-- /* Come here from named backref handling when the reference is to a- single group (that is, not to a duplicated name). The back reference- data will have already been updated. We must disable firstcu if not- set, to cope with cases like (?=(\w+))\1: which would otherwise set ':'- later. */-- HANDLE_SINGLE_REFERENCE:- if (firstcuflags == REQ_UNSET) zerofirstcuflags = firstcuflags = REQ_NONE;- *code++ = ((options & PCRE2_CASELESS) != 0)? OP_REFI : OP_REF;- PUT2INC(code, 0, meta_arg);-- /* Update the map of back references, and keep the highest one. We- could do this in parse_regex() for numerical back references, but not- for named back references, because we don't know the numbers to which- named back references refer. So we do it all in this function. */-- cb->backref_map |= (meta_arg < 32)? (1u << meta_arg) : 1;- if (meta_arg > cb->top_backref) cb->top_backref = meta_arg;- break;--- /* ===============================================================*/- /* Handle recursion by inserting the number of the called group (which is- the meta argument) after OP_RECURSE. At the end of compiling the pattern is- scanned and these numbers are replaced by offsets within the pattern. It is- done like this to avoid problems with forward references and adjusting- offsets when groups are duplicated and moved (as discovered in previous- implementations). Note that a recursion does not have a set first- character. */-- case META_RECURSE:- GETPLUSOFFSET(offset, pptr);- if (meta_arg > cb->bracount)- {- cb->erroroffset = offset;- *errorcodeptr = ERR15; /* Non-existent subpattern */- return 0;- }- HANDLE_NUMERICAL_RECURSION:- *code = OP_RECURSE;- PUT(code, 1, meta_arg);- code += 1 + LINK_SIZE;- groupsetfirstcu = FALSE;- cb->had_recurse = TRUE;- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;- zerofirstcu = firstcu;- zerofirstcuflags = firstcuflags;- break;--- /* ===============================================================*/- /* Handle capturing parentheses; the number is the meta argument. */-- case META_CAPTURE:- bravalue = OP_CBRA;- skipunits = IMM2_SIZE;- PUT2(code, 1+LINK_SIZE, meta_arg);- cb->lastcapture = meta_arg;- goto GROUP_PROCESS_NOTE_EMPTY;--- /* ===============================================================*/- /* Handle escape sequence items. For ones like \d, the ESC_values are- arranged to be the same as the corresponding OP_values in the default case- when PCRE2_UCP is not set (which is the only case in which they will appear- here).-- Note: \Q and \E are never seen here, as they were dealt with in- parse_pattern(). Neither are numerical back references or recursions, which- were turned into META_BACKREF or META_RECURSE items, respectively. \k and- \g, when followed by names, are turned into META_BACKREF_BYNAME or- META_RECURSE_BYNAME. */-- case META_ESCAPE:-- /* We can test for escape sequences that consume a character because their- values lie between ESC_b and ESC_Z; this may have to change if any new ones- are ever created. For these sequences, we disable the setting of a first- character if it hasn't already been set. */-- if (meta_arg > ESC_b && meta_arg < ESC_Z)- {- matched_char = TRUE;- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;- }-- /* Set values to reset to if this is followed by a zero repeat. */-- zerofirstcu = firstcu;- zerofirstcuflags = firstcuflags;- zeroreqcu = reqcu;- zeroreqcuflags = reqcuflags;-- /* If Unicode is not supported, \P and \p are not allowed and are- faulted at parse time, so will never appear here. */--#ifdef SUPPORT_UNICODE- if (meta_arg == ESC_P || meta_arg == ESC_p)- {- uint32_t ptype = *(++pptr) >> 16;- uint32_t pdata = *pptr & 0xffff;-- /* The special case of \p{Any} is compiled to OP_ALLANY so as to benefit- from the auto-anchoring code. */-- if (meta_arg == ESC_p && ptype == PT_ANY)- {- *code++ = OP_ALLANY;- }- else- {- *code++ = (meta_arg == ESC_p)? OP_PROP : OP_NOTPROP;- *code++ = ptype;- *code++ = pdata;- }- break; /* End META_ESCAPE */- }-#endif-- /* \K is forbidden in lookarounds since 10.38 because that's what Perl has- done. However, there's an option, in case anyone was relying on it. */-- if (cb->assert_depth > 0 && meta_arg == ESC_K &&- (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) == 0)- {- *errorcodeptr = ERR99;- return 0;- }-- /* For the rest (including \X when Unicode is supported - if not it's- faulted at parse time), the OP value is the escape value when PCRE2_UCP is- not set; if it is set, these escapes do not show up here because they are- converted into Unicode property tests in parse_regex(). Note that \b and \B- do a one-character lookbehind, and \A also behaves as if it does. */-- if (meta_arg == ESC_C) cb->external_flags |= PCRE2_HASBKC; /* Record */- if ((meta_arg == ESC_b || meta_arg == ESC_B || meta_arg == ESC_A) &&- cb->max_lookbehind == 0)- cb->max_lookbehind = 1;-- /* In non-UTF mode, and for both 32-bit modes, we turn \C into OP_ALLANY- instead of OP_ANYBYTE so that it works in DFA mode and in lookbehinds. */--#if PCRE2_CODE_UNIT_WIDTH == 32- *code++ = (meta_arg == ESC_C)? OP_ALLANY : meta_arg;-#else- *code++ = (!utf && meta_arg == ESC_C)? OP_ALLANY : meta_arg;-#endif- break; /* End META_ESCAPE */--- /* ===================================================================*/- /* Handle an unrecognized meta value. A parsed pattern value less than- META_END is a literal. Otherwise we have a problem. */-- default:- if (meta >= META_END)- {-#ifdef DEBUG_SHOW_PARSED- fprintf(stderr, "** Unrecognized parsed pattern item 0x%.8x\n", *pptr);-#endif- *errorcodeptr = ERR89; /* Internal error - unrecognized. */- return 0;- }-- /* Handle a literal character. We come here by goto in the case of a- 32-bit, non-UTF character whose value is greater than META_END. */-- NORMAL_CHAR:- meta = *pptr; /* Get the full 32 bits */- NORMAL_CHAR_SET: /* Character is already in meta */- matched_char = TRUE;-- /* For caseless UTF or UCP mode, check whether this character has more than- one other case. If so, generate a special OP_PROP item instead of OP_CHARI.- */--#ifdef SUPPORT_UNICODE- if ((utf||ucp) && (options & PCRE2_CASELESS) != 0)- {- uint32_t caseset = UCD_CASESET(meta);- if (caseset != 0)- {- *code++ = OP_PROP;- *code++ = PT_CLIST;- *code++ = caseset;- if (firstcuflags == REQ_UNSET)- firstcuflags = zerofirstcuflags = REQ_NONE;- break; /* End handling this meta item */- }- }-#endif-- /* Caseful matches, or caseless and not one of the multicase characters. We- come here by goto in the case of a positive class that contains only- case-partners of a character with just two cases; matched_char has already- been set TRUE and options fudged if necessary. */-- CLASS_CASELESS_CHAR:-- /* Get the character's code units into mcbuffer, with the length in- mclength. When not in UTF mode, the length is always 1. */--#ifdef SUPPORT_UNICODE- if (utf) mclength = PRIV(ord2utf)(meta, mcbuffer); else-#endif- {- mclength = 1;- mcbuffer[0] = meta;- }-- /* Generate the appropriate code */-- *code++ = ((options & PCRE2_CASELESS) != 0)? OP_CHARI : OP_CHAR;- memcpy(code, mcbuffer, CU2BYTES(mclength));- code += mclength;-- /* Remember if \r or \n were seen */-- if (mcbuffer[0] == CHAR_CR || mcbuffer[0] == CHAR_NL)- cb->external_flags |= PCRE2_HASCRORLF;-- /* Set the first and required code units appropriately. If no previous- first code unit, set it from this character, but revert to none on a zero- repeat. Otherwise, leave the firstcu value alone, and don't change it on- a zero repeat. */-- if (firstcuflags == REQ_UNSET)- {- zerofirstcuflags = REQ_NONE;- zeroreqcu = reqcu;- zeroreqcuflags = reqcuflags;-- /* If the character is more than one code unit long, we can set a single- firstcu only if it is not to be matched caselessly. Multiple possible- starting code units may be picked up later in the studying code. */-- if (mclength == 1 || req_caseopt == 0)- {- firstcu = mcbuffer[0];- firstcuflags = req_caseopt;- if (mclength != 1)- {- reqcu = code[-1];- reqcuflags = cb->req_varyopt;- }- }- else firstcuflags = reqcuflags = REQ_NONE;- }-- /* firstcu was previously set; we can set reqcu only if the length is- 1 or the matching is caseful. */-- else- {- zerofirstcu = firstcu;- zerofirstcuflags = firstcuflags;- zeroreqcu = reqcu;- zeroreqcuflags = reqcuflags;- if (mclength == 1 || req_caseopt == 0)- {- reqcu = code[-1];- reqcuflags = req_caseopt | cb->req_varyopt;- }- }-- /* If caselessness was temporarily instated, reset it. */-- if (reset_caseful)- {- options &= ~PCRE2_CASELESS;- req_caseopt = 0;- reset_caseful = FALSE;- }-- break; /* End literal character handling */- } /* End of big switch */- } /* End of big loop */--/* Control never reaches here. */-}----/*************************************************-* Compile regex: a sequence of alternatives *-*************************************************/--/* On entry, pptr is pointing past the bracket meta, but on return it points to-the closing bracket or META_END. The code variable is pointing at the code unit-into which the BRA operator has been stored. This function is used during the-pre-compile phase when we are trying to find out the amount of memory needed,-as well as during the real compile phase. The value of lengthptr distinguishes-the two phases.--Arguments:- options option bits, including any changes for this subpattern- codeptr -> the address of the current code pointer- pptrptr -> the address of the current parsed pattern pointer- errorcodeptr -> pointer to error code variable- skipunits skip this many code units at start (for brackets and OP_COND)- firstcuptr place to put the first required code unit- firstcuflagsptr place to put the first code unit flags- reqcuptr place to put the last required code unit- reqcuflagsptr place to put the last required code unit flags- bcptr pointer to the chain of currently open branches- cb points to the data block with tables pointers etc.- lengthptr NULL during the real compile phase- points to length accumulator during pre-compile phase--Returns: 0 There has been an error- +1 Success, this group must match at least one character- -1 Success, this group may match an empty string-*/--static int-compile_regex(uint32_t options, PCRE2_UCHAR **codeptr, uint32_t **pptrptr,- int *errorcodeptr, uint32_t skipunits, uint32_t *firstcuptr,- uint32_t *firstcuflagsptr, uint32_t *reqcuptr, uint32_t *reqcuflagsptr,- branch_chain *bcptr, compile_block *cb, PCRE2_SIZE *lengthptr)-{-PCRE2_UCHAR *code = *codeptr;-PCRE2_UCHAR *last_branch = code;-PCRE2_UCHAR *start_bracket = code;-BOOL lookbehind;-open_capitem capitem;-int capnumber = 0;-int okreturn = 1;-uint32_t *pptr = *pptrptr;-uint32_t firstcu, reqcu;-uint32_t lookbehindlength;-uint32_t firstcuflags, reqcuflags;-uint32_t branchfirstcu, branchreqcu;-uint32_t branchfirstcuflags, branchreqcuflags;-PCRE2_SIZE length;-branch_chain bc;--/* If set, call the external function that checks for stack availability. */--if (cb->cx->stack_guard != NULL &&- cb->cx->stack_guard(cb->parens_depth, cb->cx->stack_guard_data))- {- *errorcodeptr= ERR33;- return 0;- }--/* Miscellaneous initialization */--bc.outer = bcptr;-bc.current_branch = code;--firstcu = reqcu = 0;-firstcuflags = reqcuflags = REQ_UNSET;--/* Accumulate the length for use in the pre-compile phase. Start with the-length of the BRA and KET and any extra code units that are required at the-beginning. We accumulate in a local variable to save frequent testing of-lengthptr for NULL. We cannot do this by looking at the value of 'code' at the-start and end of each alternative, because compiled items are discarded during-the pre-compile phase so that the workspace is not exceeded. */--length = 2 + 2*LINK_SIZE + skipunits;--/* Remember if this is a lookbehind assertion, and if it is, save its length-and skip over the pattern offset. */--lookbehind = *code == OP_ASSERTBACK ||- *code == OP_ASSERTBACK_NOT ||- *code == OP_ASSERTBACK_NA;--if (lookbehind)- {- lookbehindlength = META_DATA(pptr[-1]);- pptr += SIZEOFFSET;- }-else lookbehindlength = 0;--/* If this is a capturing subpattern, add to the chain of open capturing items-so that we can detect them if (*ACCEPT) is encountered. Note that only OP_CBRA-need be tested here; changing this opcode to one of its variants, e.g.-OP_SCBRAPOS, happens later, after the group has been compiled. */--if (*code == OP_CBRA)- {- capnumber = GET2(code, 1 + LINK_SIZE);- capitem.number = capnumber;- capitem.next = cb->open_caps;- capitem.assert_depth = cb->assert_depth;- cb->open_caps = &capitem;- }--/* Offset is set zero to mark that this bracket is still open */--PUT(code, 1, 0);-code += 1 + LINK_SIZE + skipunits;--/* Loop for each alternative branch */--for (;;)- {- int branch_return;-- /* Insert OP_REVERSE if this is as lookbehind assertion. */-- if (lookbehind && lookbehindlength > 0)- {- *code++ = OP_REVERSE;- PUTINC(code, 0, lookbehindlength);- length += 1 + LINK_SIZE;- }-- /* Now compile the branch; in the pre-compile phase its length gets added- into the length. */-- if ((branch_return =- compile_branch(&options, &code, &pptr, errorcodeptr, &branchfirstcu,- &branchfirstcuflags, &branchreqcu, &branchreqcuflags, &bc,- cb, (lengthptr == NULL)? NULL : &length)) == 0)- return 0;-- /* If a branch can match an empty string, so can the whole group. */-- if (branch_return < 0) okreturn = -1;-- /* In the real compile phase, there is some post-processing to be done. */-- if (lengthptr == NULL)- {- /* If this is the first branch, the firstcu and reqcu values for the- branch become the values for the regex. */-- if (*last_branch != OP_ALT)- {- firstcu = branchfirstcu;- firstcuflags = branchfirstcuflags;- reqcu = branchreqcu;- reqcuflags = branchreqcuflags;- }-- /* If this is not the first branch, the first char and reqcu have to- match the values from all the previous branches, except that if the- previous value for reqcu didn't have REQ_VARY set, it can still match,- and we set REQ_VARY for the group from this branch's value. */-- else- {- /* If we previously had a firstcu, but it doesn't match the new branch,- we have to abandon the firstcu for the regex, but if there was- previously no reqcu, it takes on the value of the old firstcu. */-- if (firstcuflags != branchfirstcuflags || firstcu != branchfirstcu)- {- if (firstcuflags < REQ_NONE)- {- if (reqcuflags >= REQ_NONE)- {- reqcu = firstcu;- reqcuflags = firstcuflags;- }- }- firstcuflags = REQ_NONE;- }-- /* If we (now or from before) have no firstcu, a firstcu from the- branch becomes a reqcu if there isn't a branch reqcu. */-- if (firstcuflags >= REQ_NONE && branchfirstcuflags < REQ_NONE &&- branchreqcuflags >= REQ_NONE)- {- branchreqcu = branchfirstcu;- branchreqcuflags = branchfirstcuflags;- }-- /* Now ensure that the reqcus match */-- if (((reqcuflags & ~REQ_VARY) != (branchreqcuflags & ~REQ_VARY)) ||- reqcu != branchreqcu)- reqcuflags = REQ_NONE;- else- {- reqcu = branchreqcu;- reqcuflags |= branchreqcuflags; /* To "or" REQ_VARY if present */- }- }- }-- /* Handle reaching the end of the expression, either ')' or end of pattern.- In the real compile phase, go back through the alternative branches and- reverse the chain of offsets, with the field in the BRA item now becoming an- offset to the first alternative. If there are no alternatives, it points to- the end of the group. The length in the terminating ket is always the length- of the whole bracketed item. Return leaving the pointer at the terminating- char. */-- if (META_CODE(*pptr) != META_ALT)- {- if (lengthptr == NULL)- {- PCRE2_SIZE branch_length = code - last_branch;- do- {- PCRE2_SIZE prev_length = GET(last_branch, 1);- PUT(last_branch, 1, branch_length);- branch_length = prev_length;- last_branch -= branch_length;- }- while (branch_length > 0);- }-- /* Fill in the ket */-- *code = OP_KET;- PUT(code, 1, (int)(code - start_bracket));- code += 1 + LINK_SIZE;-- /* If it was a capturing subpattern, remove the block from the chain. */-- if (capnumber > 0) cb->open_caps = cb->open_caps->next;-- /* Set values to pass back */-- *codeptr = code;- *pptrptr = pptr;- *firstcuptr = firstcu;- *firstcuflagsptr = firstcuflags;- *reqcuptr = reqcu;- *reqcuflagsptr = reqcuflags;- if (lengthptr != NULL)- {- if (OFLOW_MAX - *lengthptr < length)- {- *errorcodeptr = ERR20;- return 0;- }- *lengthptr += length;- }- return okreturn;- }-- /* Another branch follows. In the pre-compile phase, we can move the code- pointer back to where it was for the start of the first branch. (That is,- pretend that each branch is the only one.)-- In the real compile phase, insert an ALT node. Its length field points back- to the previous branch while the bracket remains open. At the end the chain- is reversed. It's done like this so that the start of the bracket has a- zero offset until it is closed, making it possible to detect recursion. */-- if (lengthptr != NULL)- {- code = *codeptr + 1 + LINK_SIZE + skipunits;- length += 1 + LINK_SIZE;- }- else- {- *code = OP_ALT;- PUT(code, 1, (int)(code - last_branch));- bc.current_branch = last_branch = code;- code += 1 + LINK_SIZE;- }-- /* Set the lookbehind length (if not in a lookbehind the value will be zero)- and then advance past the vertical bar. */-- lookbehindlength = META_DATA(*pptr);- pptr++;- }-/* Control never reaches here */-}----/*************************************************-* Check for anchored pattern *-*************************************************/--/* Try to find out if this is an anchored regular expression. Consider each-alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket-all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then-it's anchored. However, if this is a multiline pattern, then only OP_SOD will-be found, because ^ generates OP_CIRCM in that mode.--We can also consider a regex to be anchored if OP_SOM starts all its branches.-This is the code for \G, which means "match at start of match position, taking-into account the match offset".--A branch is also implicitly anchored if it starts with .* and DOTALL is set,-because that will try the rest of the pattern at all possible matching points,-so there is no point trying again.... er ....--.... except when the .* appears inside capturing parentheses, and there is a-subsequent back reference to those parentheses. We haven't enough information-to catch that case precisely.--At first, the best we could do was to detect when .* was in capturing brackets-and the highest back reference was greater than or equal to that level.-However, by keeping a bitmap of the first 31 back references, we can catch some-of the more common cases more precisely.--... A second exception is when the .* appears inside an atomic group, because-this prevents the number of characters it matches from being adjusted.--Arguments:- code points to start of the compiled pattern- bracket_map a bitmap of which brackets we are inside while testing; this- handles up to substring 31; after that we just have to take- the less precise approach- cb points to the compile data block- atomcount atomic group level- inassert TRUE if in an assertion--Returns: TRUE or FALSE-*/--static BOOL-is_anchored(PCRE2_SPTR code, uint32_t bracket_map, compile_block *cb,- int atomcount, BOOL inassert)-{-do {- PCRE2_SPTR scode = first_significant_code(- code + PRIV(OP_lengths)[*code], FALSE);- int op = *scode;-- /* Non-capturing brackets */-- if (op == OP_BRA || op == OP_BRAPOS ||- op == OP_SBRA || op == OP_SBRAPOS)- {- if (!is_anchored(scode, bracket_map, cb, atomcount, inassert))- return FALSE;- }-- /* Capturing brackets */-- else if (op == OP_CBRA || op == OP_CBRAPOS ||- op == OP_SCBRA || op == OP_SCBRAPOS)- {- int n = GET2(scode, 1+LINK_SIZE);- uint32_t new_map = bracket_map | ((n < 32)? (1u << n) : 1);- if (!is_anchored(scode, new_map, cb, atomcount, inassert)) return FALSE;- }-- /* Positive forward assertion */-- else if (op == OP_ASSERT || op == OP_ASSERT_NA)- {- if (!is_anchored(scode, bracket_map, cb, atomcount, TRUE)) return FALSE;- }-- /* Condition. If there is no second branch, it can't be anchored. */-- else if (op == OP_COND || op == OP_SCOND)- {- if (scode[GET(scode,1)] != OP_ALT) return FALSE;- if (!is_anchored(scode, bracket_map, cb, atomcount, inassert))- return FALSE;- }-- /* Atomic groups */-- else if (op == OP_ONCE)- {- if (!is_anchored(scode, bracket_map, cb, atomcount + 1, inassert))- return FALSE;- }-- /* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and- it isn't in brackets that are or may be referenced or inside an atomic- group or an assertion. Also the pattern must not contain *PRUNE or *SKIP,- because these break the feature. Consider, for example, /(?s).*?(*PRUNE)b/- with the subject "aab", which matches "b", i.e. not at the start of a line.- There is also an option that disables auto-anchoring. */-- else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR ||- op == OP_TYPEPOSSTAR))- {- if (scode[1] != OP_ALLANY || (bracket_map & cb->backref_map) != 0 ||- atomcount > 0 || cb->had_pruneorskip || inassert ||- (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)- return FALSE;- }-- /* Check for explicit anchoring */-- else if (op != OP_SOD && op != OP_SOM && op != OP_CIRC) return FALSE;-- code += GET(code, 1);- }-while (*code == OP_ALT); /* Loop for each alternative */-return TRUE;-}----/*************************************************-* Check for starting with ^ or .* *-*************************************************/--/* This is called to find out if every branch starts with ^ or .* so that-"first char" processing can be done to speed things up in multiline-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 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 the compiled pattern or a group- bracket_map a bitmap of which brackets we are inside while testing; this- handles up to substring 31; after that we just have to take- the less precise approach- cb points to the compile data- atomcount atomic group level- inassert TRUE if in an assertion--Returns: TRUE or FALSE-*/--static BOOL-is_startline(PCRE2_SPTR code, unsigned int bracket_map, compile_block *cb,- int atomcount, BOOL inassert)-{-do {- PCRE2_SPTR scode = first_significant_code(- code + PRIV(OP_lengths)[*code], FALSE);- int op = *scode;-- /* If we are at the start of a conditional assertion group, *both* the- conditional assertion *and* what follows the condition must satisfy the test- for start of line. Other kinds of condition fail. Note that there may be an- auto-callout at the start of a condition. */-- if (op == OP_COND)- {- scode += 1 + LINK_SIZE;-- if (*scode == OP_CALLOUT) scode += PRIV(OP_lengths)[OP_CALLOUT];- else if (*scode == OP_CALLOUT_STR) scode += GET(scode, 1 + 2*LINK_SIZE);-- switch (*scode)- {- case OP_CREF:- case OP_DNCREF:- case OP_RREF:- case OP_DNRREF:- case OP_FAIL:- case OP_FALSE:- case OP_TRUE:- return FALSE;-- default: /* Assertion */- if (!is_startline(scode, bracket_map, cb, atomcount, TRUE)) return FALSE;- do scode += GET(scode, 1); while (*scode == OP_ALT);- scode += 1 + LINK_SIZE;- break;- }- scode = first_significant_code(scode, FALSE);- op = *scode;- }-- /* Non-capturing brackets */-- if (op == OP_BRA || op == OP_BRAPOS ||- op == OP_SBRA || op == OP_SBRAPOS)- {- if (!is_startline(scode, bracket_map, cb, atomcount, inassert))- return FALSE;- }-- /* Capturing brackets */-- else if (op == OP_CBRA || op == OP_CBRAPOS ||- op == OP_SCBRA || op == OP_SCBRAPOS)- {- int n = GET2(scode, 1+LINK_SIZE);- int new_map = bracket_map | ((n < 32)? (1u << n) : 1);- if (!is_startline(scode, new_map, cb, atomcount, inassert)) return FALSE;- }-- /* Positive forward assertions */-- else if (op == OP_ASSERT || op == OP_ASSERT_NA)- {- if (!is_startline(scode, bracket_map, cb, atomcount, TRUE))- return FALSE;- }-- /* Atomic brackets */-- else if (op == OP_ONCE)- {- if (!is_startline(scode, bracket_map, cb, 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 or an assertion, and 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. There is also an option that disables this- optimization. */-- else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)- {- if (scode[1] != OP_ANY || (bracket_map & cb->backref_map) != 0 ||- atomcount > 0 || cb->had_pruneorskip || inassert ||- (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)- return FALSE;- }-- /* Check for explicit circumflex; anything else gives a FALSE result. Note- in particular that this includes atomic brackets OP_ONCE because the number- of characters matched by .* cannot be adjusted inside them. */-- else if (op != OP_CIRC && op != OP_CIRCM) return FALSE;-- /* Move on to the next alternative */-- code += GET(code, 1);- }-while (*code == OP_ALT); /* Loop for each alternative */-return TRUE;-}----/*************************************************-* Scan compiled regex for recursion reference *-*************************************************/--/* This function scans through a compiled pattern until it finds an instance of-OP_RECURSE.--Arguments:- code points to start of expression- utf TRUE in UTF mode--Returns: pointer to the opcode for OP_RECURSE, or NULL if not found-*/--static PCRE2_SPTR-find_recurse(PCRE2_SPTR code, BOOL utf)-{-for (;;)- {- PCRE2_UCHAR c = *code;- if (c == OP_END) return NULL;- if (c == OP_RECURSE) return code;-- /* XCLASS is used for classes that cannot be represented just by a bit map.- This includes negated single high-valued characters. CALLOUT_STR is used for- callouts with string arguments. In both cases the length in the table is- zero; the actual length is stored in the compiled code. */-- if (c == OP_XCLASS) code += GET(code, 1);- else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE);-- /* Otherwise, we can get the item's length from the table, except that for- repeated character types, we have to test for \p and \P, which have an extra- two code units of parameters, and for MARK/PRUNE/SKIP/THEN with an argument,- we must add in its length. */-- else- {- switch(c)- {- case OP_TYPESTAR:- case OP_TYPEMINSTAR:- case OP_TYPEPLUS:- case OP_TYPEMINPLUS:- case OP_TYPEQUERY:- case OP_TYPEMINQUERY:- case OP_TYPEPOSSTAR:- case OP_TYPEPOSPLUS:- case OP_TYPEPOSQUERY:- if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;- break;-- case OP_TYPEPOSUPTO:- case OP_TYPEUPTO:- case OP_TYPEMINUPTO:- case OP_TYPEEXACT:- if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)- code += 2;- break;-- case OP_MARK:- case OP_COMMIT_ARG:- case OP_PRUNE_ARG:- case OP_SKIP_ARG:- case OP_THEN_ARG:- code += code[1];- break;- }-- /* Add in the fixed length from the table */-- code += PRIV(OP_lengths)[c];-- /* In UTF-8 and UTF-16 modes, opcodes that are followed by a character may- be followed by a multi-unit character. The length in the table is a- minimum, so we have to arrange to skip the extra units. */--#ifdef MAYBE_UTF_MULTI- if (utf) switch(c)- {- case OP_CHAR:- case OP_CHARI:- case OP_NOT:- case OP_NOTI:- case OP_EXACT:- case OP_EXACTI:- case OP_NOTEXACT:- case OP_NOTEXACTI:- case OP_UPTO:- case OP_UPTOI:- case OP_NOTUPTO:- case OP_NOTUPTOI:- case OP_MINUPTO:- case OP_MINUPTOI:- case OP_NOTMINUPTO:- case OP_NOTMINUPTOI:- case OP_POSUPTO:- case OP_POSUPTOI:- case OP_NOTPOSUPTO:- case OP_NOTPOSUPTOI:- case OP_STAR:- case OP_STARI:- case OP_NOTSTAR:- case OP_NOTSTARI:- case OP_MINSTAR:- case OP_MINSTARI:- case OP_NOTMINSTAR:- case OP_NOTMINSTARI:- case OP_POSSTAR:- case OP_POSSTARI:- case OP_NOTPOSSTAR:- case OP_NOTPOSSTARI:- case OP_PLUS:- case OP_PLUSI:- case OP_NOTPLUS:- case OP_NOTPLUSI:- case OP_MINPLUS:- case OP_MINPLUSI:- case OP_NOTMINPLUS:- case OP_NOTMINPLUSI:- case OP_POSPLUS:- case OP_POSPLUSI:- case OP_NOTPOSPLUS:- case OP_NOTPOSPLUSI:- case OP_QUERY:- case OP_QUERYI:- case OP_NOTQUERY:- case OP_NOTQUERYI:- case OP_MINQUERY:- case OP_MINQUERYI:- case OP_NOTMINQUERY:- case OP_NOTMINQUERYI:- case OP_POSQUERY:- case OP_POSQUERYI:- case OP_NOTPOSQUERY:- case OP_NOTPOSQUERYI:- if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);- break;- }-#else- (void)(utf); /* Keep compiler happy by referencing function argument */-#endif /* MAYBE_UTF_MULTI */- }- }-}----/*************************************************-* Check for asserted fixed first code unit *-*************************************************/--/* During compilation, the "first code unit" settings from forward assertions-are discarded, because they can cause conflicts with actual literals that-follow. However, if we end up without a first code unit setting for an-unanchored pattern, it is worth scanning the regex to see if there is an-initial asserted first code unit. If all branches start with the same asserted-code unit, or with a non-conditional bracket all of whose alternatives start-with the same asserted code unit (recurse ad lib), then we return that code-unit, with the flags set to zero or REQ_CASELESS; otherwise return zero with-REQ_NONE in the flags.--Arguments:- code points to start of compiled pattern- flags points to the first code unit flags- inassert non-zero if in an assertion--Returns: the fixed first code unit, or 0 with REQ_NONE in flags-*/--static uint32_t-find_firstassertedcu(PCRE2_SPTR code, uint32_t *flags, uint32_t inassert)-{-uint32_t c = 0;-uint32_t cflags = REQ_NONE;--*flags = REQ_NONE;-do {- uint32_t d;- uint32_t dflags;- int xl = (*code == OP_CBRA || *code == OP_SCBRA ||- *code == OP_CBRAPOS || *code == OP_SCBRAPOS)? IMM2_SIZE:0;- PCRE2_SPTR scode = first_significant_code(code + 1+LINK_SIZE + xl, TRUE);- PCRE2_UCHAR op = *scode;-- switch(op)- {- default:- return 0;-- case OP_BRA:- case OP_BRAPOS:- case OP_CBRA:- case OP_SCBRA:- case OP_CBRAPOS:- case OP_SCBRAPOS:- case OP_ASSERT:- case OP_ASSERT_NA:- case OP_ONCE:- case OP_SCRIPT_RUN:- d = find_firstassertedcu(scode, &dflags, inassert +- ((op == OP_ASSERT || op == OP_ASSERT_NA)?1:0));- if (dflags >= REQ_NONE) return 0;- if (cflags >= REQ_NONE) { c = d; cflags = dflags; }- else if (c != d || cflags != dflags) return 0;- break;-- case OP_EXACT:- scode += IMM2_SIZE;- /* Fall through */-- case OP_CHAR:- case OP_PLUS:- case OP_MINPLUS:- case OP_POSPLUS:- if (inassert == 0) return 0;- if (cflags >= REQ_NONE) { c = scode[1]; cflags = 0; }- else if (c != scode[1]) return 0;- break;-- case OP_EXACTI:- scode += IMM2_SIZE;- /* Fall through */-- case OP_CHARI:- case OP_PLUSI:- case OP_MINPLUSI:- case OP_POSPLUSI:- if (inassert == 0) return 0;-- /* If the character is more than one code unit long, we cannot set its- first code unit when matching caselessly. Later scanning may pick up- multiple code units. */--#ifdef SUPPORT_UNICODE-#if PCRE2_CODE_UNIT_WIDTH == 8- if (scode[1] >= 0x80) return 0;-#elif PCRE2_CODE_UNIT_WIDTH == 16- if (scode[1] >= 0xd800 && scode[1] <= 0xdfff) return 0;-#endif-#endif-- if (cflags >= REQ_NONE) { c = scode[1]; cflags = REQ_CASELESS; }- else if (c != scode[1]) return 0;- break;- }-- code += GET(code, 1);- }-while (*code == OP_ALT);--*flags = cflags;-return c;-}----/*************************************************-* Add an entry to the name/number table *-*************************************************/--/* This function is called between compiling passes to add an entry to the-name/number table, maintaining alphabetical order. Checking for permitted-and forbidden duplicates has already been done.--Arguments:- cb the compile data block- name the name to add- length the length of the name- groupno the group number- tablecount the count of names in the table so far--Returns: nothing-*/--static void-add_name_to_table(compile_block *cb, PCRE2_SPTR name, int length,- unsigned int groupno, uint32_t tablecount)-{-uint32_t i;-PCRE2_UCHAR *slot = cb->name_table;--for (i = 0; i < tablecount; i++)- {- int crc = memcmp(name, slot+IMM2_SIZE, CU2BYTES(length));- if (crc == 0 && slot[IMM2_SIZE+length] != 0)- crc = -1; /* Current name is a substring */-- /* Make space in the table and break the loop for an earlier name. For a- duplicate or later name, carry on. We do this for duplicates so that in the- simple case (when ?(| is not used) they are in order of their numbers. In all- cases they are in the order in which they appear in the pattern. */-- if (crc < 0)- {- (void)memmove(slot + cb->name_entry_size, slot,- CU2BYTES((tablecount - i) * cb->name_entry_size));- break;- }-- /* Continue the loop for a later or duplicate name */-- slot += cb->name_entry_size;- }--PUT2(slot, 0, groupno);-memcpy(slot + IMM2_SIZE, name, CU2BYTES(length));--/* Add a terminating zero and fill the rest of the slot with zeroes so that-the memory is all initialized. Otherwise valgrind moans about uninitialized-memory when saving serialized compiled patterns. */--memset(slot + IMM2_SIZE + length, 0,- CU2BYTES(cb->name_entry_size - length - IMM2_SIZE));-}----/*************************************************-* Skip in parsed pattern *-*************************************************/--/* This function is called to skip parts of the parsed pattern when finding the-length of a lookbehind branch. It is called after (*ACCEPT) and (*FAIL) to find-the end of the branch, it is called to skip over an internal lookaround or-(DEFINE) group, and it is also called to skip to the end of a class, during-which it will never encounter nested groups (but there's no need to have-special code for that).--When called to find the end of a branch or group, pptr must point to the first-meta code inside the branch, not the branch-starting code. In other cases it-can point to the item that causes the function to be called.--Arguments:- pptr current pointer to skip from- skiptype PSKIP_CLASS when skipping to end of class- PSKIP_ALT when META_ALT ends the skip- PSKIP_KET when only META_KET ends the skip--Returns: new value of pptr- NULL if META_END is reached - should never occur- or for an unknown meta value - likewise-*/--static uint32_t *-parsed_skip(uint32_t *pptr, uint32_t skiptype)-{-uint32_t nestlevel = 0;--for (;; pptr++)- {- uint32_t meta = META_CODE(*pptr);-- switch(meta)- {- default: /* Just skip over most items */- if (meta < META_END) continue; /* Literal */- break;-- /* This should never occur. */-- case META_END:- return NULL;-- /* The data for these items is variable in length. */-- case META_BACKREF: /* Offset is present only if group >= 10 */- if (META_DATA(*pptr) >= 10) pptr += SIZEOFFSET;- break;-- case META_ESCAPE: /* A few escapes are followed by data items. */- switch (META_DATA(*pptr))- {- case ESC_P:- case ESC_p:- pptr += 1;- break;-- case ESC_g:- case ESC_k:- pptr += 1 + SIZEOFFSET;- break;- }- break;-- case META_MARK: /* Add the length of the name. */- case META_COMMIT_ARG:- case META_PRUNE_ARG:- case META_SKIP_ARG:- case META_THEN_ARG:- pptr += pptr[1];- break;-- /* These are the "active" items in this loop. */-- case META_CLASS_END:- if (skiptype == PSKIP_CLASS) return pptr;- break;-- case META_ATOMIC:- case META_CAPTURE:- case META_COND_ASSERT:- case META_COND_DEFINE:- case META_COND_NAME:- case META_COND_NUMBER:- case META_COND_RNAME:- case META_COND_RNUMBER:- case META_COND_VERSION:- case META_LOOKAHEAD:- case META_LOOKAHEADNOT:- case META_LOOKAHEAD_NA:- case META_LOOKBEHIND:- case META_LOOKBEHINDNOT:- case META_LOOKBEHIND_NA:- case META_NOCAPTURE:- case META_SCRIPT_RUN:- nestlevel++;- break;-- case META_ALT:- if (nestlevel == 0 && skiptype == PSKIP_ALT) return pptr;- break;-- case META_KET:- if (nestlevel == 0) return pptr;- nestlevel--;- break;- }-- /* The extra data item length for each meta is in a table. */-- meta = (meta >> 16) & 0x7fff;- if (meta >= sizeof(meta_extra_lengths)) return NULL;- pptr += meta_extra_lengths[meta];- }-/* Control never reaches here */-return pptr;-}----/*************************************************-* Find length of a parsed group *-*************************************************/--/* This is called for nested groups within a branch of a lookbehind whose-length is being computed. If all the branches in the nested group have the same-length, that is OK. On entry, the pointer must be at the first element after-the group initializing code. On exit it points to OP_KET. Caching is used to-improve processing speed when the same capturing group occurs many times.--Arguments:- pptrptr pointer to pointer in the parsed pattern- isinline FALSE if a reference or recursion; TRUE for inline group- errcodeptr pointer to the errorcode- lcptr pointer to the loop counter- group number of captured group or -1 for a non-capturing group- recurses chain of recurse_check to catch mutual recursion- cb pointer to the compile data--Returns: the group length or a negative number-*/--static int-get_grouplength(uint32_t **pptrptr, BOOL isinline, int *errcodeptr, int *lcptr,- int group, parsed_recurse_check *recurses, compile_block *cb)-{-int branchlength;-int grouplength = -1;--/* The cache can be used only if there is no possibility of there being two-groups with the same number. We do not need to set the end pointer for a group-that is being processed as a back reference or recursion, but we must do so for-an inline group. */--if (group > 0 && (cb->external_flags & PCRE2_DUPCAPUSED) == 0)- {- uint32_t groupinfo = cb->groupinfo[group];- if ((groupinfo & GI_NOT_FIXED_LENGTH) != 0) return -1;- if ((groupinfo & GI_SET_FIXED_LENGTH) != 0)- {- if (isinline) *pptrptr = parsed_skip(*pptrptr, PSKIP_KET);- return groupinfo & GI_FIXED_LENGTH_MASK;- }- }--/* Scan the group. In this case we find the end pointer of necessity. */--for(;;)- {- branchlength = get_branchlength(pptrptr, errcodeptr, lcptr, recurses, cb);- if (branchlength < 0) goto ISNOTFIXED;- if (grouplength == -1) grouplength = branchlength;- else if (grouplength != branchlength) goto ISNOTFIXED;- if (**pptrptr == META_KET) break;- *pptrptr += 1; /* Skip META_ALT */- }--if (group > 0)- cb->groupinfo[group] |= (uint32_t)(GI_SET_FIXED_LENGTH | grouplength);-return grouplength;--ISNOTFIXED:-if (group > 0) cb->groupinfo[group] |= GI_NOT_FIXED_LENGTH;-return -1;-}----/*************************************************-* Find length of a parsed branch *-*************************************************/--/* Return a fixed length for a branch in a lookbehind, giving an error if the-length is not fixed. On entry, *pptrptr points to the first element inside the-branch. On exit it is set to point to the ALT or KET.--Arguments:- pptrptr pointer to pointer in the parsed pattern- errcodeptr pointer to error code- lcptr pointer to loop counter- recurses chain of recurse_check to catch mutual recursion- cb pointer to compile block--Returns: the length, or a negative value on error-*/--static int-get_branchlength(uint32_t **pptrptr, int *errcodeptr, int *lcptr,- parsed_recurse_check *recurses, compile_block *cb)-{-int branchlength = 0;-int grouplength;-uint32_t lastitemlength = 0;-uint32_t *pptr = *pptrptr;-PCRE2_SIZE offset;-parsed_recurse_check this_recurse;--/* A large and/or complex regex can take too long to process. This can happen-more often when (?| groups are present in the pattern because their length-cannot be cached. */--if ((*lcptr)++ > 2000)- {- *errcodeptr = ERR35; /* Lookbehind is too complicated */- return -1;- }--/* Scan the branch, accumulating the length. */--for (;; pptr++)- {- parsed_recurse_check *r;- uint32_t *gptr, *gptrend;- uint32_t escape;- uint32_t group = 0;- uint32_t itemlength = 0;-- if (*pptr < META_END)- {- itemlength = 1;- }-- else switch (META_CODE(*pptr))- {- case META_KET:- case META_ALT:- goto EXIT;-- /* (*ACCEPT) and (*FAIL) terminate the branch, but we must skip to the- actual termination. */-- case META_ACCEPT:- case META_FAIL:- pptr = parsed_skip(pptr, PSKIP_ALT);- if (pptr == NULL) goto PARSED_SKIP_FAILED;- goto EXIT;-- case META_MARK:- case META_COMMIT_ARG:- case META_PRUNE_ARG:- case META_SKIP_ARG:- case META_THEN_ARG:- pptr += pptr[1] + 1;- break;-- case META_CIRCUMFLEX:- case META_COMMIT:- case META_DOLLAR:- case META_PRUNE:- case META_SKIP:- case META_THEN:- break;-- case META_OPTIONS:- pptr += 1;- break;-- case META_BIGVALUE:- itemlength = 1;- pptr += 1;- break;-- case META_CLASS:- case META_CLASS_NOT:- itemlength = 1;- pptr = parsed_skip(pptr, PSKIP_CLASS);- if (pptr == NULL) goto PARSED_SKIP_FAILED;- break;-- case META_CLASS_EMPTY_NOT:- case META_DOT:- itemlength = 1;- break;-- case META_CALLOUT_NUMBER:- pptr += 3;- break;-- case META_CALLOUT_STRING:- pptr += 3 + SIZEOFFSET;- break;-- /* Only some escapes consume a character. Of those, \R and \X are never- allowed because they might match more than character. \C is allowed only in- 32-bit and non-UTF 8/16-bit modes. */-- case META_ESCAPE:- escape = META_DATA(*pptr);- if (escape == ESC_R || escape == ESC_X) return -1;- if (escape > ESC_b && escape < ESC_Z)- {-#if PCRE2_CODE_UNIT_WIDTH != 32- if ((cb->external_options & PCRE2_UTF) != 0 && escape == ESC_C)- {- *errcodeptr = ERR36;- return -1;- }-#endif- itemlength = 1;- if (escape == ESC_p || escape == ESC_P) pptr++; /* Skip prop data */- }- break;-- /* Lookaheads do not contribute to the length of this branch, but they may- contain lookbehinds within them whose lengths need to be set. */-- case META_LOOKAHEAD:- case META_LOOKAHEADNOT:- case META_LOOKAHEAD_NA:- *errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb, lcptr);- if (*errcodeptr != 0) return -1;-- /* Ignore any qualifiers that follow a lookahead assertion. */-- switch (pptr[1])- {- case META_ASTERISK:- case META_ASTERISK_PLUS:- case META_ASTERISK_QUERY:- case META_PLUS:- case META_PLUS_PLUS:- case META_PLUS_QUERY:- case META_QUERY:- case META_QUERY_PLUS:- case META_QUERY_QUERY:- pptr++;- break;-- case META_MINMAX:- case META_MINMAX_PLUS:- case META_MINMAX_QUERY:- pptr += 3;- break;-- default:- break;- }- break;-- /* A nested lookbehind does not contribute any length to this lookbehind,- but must itself be checked and have its lengths set. */-- case META_LOOKBEHIND:- case META_LOOKBEHINDNOT:- case META_LOOKBEHIND_NA:- if (!set_lookbehind_lengths(&pptr, errcodeptr, lcptr, recurses, cb))- return -1;- break;-- /* Back references and recursions are handled by very similar code. At this- stage, the names generated in the parsing pass are available, but the main- name table has not yet been created. So for the named varieties, scan the- list of names in order to get the number of the first one in the pattern,- and whether or not this name is duplicated. */-- case META_BACKREF_BYNAME:- if ((cb->external_options & PCRE2_MATCH_UNSET_BACKREF) != 0)- goto ISNOTFIXED;- /* Fall through */-- case META_RECURSE_BYNAME:- {- int i;- PCRE2_SPTR name;- BOOL is_dupname = FALSE;- named_group *ng = cb->named_groups;- uint32_t meta_code = META_CODE(*pptr);- uint32_t length = *(++pptr);-- GETPLUSOFFSET(offset, pptr);- name = cb->start_pattern + offset;- for (i = 0; i < cb->names_found; i++, ng++)- {- if (length == ng->length && PRIV(strncmp)(name, ng->name, length) == 0)- {- group = ng->number;- is_dupname = ng->isdup;- break;- }- }-- if (group == 0)- {- *errcodeptr = ERR15; /* Non-existent subpattern */- cb->erroroffset = offset;- return -1;- }-- /* A numerical back reference can be fixed length if duplicate capturing- groups are not being used. A non-duplicate named back reference can also- be handled. */-- if (meta_code == META_RECURSE_BYNAME ||- (!is_dupname && (cb->external_flags & PCRE2_DUPCAPUSED) == 0))- goto RECURSE_OR_BACKREF_LENGTH; /* Handle as a numbered version. */- }- goto ISNOTFIXED; /* Duplicate name or number */-- /* The offset values for back references < 10 are in a separate vector- because otherwise they would use more than two parsed pattern elements on- 64-bit systems. */-- case META_BACKREF:- if ((cb->external_options & PCRE2_MATCH_UNSET_BACKREF) != 0 ||- (cb->external_flags & PCRE2_DUPCAPUSED) != 0)- goto ISNOTFIXED;- group = META_DATA(*pptr);- if (group < 10)- {- offset = cb->small_ref_offset[group];- goto RECURSE_OR_BACKREF_LENGTH;- }-- /* Fall through */- /* For groups >= 10 - picking up group twice does no harm. */-- /* A true recursion implies not fixed length, but a subroutine call may- be OK. Back reference "recursions" are also failed. */-- case META_RECURSE:- group = META_DATA(*pptr);- GETPLUSOFFSET(offset, pptr);-- RECURSE_OR_BACKREF_LENGTH:- if (group > cb->bracount)- {- cb->erroroffset = offset;- *errcodeptr = ERR15; /* Non-existent subpattern */- return -1;- }- if (group == 0) goto ISNOTFIXED; /* Local recursion */- for (gptr = cb->parsed_pattern; *gptr != META_END; gptr++)- {- if (META_CODE(*gptr) == META_BIGVALUE) gptr++;- else if (*gptr == (META_CAPTURE | group)) break;- }-- /* We must start the search for the end of the group at the first meta code- inside the group. Otherwise it will be treated as an enclosed group. */-- gptrend = parsed_skip(gptr + 1, PSKIP_KET);- if (gptrend == NULL) goto PARSED_SKIP_FAILED;- if (pptr > gptr && pptr < gptrend) goto ISNOTFIXED; /* Local recursion */- for (r = recurses; r != NULL; r = r->prev) if (r->groupptr == gptr) break;- if (r != NULL) goto ISNOTFIXED; /* Mutual recursion */- this_recurse.prev = recurses;- this_recurse.groupptr = gptr;-- /* We do not need to know the position of the end of the group, that is,- gptr is not used after the call to get_grouplength(). Setting the second- argument FALSE stops it scanning for the end when the length can be found- in the cache. */-- gptr++;- grouplength = get_grouplength(&gptr, FALSE, errcodeptr, lcptr, group,- &this_recurse, cb);- if (grouplength < 0)- {- if (*errcodeptr == 0) goto ISNOTFIXED;- return -1; /* Error already set */- }- itemlength = grouplength;- break;-- /* A (DEFINE) group is never obeyed inline and so it does not contribute to- the length of this branch. Skip from the following item to the next- unpaired ket. */-- case META_COND_DEFINE:- pptr = parsed_skip(pptr + 1, PSKIP_KET);- break;-- /* Check other nested groups - advance past the initial data for each type- and then seek a fixed length with get_grouplength(). */-- case META_COND_NAME:- case META_COND_NUMBER:- case META_COND_RNAME:- case META_COND_RNUMBER:- pptr += 2 + SIZEOFFSET;- goto CHECK_GROUP;-- case META_COND_ASSERT:- pptr += 1;- goto CHECK_GROUP;-- case META_COND_VERSION:- pptr += 4;- goto CHECK_GROUP;-- case META_CAPTURE:- group = META_DATA(*pptr);- /* Fall through */-- case META_ATOMIC:- case META_NOCAPTURE:- case META_SCRIPT_RUN:- pptr++;- CHECK_GROUP:- grouplength = get_grouplength(&pptr, TRUE, errcodeptr, lcptr, group,- recurses, cb);- if (grouplength < 0) return -1;- itemlength = grouplength;- break;-- /* Exact repetition is OK; variable repetition is not. A repetition of zero- must subtract the length that has already been added. */-- case META_MINMAX:- case META_MINMAX_PLUS:- case META_MINMAX_QUERY:- if (pptr[1] == pptr[2])- {- switch(pptr[1])- {- case 0:- branchlength -= lastitemlength;- break;-- case 1:- itemlength = 0;- break;-- default: /* Check for integer overflow */- if (lastitemlength != 0 && /* Should not occur, but just in case */- INT_MAX/lastitemlength < pptr[1] - 1)- {- *errcodeptr = ERR87; /* Integer overflow; lookbehind too big */- return -1;- }- itemlength = (pptr[1] - 1) * lastitemlength;- break;- }- pptr += 2;- break;- }- /* Fall through */-- /* Any other item means this branch does not have a fixed length. */-- default:- ISNOTFIXED:- *errcodeptr = ERR25; /* Not fixed length */- return -1;- }-- /* Add the item length to the branchlength, checking for integer overflow and- for the branch length exceeding the limit. */-- if (INT_MAX - branchlength < (int)itemlength ||- (branchlength += itemlength) > LOOKBEHIND_MAX)- {- *errcodeptr = ERR87;- return -1;- }-- /* Save this item length for use if the next item is a quantifier. */-- lastitemlength = itemlength;- }--EXIT:-*pptrptr = pptr;-return branchlength;--PARSED_SKIP_FAILED:-*errcodeptr = ERR90;-return -1;-}----/*************************************************-* Set lengths in a lookbehind *-*************************************************/--/* This function is called for each lookbehind, to set the lengths in its-branches. An error occurs if any branch does not have a fixed length that is-less than the maximum (65535). On exit, the pointer must be left on the final-ket.--The function also maintains the max_lookbehind value. Any lookbehind branch-that contains a nested lookbehind may actually look further back than the-length of the branch. The additional amount is passed back from-get_branchlength() as an "extra" value.--Arguments:- pptrptr pointer to pointer in the parsed pattern- errcodeptr pointer to error code- lcptr pointer to loop counter- recurses chain of recurse_check to catch mutual recursion- cb pointer to compile block--Returns: TRUE if all is well- FALSE otherwise, with error code and offset set-*/--static BOOL-set_lookbehind_lengths(uint32_t **pptrptr, int *errcodeptr, int *lcptr,- parsed_recurse_check *recurses, compile_block *cb)-{-PCRE2_SIZE offset;-int branchlength;-uint32_t *bptr = *pptrptr;--READPLUSOFFSET(offset, bptr); /* Offset for error messages */-*pptrptr += SIZEOFFSET;--do- {- *pptrptr += 1;- branchlength = get_branchlength(pptrptr, errcodeptr, lcptr, recurses, cb);- if (branchlength < 0)- {- /* The errorcode and offset may already be set from a nested lookbehind. */- if (*errcodeptr == 0) *errcodeptr = ERR25;- if (cb->erroroffset == PCRE2_UNSET) cb->erroroffset = offset;- return FALSE;- }- if (branchlength > cb->max_lookbehind) cb->max_lookbehind = branchlength;- *bptr |= branchlength; /* branchlength never more than 65535 */- bptr = *pptrptr;- }-while (*bptr == META_ALT);--return TRUE;-}----/*************************************************-* Check parsed pattern lookbehinds *-*************************************************/--/* This function is called at the end of parsing a pattern if any lookbehinds-were encountered. It scans the parsed pattern for them, calling-set_lookbehind_lengths() for each one. At the start, the errorcode is zero and-the error offset is marked unset. The enables the functions above not to-override settings from deeper nestings.--This function is called recursively from get_branchlength() for lookaheads in-order to process any lookbehinds that they may contain. It stops when it hits a-non-nested closing parenthesis in this case, returning a pointer to it.--Arguments- pptr points to where to start (start of pattern or start of lookahead)- retptr if not NULL, return the ket pointer here- recurses chain of recurse_check to catch mutual recursion- cb points to the compile block- lcptr points to loop counter--Returns: 0 on success, or an errorcode (cb->erroroffset will be set)-*/--static int-check_lookbehinds(uint32_t *pptr, uint32_t **retptr,- parsed_recurse_check *recurses, compile_block *cb, int *lcptr)-{-int errorcode = 0;-int nestlevel = 0;--cb->erroroffset = PCRE2_UNSET;--for (; *pptr != META_END; pptr++)- {- if (*pptr < META_END) continue; /* Literal */-- switch (META_CODE(*pptr))- {- default:- return ERR70; /* Unrecognized meta code */-- case META_ESCAPE:- if (*pptr - META_ESCAPE == ESC_P || *pptr - META_ESCAPE == ESC_p)- pptr += 1;- break;-- case META_KET:- if (--nestlevel < 0)- {- if (retptr != NULL) *retptr = pptr;- return 0;- }- break;-- case META_ATOMIC:- case META_CAPTURE:- case META_COND_ASSERT:- case META_LOOKAHEAD:- case META_LOOKAHEADNOT:- case META_LOOKAHEAD_NA:- case META_NOCAPTURE:- case META_SCRIPT_RUN:- nestlevel++;- break;-- case META_ACCEPT:- case META_ALT:- case META_ASTERISK:- case META_ASTERISK_PLUS:- case META_ASTERISK_QUERY:- case META_BACKREF:- case META_CIRCUMFLEX:- case META_CLASS:- case META_CLASS_EMPTY:- case META_CLASS_EMPTY_NOT:- case META_CLASS_END:- case META_CLASS_NOT:- case META_COMMIT:- case META_DOLLAR:- case META_DOT:- case META_FAIL:- case META_PLUS:- case META_PLUS_PLUS:- case META_PLUS_QUERY:- case META_PRUNE:- case META_QUERY:- case META_QUERY_PLUS:- case META_QUERY_QUERY:- case META_RANGE_ESCAPED:- case META_RANGE_LITERAL:- case META_SKIP:- case META_THEN:- break;-- case META_RECURSE:- pptr += SIZEOFFSET;- break;-- case META_BACKREF_BYNAME:- case META_RECURSE_BYNAME:- pptr += 1 + SIZEOFFSET;- break;-- case META_COND_DEFINE:- pptr += SIZEOFFSET;- nestlevel++;- break;-- case META_COND_NAME:- case META_COND_NUMBER:- case META_COND_RNAME:- case META_COND_RNUMBER:- pptr += 1 + SIZEOFFSET;- nestlevel++;- break;-- case META_COND_VERSION:- pptr += 3;- nestlevel++;- break;-- case META_CALLOUT_STRING:- pptr += 3 + SIZEOFFSET;- break;-- case META_BIGVALUE:- case META_OPTIONS:- case META_POSIX:- case META_POSIX_NEG:- pptr += 1;- break;-- case META_MINMAX:- case META_MINMAX_QUERY:- case META_MINMAX_PLUS:- pptr += 2;- break;-- case META_CALLOUT_NUMBER:- pptr += 3;- break;-- case META_MARK:- case META_COMMIT_ARG:- case META_PRUNE_ARG:- case META_SKIP_ARG:- case META_THEN_ARG:- pptr += 1 + pptr[1];- break;-- case META_LOOKBEHIND:- case META_LOOKBEHINDNOT:- case META_LOOKBEHIND_NA:- if (!set_lookbehind_lengths(&pptr, &errorcode, lcptr, recurses, cb))- return errorcode;- break;- }- }--return 0;-}----/*************************************************-* External function to compile a pattern *-*************************************************/--/* This function reads a regular expression in the form of a string and returns-a pointer to a block of store holding a compiled version of the expression.--Arguments:- pattern the regular expression- patlen the length of the pattern, or PCRE2_ZERO_TERMINATED- options option bits- errorptr pointer to errorcode- erroroffset pointer to error offset- ccontext points to a compile context or is NULL--Returns: pointer to compiled data block, or NULL on error,- with errorcode and erroroffset set-*/--PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION-pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE patlen, uint32_t options,- int *errorptr, PCRE2_SIZE *erroroffset, pcre2_compile_context *ccontext)-{-BOOL utf; /* Set TRUE for UTF mode */-BOOL ucp; /* Set TRUE for UCP mode */-BOOL has_lookbehind = FALSE; /* Set TRUE if a lookbehind is found */-BOOL zero_terminated; /* Set TRUE for zero-terminated pattern */-pcre2_real_code *re = NULL; /* What we will return */-compile_block cb; /* "Static" compile-time data */-const uint8_t *tables; /* Char tables base pointer */--PCRE2_UCHAR *code; /* Current pointer in compiled code */-PCRE2_SPTR codestart; /* Start of compiled code */-PCRE2_SPTR ptr; /* Current pointer in pattern */-uint32_t *pptr; /* Current pointer in parsed pattern */--PCRE2_SIZE length = 1; /* Allow for final END opcode */-PCRE2_SIZE usedlength; /* Actual length used */-PCRE2_SIZE re_blocksize; /* Size of memory block */-PCRE2_SIZE big32count = 0; /* 32-bit literals >= 0x80000000 */-PCRE2_SIZE parsed_size_needed; /* Needed for parsed pattern */--uint32_t firstcuflags, reqcuflags; /* Type of first/req code unit */-uint32_t firstcu, reqcu; /* Value of first/req code unit */-uint32_t setflags = 0; /* NL and BSR set flags */--uint32_t skipatstart; /* When checking (*UTF) etc */-uint32_t limit_heap = UINT32_MAX;-uint32_t limit_match = UINT32_MAX; /* Unset match limits */-uint32_t limit_depth = UINT32_MAX;--int newline = 0; /* Unset; can be set by the pattern */-int bsr = 0; /* Unset; can be set by the pattern */-int errorcode = 0; /* Initialize to avoid compiler warn */-int regexrc; /* Return from compile */--uint32_t i; /* Local loop counter */--/* Comments at the head of this file explain about these variables. */--uint32_t stack_groupinfo[GROUPINFO_DEFAULT_SIZE];-uint32_t stack_parsed_pattern[PARSED_PATTERN_DEFAULT_SIZE];-named_group named_groups[NAMED_GROUP_LIST_SIZE];--/* The workspace is used in different ways in the different compiling phases.-It needs to be 16-bit aligned for the preliminary parsing scan. */--uint32_t c16workspace[C16_WORK_SIZE];-PCRE2_UCHAR *cworkspace = (PCRE2_UCHAR *)c16workspace;---/* -------------- Check arguments and set up the pattern ----------------- */--/* There must be error code and offset pointers. */--if (errorptr == NULL || erroroffset == NULL) return NULL;-*errorptr = ERR0;-*erroroffset = 0;--/* There must be a pattern! */--if (pattern == NULL)- {- *errorptr = ERR16;- return NULL;- }--/* A NULL compile context means "use a default context" */--if (ccontext == NULL)- ccontext = (pcre2_compile_context *)(&PRIV(default_compile_context));--/* PCRE2_MATCH_INVALID_UTF implies UTF */--if ((options & PCRE2_MATCH_INVALID_UTF) != 0) options |= PCRE2_UTF;--/* Check that all undefined public option bits are zero. */--if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0 ||- (ccontext->extra_options & ~PUBLIC_COMPILE_EXTRA_OPTIONS) != 0)- {- *errorptr = ERR17;- return NULL;- }--if ((options & PCRE2_LITERAL) != 0 &&- ((options & ~PUBLIC_LITERAL_COMPILE_OPTIONS) != 0 ||- (ccontext->extra_options & ~PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS) != 0))- {- *errorptr = ERR92;- return NULL;- }--/* A zero-terminated pattern is indicated by the special length value-PCRE2_ZERO_TERMINATED. Check for an overlong pattern. */--if ((zero_terminated = (patlen == PCRE2_ZERO_TERMINATED)))- patlen = PRIV(strlen)(pattern);--if (patlen > ccontext->max_pattern_length)- {- *errorptr = ERR88;- return NULL;- }--/* From here on, all returns from this function should end up going via the-EXIT label. */---/* ------------ Initialize the "static" compile data -------------- */--tables = (ccontext->tables != NULL)? ccontext->tables : PRIV(default_tables);--cb.lcc = tables + lcc_offset; /* Individual */-cb.fcc = tables + fcc_offset; /* character */-cb.cbits = tables + cbits_offset; /* tables */-cb.ctypes = tables + ctypes_offset;--cb.assert_depth = 0;-cb.bracount = 0;-cb.cx = ccontext;-cb.dupnames = FALSE;-cb.end_pattern = pattern + patlen;-cb.erroroffset = 0;-cb.external_flags = 0;-cb.external_options = options;-cb.groupinfo = stack_groupinfo;-cb.had_recurse = FALSE;-cb.lastcapture = 0;-cb.max_lookbehind = 0;-cb.name_entry_size = 0;-cb.name_table = NULL;-cb.named_groups = named_groups;-cb.named_group_list_size = NAMED_GROUP_LIST_SIZE;-cb.names_found = 0;-cb.open_caps = NULL;-cb.parens_depth = 0;-cb.parsed_pattern = stack_parsed_pattern;-cb.req_varyopt = 0;-cb.start_code = cworkspace;-cb.start_pattern = pattern;-cb.start_workspace = cworkspace;-cb.workspace_size = COMPILE_WORK_SIZE;--/* Maximum back reference and backref bitmap. The bitmap records up to 31 back-references to help in deciding whether (.*) can be treated as anchored or not.-*/--cb.top_backref = 0;-cb.backref_map = 0;--/* Escape sequences \1 to \9 are always back references, but as they are only-two characters long, only two elements can be used in the parsed_pattern-vector. The first contains the reference, and we'd like to use the second to-record the offset in the pattern, so that forward references to non-existent-groups can be diagnosed later with an offset. However, on 64-bit systems,-PCRE2_SIZE won't fit. Instead, we have a vector of offsets for the first-occurrence of \1 to \9, indexed by the second parsed_pattern value. All other-references have enough space for the offset to be put into the parsed pattern.-*/--for (i = 0; i < 10; i++) cb.small_ref_offset[i] = PCRE2_UNSET;---/* --------------- Start looking at the pattern --------------- */--/* Unless PCRE2_LITERAL is set, check for global one-time option settings at-the start of the pattern, and remember the offset to the actual regex. With-valgrind support, make the terminator of a zero-terminated pattern-inaccessible. This catches bugs that would otherwise only show up for-non-zero-terminated patterns. */--#ifdef SUPPORT_VALGRIND-if (zero_terminated) VALGRIND_MAKE_MEM_NOACCESS(pattern + patlen, CU2BYTES(1));-#endif--ptr = pattern;-skipatstart = 0;--if ((options & PCRE2_LITERAL) == 0)- {- while (patlen - skipatstart >= 2 &&- ptr[skipatstart] == CHAR_LEFT_PARENTHESIS &&- ptr[skipatstart+1] == CHAR_ASTERISK)- {- for (i = 0; i < sizeof(pso_list)/sizeof(pso); i++)- {- uint32_t c, pp;- pso *p = pso_list + i;-- if (patlen - skipatstart - 2 >= p->length &&- PRIV(strncmp_c8)(ptr + skipatstart + 2, (char *)(p->name),- p->length) == 0)- {- skipatstart += p->length + 2;- switch(p->type)- {- case PSO_OPT:- cb.external_options |= p->value;- break;-- case PSO_FLG:- setflags |= p->value;- break;-- case PSO_NL:- newline = p->value;- setflags |= PCRE2_NL_SET;- break;-- case PSO_BSR:- bsr = p->value;- setflags |= PCRE2_BSR_SET;- break;-- case PSO_LIMM:- case PSO_LIMD:- case PSO_LIMH:- c = 0;- pp = skipatstart;- if (!IS_DIGIT(ptr[pp]))- {- errorcode = ERR60;- ptr += pp;- goto HAD_EARLY_ERROR;- }- while (IS_DIGIT(ptr[pp]))- {- if (c > UINT32_MAX / 10 - 1) break; /* Integer overflow */- c = c*10 + (ptr[pp++] - CHAR_0);- }- if (ptr[pp++] != CHAR_RIGHT_PARENTHESIS)- {- errorcode = ERR60;- ptr += pp;- goto HAD_EARLY_ERROR;- }- if (p->type == PSO_LIMH) limit_heap = c;- else if (p->type == PSO_LIMM) limit_match = c;- else limit_depth = c;- skipatstart += pp - skipatstart;- break;- }- break; /* Out of the table scan loop */- }- }- if (i >= sizeof(pso_list)/sizeof(pso)) break; /* Out of pso loop */- }- }--/* End of pattern-start options; advance to start of real regex. */--ptr += skipatstart;--/* Can't support UTF or UCP if PCRE2 was built without Unicode support. */--#ifndef SUPPORT_UNICODE-if ((cb.external_options & (PCRE2_UTF|PCRE2_UCP)) != 0)- {- errorcode = ERR32;- goto HAD_EARLY_ERROR;- }-#endif--/* Check UTF. We have the original options in 'options', with that value as-modified by (*UTF) etc in cb->external_options. The extra option-PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not permitted in UTF-16 mode because the-surrogate code points cannot be represented in UTF-16. */--utf = (cb.external_options & PCRE2_UTF) != 0;-if (utf)- {- if ((options & PCRE2_NEVER_UTF) != 0)- {- errorcode = ERR74;- goto HAD_EARLY_ERROR;- }- if ((options & PCRE2_NO_UTF_CHECK) == 0 &&- (errorcode = PRIV(valid_utf)(pattern, patlen, erroroffset)) != 0)- goto HAD_ERROR; /* Offset was set by valid_utf() */--#if PCRE2_CODE_UNIT_WIDTH == 16- if ((ccontext->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) != 0)- {- errorcode = ERR91;- goto HAD_EARLY_ERROR;- }-#endif- }--/* Check UCP lockout. */--ucp = (cb.external_options & PCRE2_UCP) != 0;-if (ucp && (cb.external_options & PCRE2_NEVER_UCP) != 0)- {- errorcode = ERR75;- goto HAD_EARLY_ERROR;- }--/* Process the BSR setting. */--if (bsr == 0) bsr = ccontext->bsr_convention;--/* Process the newline setting. */--if (newline == 0) newline = ccontext->newline_convention;-cb.nltype = NLTYPE_FIXED;-switch(newline)- {- case PCRE2_NEWLINE_CR:- cb.nllen = 1;- cb.nl[0] = CHAR_CR;- break;-- case PCRE2_NEWLINE_LF:- cb.nllen = 1;- cb.nl[0] = CHAR_NL;- break;-- case PCRE2_NEWLINE_NUL:- cb.nllen = 1;- cb.nl[0] = CHAR_NUL;- break;-- case PCRE2_NEWLINE_CRLF:- cb.nllen = 2;- cb.nl[0] = CHAR_CR;- cb.nl[1] = CHAR_NL;- break;-- case PCRE2_NEWLINE_ANY:- cb.nltype = NLTYPE_ANY;- break;-- case PCRE2_NEWLINE_ANYCRLF:- cb.nltype = NLTYPE_ANYCRLF;- break;-- default:- errorcode = ERR56;- goto HAD_EARLY_ERROR;- }--/* Pre-scan the pattern to do two things: (1) Discover the named groups and-their numerical equivalents, so that this information is always available for-the remaining processing. (2) At the same time, parse the pattern and put a-processed version into the parsed_pattern vector. This has escapes interpreted-and comments removed (amongst other things).--In all but one case, when PCRE2_AUTO_CALLOUT is not set, the number of unsigned-32-bit ints in the parsed pattern is bounded by the length of the pattern plus-one (for the terminator) plus four if PCRE2_EXTRA_WORD or PCRE2_EXTRA_LINE is-set. The exceptional case is when running in 32-bit, non-UTF mode, when literal-characters greater than META_END (0x80000000) have to be coded as two units. In-this case, therefore, we scan the pattern to check for such values. */--#if PCRE2_CODE_UNIT_WIDTH == 32-if (!utf)- {- PCRE2_SPTR p;- for (p = ptr; p < cb.end_pattern; p++) if (*p >= META_END) big32count++;- }-#endif--/* Ensure that the parsed pattern buffer is big enough. When PCRE2_AUTO_CALLOUT-is set we have to assume a numerical callout (4 elements) for each character-plus one at the end. This is overkill, but memory is plentiful these days. For-many smaller patterns the vector on the stack (which was set up above) can be-used. */--parsed_size_needed = patlen - skipatstart + big32count;--if ((ccontext->extra_options &- (PCRE2_EXTRA_MATCH_WORD|PCRE2_EXTRA_MATCH_LINE)) != 0)- parsed_size_needed += 4;--if ((options & PCRE2_AUTO_CALLOUT) != 0)- parsed_size_needed = (parsed_size_needed + 1) * 5;--if (parsed_size_needed >= PARSED_PATTERN_DEFAULT_SIZE)- {- uint32_t *heap_parsed_pattern = ccontext->memctl.malloc(- (parsed_size_needed + 1) * sizeof(uint32_t), ccontext->memctl.memory_data);- if (heap_parsed_pattern == NULL)- {- *errorptr = ERR21;- goto EXIT;- }- cb.parsed_pattern = heap_parsed_pattern;- }-cb.parsed_pattern_end = cb.parsed_pattern + parsed_size_needed + 1;--/* Do the parsing scan. */--errorcode = parse_regex(ptr, cb.external_options, &has_lookbehind, &cb);-if (errorcode != 0) goto HAD_CB_ERROR;--/* Workspace is needed to remember information about numbered groups: whether a-group can match an empty string and what its fixed length is. This is done to-avoid the possibility of recursive references causing very long compile times-when checking these features. Unnumbered groups do not have this exposure since-they cannot be referenced. We use an indexed vector for this purpose. If there-are sufficiently few groups, the default vector on the stack, as set up above,-can be used. Otherwise we have to get/free a special vector. The vector must be-initialized to zero. */--if (cb.bracount >= GROUPINFO_DEFAULT_SIZE)- {- cb.groupinfo = ccontext->memctl.malloc(- (cb.bracount + 1)*sizeof(uint32_t), ccontext->memctl.memory_data);- if (cb.groupinfo == NULL)- {- errorcode = ERR21;- cb.erroroffset = 0;- goto HAD_CB_ERROR;- }- }-memset(cb.groupinfo, 0, (cb.bracount + 1) * sizeof(uint32_t));--/* If there were any lookbehinds, scan the parsed pattern to figure out their-lengths. */--if (has_lookbehind)- {- int loopcount = 0;- errorcode = check_lookbehinds(cb.parsed_pattern, NULL, NULL, &cb, &loopcount);- if (errorcode != 0) goto HAD_CB_ERROR;- }--/* For debugging, there is a function that shows the parsed data vector. */--#ifdef DEBUG_SHOW_PARSED-fprintf(stderr, "+++ Pre-scan complete:\n");-show_parsed(&cb);-#endif--/* For debugging capturing information this code can be enabled. */--#ifdef DEBUG_SHOW_CAPTURES- {- named_group *ng = cb.named_groups;- fprintf(stderr, "+++Captures: %d\n", cb.bracount);- for (i = 0; i < cb.names_found; i++, ng++)- {- fprintf(stderr, "+++%3d %.*s\n", ng->number, ng->length, ng->name);- }- }-#endif--/* Pretend to compile the pattern while actually just accumulating the amount-of memory required in the 'length' variable. This behaviour is triggered by-passing a non-NULL final argument to compile_regex(). We pass a block of-workspace (cworkspace) for it to compile parts of the pattern into; the-compiled code is discarded when it is no longer needed, so hopefully this-workspace will never overflow, though there is a test for its doing so.--On error, errorcode will be set non-zero, so we don't need to look at the-result of the function. The initial options have been put into the cb block,-but we still have to pass a separate options variable (the first argument)-because the options may change as the pattern is processed. */--cb.erroroffset = patlen; /* For any subsequent errors that do not set it */-pptr = cb.parsed_pattern;-code = cworkspace;-*code = OP_BRA;--(void)compile_regex(cb.external_options, &code, &pptr, &errorcode, 0, &firstcu,- &firstcuflags, &reqcu, &reqcuflags, NULL, &cb, &length);--if (errorcode != 0) goto HAD_CB_ERROR; /* Offset is in cb.erroroffset */--/* This should be caught in compile_regex(), but just in case... */--if (length > MAX_PATTERN_SIZE)- {- errorcode = ERR20;- goto HAD_CB_ERROR;- }--/* Compute the size of, and then get and initialize, the data block for storing-the compiled pattern and names table. Integer overflow should no longer be-possible because nowadays we limit the maximum value of cb.names_found and-cb.name_entry_size. */--re_blocksize = sizeof(pcre2_real_code) +- CU2BYTES(length +- (PCRE2_SIZE)cb.names_found * (PCRE2_SIZE)cb.name_entry_size);-re = (pcre2_real_code *)- ccontext->memctl.malloc(re_blocksize, ccontext->memctl.memory_data);-if (re == NULL)- {- errorcode = ERR21;- goto HAD_CB_ERROR;- }--/* The compiler may put padding at the end of the pcre2_real_code structure in-order to round it up to a multiple of 4 or 8 bytes. This means that when a-compiled pattern is copied (for example, when serialized) undefined bytes are-read, and this annoys debuggers such as valgrind. To avoid this, we explicitly-write to the last 8 bytes of the structure before setting the fields. */--memset((char *)re + sizeof(pcre2_real_code) - 8, 0, 8);-re->memctl = ccontext->memctl;-re->tables = tables;-re->executable_jit = NULL;-memset(re->start_bitmap, 0, 32 * sizeof(uint8_t));-re->blocksize = re_blocksize;-re->magic_number = MAGIC_NUMBER;-re->compile_options = options;-re->overall_options = cb.external_options;-re->extra_options = ccontext->extra_options;-re->flags = PCRE2_CODE_UNIT_WIDTH/8 | cb.external_flags | setflags;-re->limit_heap = limit_heap;-re->limit_match = limit_match;-re->limit_depth = limit_depth;-re->first_codeunit = 0;-re->last_codeunit = 0;-re->bsr_convention = bsr;-re->newline_convention = newline;-re->max_lookbehind = 0;-re->minlength = 0;-re->top_bracket = 0;-re->top_backref = 0;-re->name_entry_size = cb.name_entry_size;-re->name_count = cb.names_found;--/* The basic block is immediately followed by the name table, and the compiled-code follows after that. */--codestart = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)) +- re->name_entry_size * re->name_count;--/* Update the compile data block for the actual compile. The starting points of-the name/number translation table and of the code are passed around in the-compile data block. The start/end pattern and initial options are already set-from the pre-compile phase, as is the name_entry_size field. */--cb.parens_depth = 0;-cb.assert_depth = 0;-cb.lastcapture = 0;-cb.name_table = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code));-cb.start_code = codestart;-cb.req_varyopt = 0;-cb.had_accept = FALSE;-cb.had_pruneorskip = FALSE;-cb.open_caps = NULL;--/* If any named groups were found, create the name/number table from the list-created in the pre-pass. */--if (cb.names_found > 0)- {- named_group *ng = cb.named_groups;- for (i = 0; i < cb.names_found; i++, ng++)- add_name_to_table(&cb, ng->name, ng->length, ng->number, i);- }--/* Set up a starting, non-extracting bracket, then compile the expression. On-error, errorcode will be set non-zero, so we don't need to look at the result-of the function here. */--pptr = cb.parsed_pattern;-code = (PCRE2_UCHAR *)codestart;-*code = OP_BRA;-regexrc = compile_regex(re->overall_options, &code, &pptr, &errorcode, 0,- &firstcu, &firstcuflags, &reqcu, &reqcuflags, NULL, &cb, NULL);-if (regexrc < 0) re->flags |= PCRE2_MATCH_EMPTY;-re->top_bracket = cb.bracount;-re->top_backref = cb.top_backref;-re->max_lookbehind = cb.max_lookbehind;--if (cb.had_accept)- {- reqcu = 0; /* Must disable after (*ACCEPT) */- reqcuflags = REQ_NONE;- re->flags |= PCRE2_HASACCEPT; /* Disables minimum length */- }--/* Fill in the final opcode and check for disastrous overflow. If no overflow,-but the estimated length exceeds the really used length, adjust the value of-re->blocksize, and if valgrind support is configured, mark the extra allocated-memory as unaddressable, so that any out-of-bound reads can be detected. */--*code++ = OP_END;-usedlength = code - codestart;-if (usedlength > length) errorcode = ERR23; else- {- re->blocksize -= CU2BYTES(length - usedlength);-#ifdef SUPPORT_VALGRIND- VALGRIND_MAKE_MEM_NOACCESS(code, CU2BYTES(length - usedlength));-#endif- }--/* Scan the pattern for recursion/subroutine calls and convert the group-numbers into offsets. Maintain a small cache so that repeated groups containing-recursions are efficiently handled. */--#define RSCAN_CACHE_SIZE 8--if (errorcode == 0 && cb.had_recurse)- {- PCRE2_UCHAR *rcode;- PCRE2_SPTR rgroup;- unsigned int ccount = 0;- int start = RSCAN_CACHE_SIZE;- recurse_cache rc[RSCAN_CACHE_SIZE];-- for (rcode = (PCRE2_UCHAR *)find_recurse(codestart, utf);- rcode != NULL;- rcode = (PCRE2_UCHAR *)find_recurse(rcode + 1 + LINK_SIZE, utf))- {- int p, groupnumber;-- groupnumber = (int)GET(rcode, 1);- if (groupnumber == 0) rgroup = codestart; else- {- PCRE2_SPTR search_from = codestart;- rgroup = NULL;- for (i = 0, p = start; i < ccount; i++, p = (p + 1) & 7)- {- if (groupnumber == rc[p].groupnumber)- {- rgroup = rc[p].group;- break;- }-- /* Group n+1 must always start to the right of group n, so we can save- search time below when the new group number is greater than any of the- previously found groups. */-- if (groupnumber > rc[p].groupnumber) search_from = rc[p].group;- }-- if (rgroup == NULL)- {- rgroup = PRIV(find_bracket)(search_from, utf, groupnumber);- if (rgroup == NULL)- {- errorcode = ERR53;- break;- }- if (--start < 0) start = RSCAN_CACHE_SIZE - 1;- rc[start].groupnumber = groupnumber;- rc[start].group = rgroup;- if (ccount < RSCAN_CACHE_SIZE) ccount++;- }- }-- PUT(rcode, 1, rgroup - codestart);- }- }--/* In rare debugging situations we sometimes need to look at the compiled code-at this stage. */--#ifdef DEBUG_CALL_PRINTINT-pcre2_printint(re, stderr, TRUE);-fprintf(stderr, "Length=%lu Used=%lu\n", length, usedlength);-#endif--/* Unless disabled, check whether any single character iterators can be-auto-possessified. The function overwrites the appropriate opcode values, so-the type of the pointer must be cast. NOTE: the intermediate variable "temp" is-used in this code because at least one compiler gives a warning about loss of-"const" attribute if the cast (PCRE2_UCHAR *)codestart is used directly in the-function call. */--if (errorcode == 0 && (re->overall_options & PCRE2_NO_AUTO_POSSESS) == 0)- {- PCRE2_UCHAR *temp = (PCRE2_UCHAR *)codestart;- if (PRIV(auto_possessify)(temp, &cb) != 0) errorcode = ERR80;- }--/* Failed to compile, or error while post-processing. */--if (errorcode != 0) goto HAD_CB_ERROR;--/* Successful compile. If the anchored option was not passed, set it if-we can determine that the pattern is anchored by virtue of ^ characters or \A-or anything else, such as starting with non-atomic .* when DOTALL is set and-there are no occurrences of *PRUNE or *SKIP (though there is an option to-disable this case). */--if ((re->overall_options & PCRE2_ANCHORED) == 0 &&- is_anchored(codestart, 0, &cb, 0, FALSE))- re->overall_options |= PCRE2_ANCHORED;--/* Set up the first code unit or startline flag, the required code unit, and-then study the pattern. This code need not be obeyed if PCRE2_NO_START_OPTIMIZE-is set, as the data it would create will not be used. Note that a first code-unit (but not the startline flag) is useful for anchored patterns because it-can still give a quick "no match" and also avoid searching for a last code-unit. */--if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)- {- int minminlength = 0; /* For minimal minlength from first/required CU */-- /* If we do not have a first code unit, see if there is one that is asserted- (these are not saved during the compile because they can cause conflicts with- actual literals that follow). */-- if (firstcuflags >= REQ_NONE)- firstcu = find_firstassertedcu(codestart, &firstcuflags, 0);-- /* Save the data for a first code unit. The existence of one means the- minimum length must be at least 1. */-- if (firstcuflags < REQ_NONE)- {- re->first_codeunit = firstcu;- re->flags |= PCRE2_FIRSTSET;- minminlength++;-- /* Handle caseless first code units. */-- if ((firstcuflags & REQ_CASELESS) != 0)- {- if (firstcu < 128 || (!utf && !ucp && firstcu < 255))- {- if (cb.fcc[firstcu] != firstcu) re->flags |= PCRE2_FIRSTCASELESS;- }-- /* The first code unit is > 128 in UTF or UCP mode, or > 255 otherwise.- In 8-bit UTF mode, codepoints in the range 128-255 are introductory code- points and cannot have another case, but if UCP is set they may do. */--#ifdef SUPPORT_UNICODE-#if PCRE2_CODE_UNIT_WIDTH == 8- else if (ucp && !utf && UCD_OTHERCASE(firstcu) != firstcu)- re->flags |= PCRE2_FIRSTCASELESS;-#else- else if ((utf || ucp) && firstcu <= MAX_UTF_CODE_POINT &&- UCD_OTHERCASE(firstcu) != firstcu)- re->flags |= PCRE2_FIRSTCASELESS;-#endif-#endif /* SUPPORT_UNICODE */- }- }-- /* When there is no first code unit, for non-anchored patterns, see if we can- set the PCRE2_STARTLINE flag. This is helpful for multiline matches when all- branches start with ^ and also when all branches start with non-atomic .* for- non-DOTALL matches when *PRUNE and SKIP are not present. (There is an option- that disables this case.) */-- else if ((re->overall_options & PCRE2_ANCHORED) == 0 &&- is_startline(codestart, 0, &cb, 0, FALSE))- re->flags |= PCRE2_STARTLINE;-- /* Handle the "required code unit", if one is set. In the UTF case we can- increment the minimum minimum length only if we are sure this really is a- different character and not a non-starting code unit of the first character,- because the minimum length count is in characters, not code units. */-- if (reqcuflags < REQ_NONE)- {-#if PCRE2_CODE_UNIT_WIDTH == 16- if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */- firstcuflags >= REQ_NONE || /* First not set */- (firstcu & 0xf800) != 0xd800 || /* First not surrogate */- (reqcu & 0xfc00) != 0xdc00) /* Req not low surrogate */-#elif PCRE2_CODE_UNIT_WIDTH == 8- if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */- firstcuflags >= REQ_NONE || /* First not set */- (firstcu & 0x80) == 0 || /* First is ASCII */- (reqcu & 0x80) == 0) /* Req is ASCII */-#endif- {- minminlength++;- }-- /* In the case of an anchored pattern, set up the value only if it follows- a variable length item in the pattern. */-- if ((re->overall_options & PCRE2_ANCHORED) == 0 ||- (reqcuflags & REQ_VARY) != 0)- {- re->last_codeunit = reqcu;- re->flags |= PCRE2_LASTSET;-- /* Handle caseless required code units as for first code units (above). */-- if ((reqcuflags & REQ_CASELESS) != 0)- {- if (reqcu < 128 || (!utf && !ucp && reqcu < 255))- {- if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS;- }-#ifdef SUPPORT_UNICODE-#if PCRE2_CODE_UNIT_WIDTH == 8- else if (ucp && !utf && UCD_OTHERCASE(reqcu) != reqcu)- re->flags |= PCRE2_LASTCASELESS;-#else- else if ((utf || ucp) && reqcu <= MAX_UTF_CODE_POINT &&- UCD_OTHERCASE(reqcu) != reqcu)- re->flags |= PCRE2_LASTCASELESS;-#endif-#endif /* SUPPORT_UNICODE */- }- }- }-- /* Study the compiled pattern to set up information such as a bitmap of- starting code units and a minimum matching length. */-- if (PRIV(study)(re) != 0)- {- errorcode = ERR31;- goto HAD_CB_ERROR;- }-- /* If study() set a bitmap of starting code units, it implies a minimum- length of at least one. */-- if ((re->flags & PCRE2_FIRSTMAPSET) != 0 && minminlength == 0)- minminlength = 1;-- /* If the minimum length set (or not set) by study() is less than the minimum- implied by required code units, override it. */-- if (re->minlength < minminlength) re->minlength = minminlength;- } /* End of start-of-match optimizations. */--/* Control ends up here in all cases. When running under valgrind, make a-pattern's terminating zero defined again. If memory was obtained for the parsed-version of the pattern, free it before returning. Also free the list of named-groups if a larger one had to be obtained, and likewise the group information-vector. */--EXIT:-#ifdef SUPPORT_VALGRIND-if (zero_terminated) VALGRIND_MAKE_MEM_DEFINED(pattern + patlen, CU2BYTES(1));-#endif-if (cb.parsed_pattern != stack_parsed_pattern)- ccontext->memctl.free(cb.parsed_pattern, ccontext->memctl.memory_data);-if (cb.named_group_list_size > NAMED_GROUP_LIST_SIZE)- ccontext->memctl.free((void *)cb.named_groups, ccontext->memctl.memory_data);-if (cb.groupinfo != stack_groupinfo)- ccontext->memctl.free((void *)cb.groupinfo, ccontext->memctl.memory_data);-return re; /* Will be NULL after an error */--/* Errors discovered in parse_regex() set the offset value in the compile-block. Errors discovered before it is called must compute it from the ptr-value. After parse_regex() is called, the offset in the compile block is set to-the end of the pattern, but certain errors in compile_regex() may reset it if-an offset is available in the parsed pattern. */--HAD_CB_ERROR:-ptr = pattern + cb.erroroffset;--HAD_EARLY_ERROR:-*erroroffset = ptr - pattern;--HAD_ERROR:-*errorptr = errorcode;-pcre2_code_free(re);-re = NULL;-goto EXIT;-}+ New API code Copyright (c) 2016-2024 University of Cambridge++-----------------------------------------------------------------------------+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright notice,+ this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++ * Neither the name of the University of Cambridge nor the names of its+ contributors may be used to endorse or promote products derived from+ this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.+-----------------------------------------------------------------------------+*/+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#define NLBLOCK cb /* Block containing newline information */+#define PSSTART start_pattern /* Field containing processed string start */+#define PSEND end_pattern /* Field containing processed string end */++#include "pcre2_internal.h"++/* In rare error cases debugging might require calling pcre2_printint(). */++#if 0+#ifdef EBCDIC+#define PRINTABLE(c) ((c) >= 64 && (c) < 255)+#else+#define PRINTABLE(c) ((c) >= 32 && (c) < 127)+#endif+#include "pcre2_printint.c"+#define DEBUG_CALL_PRINTINT+#endif++/* Other debugging code can be enabled by these defines. */++/* #define DEBUG_SHOW_CAPTURES */+/* #define DEBUG_SHOW_PARSED */++/* There are a few things that vary with different code unit sizes. Handle them+by defining macros in order to minimize #if usage. */++#if PCRE2_CODE_UNIT_WIDTH == 8+#define STRING_UTFn_RIGHTPAR STRING_UTF8_RIGHTPAR, 5+#define XDIGIT(c) xdigitab[c]++#else /* Either 16-bit or 32-bit */+#define XDIGIT(c) (MAX_255(c)? xdigitab[c] : 0xff)++#if PCRE2_CODE_UNIT_WIDTH == 16+#define STRING_UTFn_RIGHTPAR STRING_UTF16_RIGHTPAR, 6++#else /* 32-bit */+#define STRING_UTFn_RIGHTPAR STRING_UTF32_RIGHTPAR, 6+#endif+#endif++/* Macros to store and retrieve a PCRE2_SIZE value in the parsed pattern, which+consists of uint32_t elements. Assume that if uint32_t can't hold it, two of+them will be able to (i.e. assume a 64-bit world). */++#if PCRE2_SIZE_MAX <= UINT32_MAX+#define PUTOFFSET(s,p) *p++ = s+#define GETOFFSET(s,p) s = *p+++#define GETPLUSOFFSET(s,p) s = *(++p)+#define READPLUSOFFSET(s,p) s = p[1]+#define SKIPOFFSET(p) p+++#define SIZEOFFSET 1+#else+#define PUTOFFSET(s,p) \+ { *p++ = (uint32_t)(s >> 32); *p++ = (uint32_t)(s & 0xffffffff); }+#define GETOFFSET(s,p) \+ { s = ((PCRE2_SIZE)p[0] << 32) | (PCRE2_SIZE)p[1]; p += 2; }+#define GETPLUSOFFSET(s,p) \+ { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; p += 2; }+#define READPLUSOFFSET(s,p) \+ { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; }+#define SKIPOFFSET(p) p += 2+#define SIZEOFFSET 2+#endif++/* Macros for manipulating elements of the parsed pattern vector. */++#define META_CODE(x) (x & 0xffff0000u)+#define META_DATA(x) (x & 0x0000ffffu)+#define META_DIFF(x,y) ((x-y)>>16)++/* Function definitions to allow mutual recursion */++#ifdef SUPPORT_UNICODE+static unsigned int+ add_list_to_class_internal(uint8_t *, PCRE2_UCHAR **, uint32_t, uint32_t,+ compile_block *, const uint32_t *, unsigned int);+#endif++static int+ compile_regex(uint32_t, uint32_t, PCRE2_UCHAR **, uint32_t **, int *,+ uint32_t, uint32_t *, uint32_t *, uint32_t *, uint32_t *, branch_chain *,+ open_capitem *, compile_block *, PCRE2_SIZE *);++static int+ get_branchlength(uint32_t **, int *, int *, int *, parsed_recurse_check *,+ compile_block *);++static BOOL+ set_lookbehind_lengths(uint32_t **, int *, int *, parsed_recurse_check *,+ compile_block *);++static int+ check_lookbehinds(uint32_t *, uint32_t **, parsed_recurse_check *,+ compile_block *, int *);+++/*************************************************+* Code parameters and static tables *+*************************************************/++#define MAX_GROUP_NUMBER 65535u+#define MAX_REPEAT_COUNT 65535u+#define REPEAT_UNLIMITED (MAX_REPEAT_COUNT+1)++/* COMPILE_WORK_SIZE specifies the size of stack workspace, which is used in+different ways in the different pattern scans. The parsing and group-+identifying pre-scan uses it to handle nesting, and needs it to be 16-bit+aligned for this. Having defined the size in code units, we set up+C16_WORK_SIZE as the number of elements in the 16-bit vector.++During the first compiling phase, when determining how much memory is required,+the regex is partly compiled into this space, but the compiled parts are+discarded as soon as they can be, so that hopefully there will never be an+overrun. The code does, however, check for an overrun, which can occur for+pathological patterns. The size of the workspace depends on LINK_SIZE because+the length of compiled items varies with this.++In the real compile phase, this workspace is not currently used. */++#define COMPILE_WORK_SIZE (3000*LINK_SIZE) /* Size in code units */++#define C16_WORK_SIZE \+ ((COMPILE_WORK_SIZE * sizeof(PCRE2_UCHAR))/sizeof(uint16_t))++/* A uint32_t vector is used for caching information about the size of+capturing groups, to improve performance. A default is created on the stack of+this size. */++#define GROUPINFO_DEFAULT_SIZE 256++/* The overrun tests check for a slightly smaller size so that they detect the+overrun before it actually does run off the end of the data block. */++#define WORK_SIZE_SAFETY_MARGIN (100)++/* This value determines the size of the initial vector that is used for+remembering named groups during the pre-compile. It is allocated on the stack,+but if it is too small, it is expanded, in a similar way to the workspace. The+value is the number of slots in the list. */++#define NAMED_GROUP_LIST_SIZE 20++/* The pre-compiling pass over the pattern creates a parsed pattern in a vector+of uint32_t. For short patterns this lives on the stack, with this size. Heap+memory is used for longer patterns. */++#define PARSED_PATTERN_DEFAULT_SIZE 1024++/* Maximum length value to check against when making sure that the variable+that holds the compiled pattern length does not overflow. We make it a bit less+than INT_MAX to allow for adding in group terminating code units, so that we+don't have to check them every time. */++#define OFLOW_MAX (INT_MAX - 20)++/* Code values for parsed patterns, which are stored in a vector of 32-bit+unsigned ints. Values less than META_END are literal data values. The coding+for identifying the item is in the top 16-bits, leaving 16 bits for the+additional data that some of them need. The META_CODE, META_DATA, and META_DIFF+macros are used to manipulate parsed pattern elements.++NOTE: When these definitions are changed, the table of extra lengths for each+code (meta_extra_lengths, just below) must be updated to remain in step. */++#define META_END 0x80000000u /* End of pattern */++#define META_ALT 0x80010000u /* alternation */+#define META_ATOMIC 0x80020000u /* atomic group */+#define META_BACKREF 0x80030000u /* Back ref */+#define META_BACKREF_BYNAME 0x80040000u /* \k'name' */+#define META_BIGVALUE 0x80050000u /* Next is a literal > META_END */+#define META_CALLOUT_NUMBER 0x80060000u /* (?C with numerical argument */+#define META_CALLOUT_STRING 0x80070000u /* (?C with string argument */+#define META_CAPTURE 0x80080000u /* Capturing parenthesis */+#define META_CIRCUMFLEX 0x80090000u /* ^ metacharacter */+#define META_CLASS 0x800a0000u /* start non-empty class */+#define META_CLASS_EMPTY 0x800b0000u /* empty class */+#define META_CLASS_EMPTY_NOT 0x800c0000u /* negative empty class */+#define META_CLASS_END 0x800d0000u /* end of non-empty class */+#define META_CLASS_NOT 0x800e0000u /* start non-empty negative class */+#define META_COND_ASSERT 0x800f0000u /* (?(?assertion)... */+#define META_COND_DEFINE 0x80100000u /* (?(DEFINE)... */+#define META_COND_NAME 0x80110000u /* (?(<name>)... */+#define META_COND_NUMBER 0x80120000u /* (?(digits)... */+#define META_COND_RNAME 0x80130000u /* (?(R&name)... */+#define META_COND_RNUMBER 0x80140000u /* (?(Rdigits)... */+#define META_COND_VERSION 0x80150000u /* (?(VERSION<op>x.y)... */+#define META_DOLLAR 0x80160000u /* $ metacharacter */+#define META_DOT 0x80170000u /* . metacharacter */+#define META_ESCAPE 0x80180000u /* \d and friends */+#define META_KET 0x80190000u /* closing parenthesis */+#define META_NOCAPTURE 0x801a0000u /* no capture parens */+#define META_OPTIONS 0x801b0000u /* (?i) and friends */+#define META_POSIX 0x801c0000u /* POSIX class item */+#define META_POSIX_NEG 0x801d0000u /* negative POSIX class item */+#define META_RANGE_ESCAPED 0x801e0000u /* range with at least one escape */+#define META_RANGE_LITERAL 0x801f0000u /* range defined literally */+#define META_RECURSE 0x80200000u /* Recursion */+#define META_RECURSE_BYNAME 0x80210000u /* (?&name) */+#define META_SCRIPT_RUN 0x80220000u /* (*script_run:...) */++/* These must be kept together to make it easy to check that an assertion+is present where expected in a conditional group. */++#define META_LOOKAHEAD 0x80230000u /* (?= */+#define META_LOOKAHEADNOT 0x80240000u /* (?! */+#define META_LOOKBEHIND 0x80250000u /* (?<= */+#define META_LOOKBEHINDNOT 0x80260000u /* (?<! */++/* These cannot be conditions */++#define META_LOOKAHEAD_NA 0x80270000u /* (*napla: */+#define META_LOOKBEHIND_NA 0x80280000u /* (*naplb: */++/* These must be kept in this order, with consecutive values, and the _ARG+versions of COMMIT, PRUNE, SKIP, and THEN immediately after their non-argument+versions. */++#define META_MARK 0x80290000u /* (*MARK) */+#define META_ACCEPT 0x802a0000u /* (*ACCEPT) */+#define META_FAIL 0x802b0000u /* (*FAIL) */+#define META_COMMIT 0x802c0000u /* These */+#define META_COMMIT_ARG 0x802d0000u /* pairs */+#define META_PRUNE 0x802e0000u /* must */+#define META_PRUNE_ARG 0x802f0000u /* be */+#define META_SKIP 0x80300000u /* kept */+#define META_SKIP_ARG 0x80310000u /* in */+#define META_THEN 0x80320000u /* this */+#define META_THEN_ARG 0x80330000u /* order */++/* These must be kept in groups of adjacent 3 values, and all together. */++#define META_ASTERISK 0x80340000u /* * */+#define META_ASTERISK_PLUS 0x80350000u /* *+ */+#define META_ASTERISK_QUERY 0x80360000u /* *? */+#define META_PLUS 0x80370000u /* + */+#define META_PLUS_PLUS 0x80380000u /* ++ */+#define META_PLUS_QUERY 0x80390000u /* +? */+#define META_QUERY 0x803a0000u /* ? */+#define META_QUERY_PLUS 0x803b0000u /* ?+ */+#define META_QUERY_QUERY 0x803c0000u /* ?? */+#define META_MINMAX 0x803d0000u /* {n,m} repeat */+#define META_MINMAX_PLUS 0x803e0000u /* {n,m}+ repeat */+#define META_MINMAX_QUERY 0x803f0000u /* {n,m}? repeat */++#define META_FIRST_QUANTIFIER META_ASTERISK+#define META_LAST_QUANTIFIER META_MINMAX_QUERY++/* This is a special "meta code" that is used only to distinguish (*asr: from+(*sr: in the table of aphabetic assertions. It is never stored in the parsed+pattern because (*asr: is turned into (*sr:(*atomic: at that stage. There is+therefore no need for it to have a length entry, so use a high value. */++#define META_ATOMIC_SCRIPT_RUN 0x8fff0000u++/* Table of extra lengths for each of the meta codes. Must be kept in step with+the definitions above. For some items these values are a basic length to which+a variable amount has to be added. */++static unsigned char meta_extra_lengths[] = {+ 0, /* META_END */+ 0, /* META_ALT */+ 0, /* META_ATOMIC */+ 0, /* META_BACKREF - more if group is >= 10 */+ 1+SIZEOFFSET, /* META_BACKREF_BYNAME */+ 1, /* META_BIGVALUE */+ 3, /* META_CALLOUT_NUMBER */+ 3+SIZEOFFSET, /* META_CALLOUT_STRING */+ 0, /* META_CAPTURE */+ 0, /* META_CIRCUMFLEX */+ 0, /* META_CLASS */+ 0, /* META_CLASS_EMPTY */+ 0, /* META_CLASS_EMPTY_NOT */+ 0, /* META_CLASS_END */+ 0, /* META_CLASS_NOT */+ 0, /* META_COND_ASSERT */+ SIZEOFFSET, /* META_COND_DEFINE */+ 1+SIZEOFFSET, /* META_COND_NAME */+ 1+SIZEOFFSET, /* META_COND_NUMBER */+ 1+SIZEOFFSET, /* META_COND_RNAME */+ 1+SIZEOFFSET, /* META_COND_RNUMBER */+ 3, /* META_COND_VERSION */+ 0, /* META_DOLLAR */+ 0, /* META_DOT */+ 0, /* META_ESCAPE - more for ESC_P, ESC_p, ESC_g, ESC_k */+ 0, /* META_KET */+ 0, /* META_NOCAPTURE */+ 1, /* META_OPTIONS */+ 1, /* META_POSIX */+ 1, /* META_POSIX_NEG */+ 0, /* META_RANGE_ESCAPED */+ 0, /* META_RANGE_LITERAL */+ SIZEOFFSET, /* META_RECURSE */+ 1+SIZEOFFSET, /* META_RECURSE_BYNAME */+ 0, /* META_SCRIPT_RUN */+ 0, /* META_LOOKAHEAD */+ 0, /* META_LOOKAHEADNOT */+ SIZEOFFSET, /* META_LOOKBEHIND */+ SIZEOFFSET, /* META_LOOKBEHINDNOT */+ 0, /* META_LOOKAHEAD_NA */+ SIZEOFFSET, /* META_LOOKBEHIND_NA */+ 1, /* META_MARK - plus the string length */+ 0, /* META_ACCEPT */+ 0, /* META_FAIL */+ 0, /* META_COMMIT */+ 1, /* META_COMMIT_ARG - plus the string length */+ 0, /* META_PRUNE */+ 1, /* META_PRUNE_ARG - plus the string length */+ 0, /* META_SKIP */+ 1, /* META_SKIP_ARG - plus the string length */+ 0, /* META_THEN */+ 1, /* META_THEN_ARG - plus the string length */+ 0, /* META_ASTERISK */+ 0, /* META_ASTERISK_PLUS */+ 0, /* META_ASTERISK_QUERY */+ 0, /* META_PLUS */+ 0, /* META_PLUS_PLUS */+ 0, /* META_PLUS_QUERY */+ 0, /* META_QUERY */+ 0, /* META_QUERY_PLUS */+ 0, /* META_QUERY_QUERY */+ 2, /* META_MINMAX */+ 2, /* META_MINMAX_PLUS */+ 2 /* META_MINMAX_QUERY */+};++/* Types for skipping parts of a parsed pattern. */++enum { PSKIP_ALT, PSKIP_CLASS, PSKIP_KET };++/* Macro for setting individual bits in class bitmaps. It took some+experimenting to figure out how to stop gcc 5.3.0 from warning with+-Wconversion. This version gets a warning:++ #define SETBIT(a,b) a[(b)/8] |= (uint8_t)(1u << ((b)&7))++Let's hope the apparently less efficient version isn't actually so bad if the+compiler is clever with identical subexpressions. */++#define SETBIT(a,b) a[(b)/8] = (uint8_t)(a[(b)/8] | (1u << ((b)&7)))++/* Values and flags for the unsigned xxcuflags variables that accompany xxcu+variables, which are concerned with first and required code units. A value+greater than or equal to REQ_NONE means "no code unit set"; otherwise the+matching xxcu variable is set, and the low valued bits are relevant. */++#define REQ_UNSET 0xffffffffu /* Not yet found anything */+#define REQ_NONE 0xfffffffeu /* Found not fixed character */+#define REQ_CASELESS 0x00000001u /* Code unit in xxcu is caseless */+#define REQ_VARY 0x00000002u /* Code unit is followed by non-literal */++/* These flags are used in the groupinfo vector. */++#define GI_SET_FIXED_LENGTH 0x80000000u+#define GI_NOT_FIXED_LENGTH 0x40000000u+#define GI_FIXED_LENGTH_MASK 0x0000ffffu++/* This simple test for a decimal digit works for both ASCII/Unicode and EBCDIC+and is fast (a good compiler can turn it into a subtraction and unsigned+comparison). */++#define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9)++/* Table to identify hex digits. The tables in chartables are dependent on the+locale, and may mark arbitrary characters as digits. We want to recognize only+0-9, a-z, and A-Z as hex digits, which is why we have a private table here. It+costs 256 bytes, but it is a lot faster than doing character value tests (at+least in some simple cases I timed), and in some applications one wants PCRE2+to compile efficiently as well as match efficiently. The value in the table is+the binary hex digit value, or 0xff for non-hex digits. */++/* This is the "normal" case, for ASCII systems, and EBCDIC systems running in+UTF-8 mode. */++#ifndef EBCDIC+static const uint8_t xdigitab[] =+ {+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0- 7 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 8- 15 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 16- 23 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 24- 31 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - ' */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* ( - / */+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0 - 7 */+ 0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff, /* 8 - ? */+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* @ - G */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* H - O */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* P - W */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* X - _ */+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* ` - g */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* h - o */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* p - w */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* x -127 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 128-135 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 136-143 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 144-151 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 152-159 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 160-167 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 168-175 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 176-183 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 184-191 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 192-199 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 2ff-207 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 208-215 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 216-223 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 224-231 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 232-239 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 240-247 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};/* 248-255 */++#else++/* This is the "abnormal" case, for EBCDIC systems not running in UTF-8 mode. */++static const uint8_t xdigitab[] =+ {+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0- 7 0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 8- 15 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 16- 23 10 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 24- 31 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 32- 39 20 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 40- 47 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 48- 55 30 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 56- 63 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - 71 40 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 72- | */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* & - 87 50 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 88- 95 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - -103 60 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 104- ? */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 112-119 70 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 120- " */+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* 128- g 80 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* h -143 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 144- p 90 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* q -159 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 160- x A0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* y -175 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* ^ -183 B0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 184-191 */+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* { - G C0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* H -207 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* } - P D0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* Q -223 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* \ - X E0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* Y -239 */+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0 - 7 F0 */+ 0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff};/* 8 -255 */+#endif /* EBCDIC */+++/* Table for handling alphanumeric escaped characters. Positive returns are+simple data values; negative values are for special things like \d and so on.+Zero means further processing is needed (for things like \x), or the escape is+invalid. */++/* This is the "normal" table for ASCII systems or for EBCDIC systems running+in UTF-8 mode. It runs from '0' to 'z'. */++#ifndef EBCDIC+#define ESCAPES_FIRST CHAR_0+#define ESCAPES_LAST CHAR_z+#define UPPER_CASE(c) (c-32)++static const short int escapes[] = {+ 0, 0,+ 0, 0,+ 0, 0,+ 0, 0,+ 0, 0,+ CHAR_COLON, CHAR_SEMICOLON,+ CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN,+ CHAR_GREATER_THAN_SIGN, CHAR_QUESTION_MARK,+ CHAR_COMMERCIAL_AT, -ESC_A,+ -ESC_B, -ESC_C,+ -ESC_D, -ESC_E,+ 0, -ESC_G,+ -ESC_H, 0,+ 0, -ESC_K,+ 0, 0,+ -ESC_N, 0,+ -ESC_P, -ESC_Q,+ -ESC_R, -ESC_S,+ 0, 0,+ -ESC_V, -ESC_W,+ -ESC_X, 0,+ -ESC_Z, CHAR_LEFT_SQUARE_BRACKET,+ CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET,+ CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE,+ CHAR_GRAVE_ACCENT, CHAR_BEL,+ -ESC_b, 0,+ -ESC_d, CHAR_ESC,+ CHAR_FF, 0,+ -ESC_h, 0,+ 0, -ESC_k,+ 0, 0,+ CHAR_LF, 0,+ -ESC_p, 0,+ CHAR_CR, -ESC_s,+ CHAR_HT, 0,+ -ESC_v, -ESC_w,+ 0, 0,+ -ESC_z+};++#else++/* This is the "abnormal" table for EBCDIC systems without UTF-8 support.+It runs from 'a' to '9'. For some minimal testing of EBCDIC features, the code+is sometimes compiled on an ASCII system. In this case, we must not use CHAR_a+because it is defined as 'a', which of course picks up the ASCII value. */++#if 'a' == 0x81 /* Check for a real EBCDIC environment */+#define ESCAPES_FIRST CHAR_a+#define ESCAPES_LAST CHAR_9+#define UPPER_CASE(c) (c+64)+#else /* Testing in an ASCII environment */+#define ESCAPES_FIRST ((unsigned char)'\x81') /* EBCDIC 'a' */+#define ESCAPES_LAST ((unsigned char)'\xf9') /* EBCDIC '9' */+#define UPPER_CASE(c) (c-32)+#endif++static const short int escapes[] = {+/* 80 */ CHAR_BEL, -ESC_b, 0, -ESC_d, CHAR_ESC, CHAR_FF, 0,+/* 88 */ -ESC_h, 0, 0, '{', 0, 0, 0, 0,+/* 90 */ 0, 0, -ESC_k, 0, 0, CHAR_LF, 0, -ESC_p,+/* 98 */ 0, CHAR_CR, 0, '}', 0, 0, 0, 0,+/* A0 */ 0, '~', -ESC_s, CHAR_HT, 0, -ESC_v, -ESC_w, 0,+/* A8 */ 0, -ESC_z, 0, 0, 0, '[', 0, 0,+/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0,+/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-',+/* C0 */ '{', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G,+/* C8 */ -ESC_H, 0, 0, 0, 0, 0, 0, 0,+/* D0 */ '}', 0, -ESC_K, 0, 0, -ESC_N, 0, -ESC_P,+/* D8 */ -ESC_Q, -ESC_R, 0, 0, 0, 0, 0, 0,+/* E0 */ '\\', 0, -ESC_S, 0, 0, -ESC_V, -ESC_W, -ESC_X,+/* E8 */ 0, -ESC_Z, 0, 0, 0, 0, 0, 0,+/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,+/* F8 */ 0, 0+};++/* We also need a table of characters that may follow \c in an EBCDIC+environment for characters 0-31. */++static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";++#endif /* EBCDIC */+++/* Table of special "verbs" like (*PRUNE). This is a short table, so it is+searched linearly. Put all the names into a single string, in order to reduce+the number of relocations when a shared library is dynamically linked. The+string is built from string macros so that it works in UTF-8 mode on EBCDIC+platforms. */++typedef struct verbitem {+ unsigned int len; /* Length of verb name */+ uint32_t meta; /* Base META_ code */+ int has_arg; /* Argument requirement */+} verbitem;++static const char verbnames[] =+ "\0" /* Empty name is a shorthand for MARK */+ STRING_MARK0+ STRING_ACCEPT0+ STRING_F0+ STRING_FAIL0+ STRING_COMMIT0+ STRING_PRUNE0+ STRING_SKIP0+ STRING_THEN;++static const verbitem verbs[] = {+ { 0, META_MARK, +1 }, /* > 0 => must have an argument */+ { 4, META_MARK, +1 },+ { 6, META_ACCEPT, -1 }, /* < 0 => Optional argument, convert to pre-MARK */+ { 1, META_FAIL, -1 },+ { 4, META_FAIL, -1 },+ { 6, META_COMMIT, 0 },+ { 5, META_PRUNE, 0 }, /* Optional argument; bump META code if found */+ { 4, META_SKIP, 0 },+ { 4, META_THEN, 0 }+};++static const int verbcount = sizeof(verbs)/sizeof(verbitem);++/* Verb opcodes, indexed by their META code offset from META_MARK. */++static const uint32_t verbops[] = {+ OP_MARK, OP_ACCEPT, OP_FAIL, OP_COMMIT, OP_COMMIT_ARG, OP_PRUNE,+ OP_PRUNE_ARG, OP_SKIP, OP_SKIP_ARG, OP_THEN, OP_THEN_ARG };++/* Table of "alpha assertions" like (*pla:...), similar to the (*VERB) table. */++typedef struct alasitem {+ unsigned int len; /* Length of name */+ uint32_t meta; /* Base META_ code */+} alasitem;++static const char alasnames[] =+ STRING_pla0+ STRING_plb0+ STRING_napla0+ STRING_naplb0+ STRING_nla0+ STRING_nlb0+ STRING_positive_lookahead0+ STRING_positive_lookbehind0+ STRING_non_atomic_positive_lookahead0+ STRING_non_atomic_positive_lookbehind0+ STRING_negative_lookahead0+ STRING_negative_lookbehind0+ STRING_atomic0+ STRING_sr0+ STRING_asr0+ STRING_script_run0+ STRING_atomic_script_run;++static const alasitem alasmeta[] = {+ { 3, META_LOOKAHEAD },+ { 3, META_LOOKBEHIND },+ { 5, META_LOOKAHEAD_NA },+ { 5, META_LOOKBEHIND_NA },+ { 3, META_LOOKAHEADNOT },+ { 3, META_LOOKBEHINDNOT },+ { 18, META_LOOKAHEAD },+ { 19, META_LOOKBEHIND },+ { 29, META_LOOKAHEAD_NA },+ { 30, META_LOOKBEHIND_NA },+ { 18, META_LOOKAHEADNOT },+ { 19, META_LOOKBEHINDNOT },+ { 6, META_ATOMIC },+ { 2, META_SCRIPT_RUN }, /* sr = script run */+ { 3, META_ATOMIC_SCRIPT_RUN }, /* asr = atomic script run */+ { 10, META_SCRIPT_RUN }, /* script run */+ { 17, META_ATOMIC_SCRIPT_RUN } /* atomic script run */+};++static const int alascount = sizeof(alasmeta)/sizeof(alasitem);++/* Offsets from OP_STAR for case-independent and negative repeat opcodes. */++static uint32_t chartypeoffset[] = {+ OP_STAR - OP_STAR, OP_STARI - OP_STAR,+ OP_NOTSTAR - OP_STAR, OP_NOTSTARI - OP_STAR };++/* Tables of names of POSIX character classes and their lengths. The names are+now all in a single string, to reduce the number of relocations when a shared+library is dynamically loaded. The list of lengths is terminated by a zero+length entry. The first three must be alpha, lower, upper, as this is assumed+for handling case independence. The indices for several classes are needed, so+identify them. */++static const char posix_names[] =+ STRING_alpha0 STRING_lower0 STRING_upper0 STRING_alnum0+ STRING_ascii0 STRING_blank0 STRING_cntrl0 STRING_digit0+ STRING_graph0 STRING_print0 STRING_punct0 STRING_space0+ STRING_word0 STRING_xdigit;++static const uint8_t posix_name_lengths[] = {+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };++#define PC_DIGIT 7+#define PC_GRAPH 8+#define PC_PRINT 9+#define PC_PUNCT 10+#define PC_XDIGIT 13++/* Table of class bit maps for each POSIX class. Each class is formed from a+base map, with an optional addition or removal of another map. Then, for some+classes, there is some additional tweaking: for [:blank:] the vertical space+characters are removed, and for [:alpha:] and [:alnum:] the underscore+character is removed. The triples in the table consist of the base map offset,+second map offset or -1 if no second map, and a non-negative value for map+addition or a negative value for map subtraction (if there are two maps). The+absolute value of the third field has these meanings: 0 => no tweaking, 1 =>+remove vertical space characters, 2 => remove underscore. */++static const int posix_class_maps[] = {+ cbit_word, cbit_digit, -2, /* alpha */+ cbit_lower, -1, 0, /* lower */+ cbit_upper, -1, 0, /* upper */+ cbit_word, -1, 2, /* alnum - word without underscore */+ cbit_print, cbit_cntrl, 0, /* ascii */+ cbit_space, -1, 1, /* blank - a GNU extension */+ cbit_cntrl, -1, 0, /* cntrl */+ cbit_digit, -1, 0, /* digit */+ cbit_graph, -1, 0, /* graph */+ cbit_print, -1, 0, /* print */+ cbit_punct, -1, 0, /* punct */+ cbit_space, -1, 0, /* space */+ cbit_word, -1, 0, /* word - a Perl extension */+ cbit_xdigit, -1, 0 /* xdigit */+};++#ifdef SUPPORT_UNICODE++/* The POSIX class Unicode property substitutes that are used in UCP mode must+be in the order of the POSIX class names, defined above. */++static int posix_substitutes[] = {+ PT_GC, ucp_L, /* alpha */+ PT_PC, ucp_Ll, /* lower */+ PT_PC, ucp_Lu, /* upper */+ PT_ALNUM, 0, /* alnum */+ -1, 0, /* ascii, treat as non-UCP */+ -1, 1, /* blank, treat as \h */+ PT_PC, ucp_Cc, /* cntrl */+ PT_PC, ucp_Nd, /* digit */+ PT_PXGRAPH, 0, /* graph */+ PT_PXPRINT, 0, /* print */+ PT_PXPUNCT, 0, /* punct */+ PT_PXSPACE, 0, /* space */ /* Xps is POSIX space, but from 8.34 */+ PT_WORD, 0, /* word */ /* Perl and POSIX space are the same */+ PT_PXXDIGIT, 0 /* xdigit */ /* Perl has additional hex digits */+};+#define POSIX_SUBSIZE (sizeof(posix_substitutes) / (2*sizeof(uint32_t)))+#endif /* SUPPORT_UNICODE */++/* Masks for checking option settings. When PCRE2_LITERAL is set, only a subset+are allowed. */++#define PUBLIC_LITERAL_COMPILE_OPTIONS \+ (PCRE2_ANCHORED|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_ENDANCHORED| \+ PCRE2_FIRSTLINE|PCRE2_LITERAL|PCRE2_MATCH_INVALID_UTF| \+ PCRE2_NO_START_OPTIMIZE|PCRE2_NO_UTF_CHECK|PCRE2_USE_OFFSET_LIMIT|PCRE2_UTF)++#define PUBLIC_COMPILE_OPTIONS \+ (PUBLIC_LITERAL_COMPILE_OPTIONS| \+ PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \+ PCRE2_ALT_VERBNAMES|PCRE2_DOLLAR_ENDONLY|PCRE2_DOTALL|PCRE2_DUPNAMES| \+ PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_MATCH_UNSET_BACKREF| \+ PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C|PCRE2_NEVER_UCP| \+ PCRE2_NEVER_UTF|PCRE2_NO_AUTO_CAPTURE|PCRE2_NO_AUTO_POSSESS| \+ PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_UCP|PCRE2_UNGREEDY)++#define PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS \+ (PCRE2_EXTRA_MATCH_LINE|PCRE2_EXTRA_MATCH_WORD|PCRE2_EXTRA_CASELESS_RESTRICT)++#define PUBLIC_COMPILE_EXTRA_OPTIONS \+ (PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS| \+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES|PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL| \+ PCRE2_EXTRA_ESCAPED_CR_IS_LF|PCRE2_EXTRA_ALT_BSUX| \+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK|PCRE2_EXTRA_ASCII_BSD| \+ PCRE2_EXTRA_ASCII_BSS|PCRE2_EXTRA_ASCII_BSW|PCRE2_EXTRA_ASCII_POSIX| \+ PCRE2_EXTRA_ASCII_DIGIT)++/* Compile time error code numbers. They are given names so that they can more+easily be tracked. When a new number is added, the tables called eint1 and+eint2 in pcre2posix.c may need to be updated, and a new error text must be+added to compile_error_texts in pcre2_error.c. Also, the error codes in+pcre2.h.in must be updated - their values are exactly 100 greater than these+values. */++enum { ERR0 = COMPILE_ERROR_BASE,+ ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10,+ ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20,+ ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30,+ ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40,+ ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, 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, ERR87, ERR88, ERR89, ERR90,+ ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98, ERR99, ERR100,+ ERR101 };++/* This is a table of start-of-pattern options such as (*UTF) and settings such+as (*LIMIT_MATCH=nnnn) and (*CRLF). For completeness and backward+compatibility, (*UTFn) is supported in the relevant libraries, but (*UTF) is+generic and always supported. */++enum { PSO_OPT, /* Value is an option bit */+ PSO_FLG, /* Value is a flag bit */+ PSO_NL, /* Value is a newline type */+ PSO_BSR, /* Value is a \R type */+ PSO_LIMH, /* Read integer value for heap limit */+ PSO_LIMM, /* Read integer value for match limit */+ PSO_LIMD /* Read integer value for depth limit */+ };++typedef struct pso {+ const uint8_t *name;+ uint16_t length;+ uint16_t type;+ uint32_t value;+} pso;++/* NB: STRING_UTFn_RIGHTPAR contains the length as well */++static const pso pso_list[] = {+ { (uint8_t *)STRING_UTFn_RIGHTPAR, PSO_OPT, PCRE2_UTF },+ { (uint8_t *)STRING_UTF_RIGHTPAR, 4, PSO_OPT, PCRE2_UTF },+ { (uint8_t *)STRING_UCP_RIGHTPAR, 4, PSO_OPT, PCRE2_UCP },+ { (uint8_t *)STRING_NOTEMPTY_RIGHTPAR, 9, PSO_FLG, PCRE2_NOTEMPTY_SET },+ { (uint8_t *)STRING_NOTEMPTY_ATSTART_RIGHTPAR, 17, PSO_FLG, PCRE2_NE_ATST_SET },+ { (uint8_t *)STRING_NO_AUTO_POSSESS_RIGHTPAR, 16, PSO_OPT, PCRE2_NO_AUTO_POSSESS },+ { (uint8_t *)STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR, 18, PSO_OPT, PCRE2_NO_DOTSTAR_ANCHOR },+ { (uint8_t *)STRING_NO_JIT_RIGHTPAR, 7, PSO_FLG, PCRE2_NOJIT },+ { (uint8_t *)STRING_NO_START_OPT_RIGHTPAR, 13, PSO_OPT, PCRE2_NO_START_OPTIMIZE },+ { (uint8_t *)STRING_LIMIT_HEAP_EQ, 11, PSO_LIMH, 0 },+ { (uint8_t *)STRING_LIMIT_MATCH_EQ, 12, PSO_LIMM, 0 },+ { (uint8_t *)STRING_LIMIT_DEPTH_EQ, 12, PSO_LIMD, 0 },+ { (uint8_t *)STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMD, 0 },+ { (uint8_t *)STRING_CR_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_CR },+ { (uint8_t *)STRING_LF_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_LF },+ { (uint8_t *)STRING_CRLF_RIGHTPAR, 5, PSO_NL, PCRE2_NEWLINE_CRLF },+ { (uint8_t *)STRING_ANY_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_ANY },+ { (uint8_t *)STRING_NUL_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_NUL },+ { (uint8_t *)STRING_ANYCRLF_RIGHTPAR, 8, PSO_NL, PCRE2_NEWLINE_ANYCRLF },+ { (uint8_t *)STRING_BSR_ANYCRLF_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_ANYCRLF },+ { (uint8_t *)STRING_BSR_UNICODE_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_UNICODE }+};++/* This table is used when converting repeating opcodes into possessified+versions as a result of an explicit possessive quantifier such as ++. A zero+value means there is no possessified version - in those cases the item in+question must be wrapped in ONCE brackets. The table is truncated at OP_CALLOUT+because all relevant opcodes are less than that. */++static const uint8_t opcode_possessify[] = {+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 15 */+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 31 */++ 0, /* NOTI */+ OP_POSSTAR, 0, /* STAR, MINSTAR */+ OP_POSPLUS, 0, /* PLUS, MINPLUS */+ OP_POSQUERY, 0, /* QUERY, MINQUERY */+ OP_POSUPTO, 0, /* UPTO, MINUPTO */+ 0, /* EXACT */+ 0, 0, 0, 0, /* POS{STAR,PLUS,QUERY,UPTO} */++ OP_POSSTARI, 0, /* STARI, MINSTARI */+ OP_POSPLUSI, 0, /* PLUSI, MINPLUSI */+ OP_POSQUERYI, 0, /* QUERYI, MINQUERYI */+ OP_POSUPTOI, 0, /* UPTOI, MINUPTOI */+ 0, /* EXACTI */+ 0, 0, 0, 0, /* POS{STARI,PLUSI,QUERYI,UPTOI} */++ OP_NOTPOSSTAR, 0, /* NOTSTAR, NOTMINSTAR */+ OP_NOTPOSPLUS, 0, /* NOTPLUS, NOTMINPLUS */+ OP_NOTPOSQUERY, 0, /* NOTQUERY, NOTMINQUERY */+ OP_NOTPOSUPTO, 0, /* NOTUPTO, NOTMINUPTO */+ 0, /* NOTEXACT */+ 0, 0, 0, 0, /* NOTPOS{STAR,PLUS,QUERY,UPTO} */++ OP_NOTPOSSTARI, 0, /* NOTSTARI, NOTMINSTARI */+ OP_NOTPOSPLUSI, 0, /* NOTPLUSI, NOTMINPLUSI */+ OP_NOTPOSQUERYI, 0, /* NOTQUERYI, NOTMINQUERYI */+ OP_NOTPOSUPTOI, 0, /* NOTUPTOI, NOTMINUPTOI */+ 0, /* NOTEXACTI */+ 0, 0, 0, 0, /* NOTPOS{STARI,PLUSI,QUERYI,UPTOI} */++ OP_TYPEPOSSTAR, 0, /* TYPESTAR, TYPEMINSTAR */+ OP_TYPEPOSPLUS, 0, /* TYPEPLUS, TYPEMINPLUS */+ OP_TYPEPOSQUERY, 0, /* TYPEQUERY, TYPEMINQUERY */+ OP_TYPEPOSUPTO, 0, /* TYPEUPTO, TYPEMINUPTO */+ 0, /* TYPEEXACT */+ 0, 0, 0, 0, /* TYPEPOS{STAR,PLUS,QUERY,UPTO} */++ OP_CRPOSSTAR, 0, /* CRSTAR, CRMINSTAR */+ OP_CRPOSPLUS, 0, /* CRPLUS, CRMINPLUS */+ OP_CRPOSQUERY, 0, /* CRQUERY, CRMINQUERY */+ OP_CRPOSRANGE, 0, /* CRRANGE, CRMINRANGE */+ 0, 0, 0, 0, /* CRPOS{STAR,PLUS,QUERY,RANGE} */++ 0, 0, 0, /* CLASS, NCLASS, XCLASS */+ 0, 0, /* REF, REFI */+ 0, 0, /* DNREF, DNREFI */+ 0, 0 /* RECURSE, CALLOUT */+};+++#ifdef DEBUG_SHOW_PARSED+/*************************************************+* Show the parsed pattern for debugging *+*************************************************/++/* For debugging the pre-scan, this code, which outputs the parsed data vector,+can be enabled. */++static void show_parsed(compile_block *cb)+{+uint32_t *pptr = cb->parsed_pattern;++for (;;)+ {+ int max, min;+ PCRE2_SIZE offset;+ uint32_t i;+ uint32_t length;+ uint32_t meta_arg = META_DATA(*pptr);++ fprintf(stderr, "+++ %02d %.8x ", (int)(pptr - cb->parsed_pattern), *pptr);++ if (*pptr < META_END)+ {+ if (*pptr > 32 && *pptr < 128) fprintf(stderr, "%c", *pptr);+ pptr++;+ }++ else switch (META_CODE(*pptr++))+ {+ default:+ fprintf(stderr, "**** OOPS - unknown META value - giving up ****\n");+ return;++ case META_END:+ fprintf(stderr, "META_END\n");+ return;++ case META_CAPTURE:+ fprintf(stderr, "META_CAPTURE %d", meta_arg);+ break;++ case META_RECURSE:+ GETOFFSET(offset, pptr);+ fprintf(stderr, "META_RECURSE %d %zd", meta_arg, offset);+ break;++ case META_BACKREF:+ if (meta_arg < 10)+ offset = cb->small_ref_offset[meta_arg];+ else+ GETOFFSET(offset, pptr);+ fprintf(stderr, "META_BACKREF %d %zd", meta_arg, offset);+ break;++ case META_ESCAPE:+ if (meta_arg == ESC_P || meta_arg == ESC_p)+ {+ uint32_t ptype = *pptr >> 16;+ uint32_t pvalue = *pptr++ & 0xffff;+ fprintf(stderr, "META \\%c %d %d", (meta_arg == ESC_P)? 'P':'p',+ ptype, pvalue);+ }+ else+ {+ uint32_t cc;+ /* There's just one escape we might have here that isn't negated in the+ escapes table. */+ if (meta_arg == ESC_g) cc = CHAR_g;+ else for (cc = ESCAPES_FIRST; cc <= ESCAPES_LAST; cc++)+ {+ if (meta_arg == (uint32_t)(-escapes[cc - ESCAPES_FIRST])) break;+ }+ if (cc > ESCAPES_LAST) cc = CHAR_QUESTION_MARK;+ fprintf(stderr, "META \\%c", cc);+ }+ break;++ case META_MINMAX:+ min = *pptr++;+ max = *pptr++;+ if (max != REPEAT_UNLIMITED)+ fprintf(stderr, "META {%d,%d}", min, max);+ else+ fprintf(stderr, "META {%d,}", min);+ break;++ case META_MINMAX_QUERY:+ min = *pptr++;+ max = *pptr++;+ if (max != REPEAT_UNLIMITED)+ fprintf(stderr, "META {%d,%d}?", min, max);+ else+ fprintf(stderr, "META {%d,}?", min);+ break;++ case META_MINMAX_PLUS:+ min = *pptr++;+ max = *pptr++;+ if (max != REPEAT_UNLIMITED)+ fprintf(stderr, "META {%d,%d}+", min, max);+ else+ fprintf(stderr, "META {%d,}+", min);+ break;++ case META_BIGVALUE: fprintf(stderr, "META_BIGVALUE %.8x", *pptr++); break;+ case META_CIRCUMFLEX: fprintf(stderr, "META_CIRCUMFLEX"); break;+ case META_COND_ASSERT: fprintf(stderr, "META_COND_ASSERT"); break;+ case META_DOLLAR: fprintf(stderr, "META_DOLLAR"); break;+ case META_DOT: fprintf(stderr, "META_DOT"); break;+ case META_ASTERISK: fprintf(stderr, "META *"); break;+ case META_ASTERISK_QUERY: fprintf(stderr, "META *?"); break;+ case META_ASTERISK_PLUS: fprintf(stderr, "META *+"); break;+ case META_PLUS: fprintf(stderr, "META +"); break;+ case META_PLUS_QUERY: fprintf(stderr, "META +?"); break;+ case META_PLUS_PLUS: fprintf(stderr, "META ++"); break;+ case META_QUERY: fprintf(stderr, "META ?"); break;+ case META_QUERY_QUERY: fprintf(stderr, "META ??"); break;+ case META_QUERY_PLUS: fprintf(stderr, "META ?+"); break;++ case META_ATOMIC: fprintf(stderr, "META (?>"); break;+ case META_NOCAPTURE: fprintf(stderr, "META (?:"); break;+ case META_LOOKAHEAD: fprintf(stderr, "META (?="); break;+ case META_LOOKAHEADNOT: fprintf(stderr, "META (?!"); break;+ case META_LOOKAHEAD_NA: fprintf(stderr, "META (*napla:"); break;+ case META_SCRIPT_RUN: fprintf(stderr, "META (*sr:"); break;+ case META_KET: fprintf(stderr, "META )"); break;+ case META_ALT: fprintf(stderr, "META | %d", meta_arg); break;++ case META_CLASS: fprintf(stderr, "META ["); break;+ case META_CLASS_NOT: fprintf(stderr, "META [^"); break;+ case META_CLASS_END: fprintf(stderr, "META ]"); break;+ case META_CLASS_EMPTY: fprintf(stderr, "META []"); break;+ case META_CLASS_EMPTY_NOT: fprintf(stderr, "META [^]"); break;++ case META_RANGE_LITERAL: fprintf(stderr, "META - (literal)"); break;+ case META_RANGE_ESCAPED: fprintf(stderr, "META - (escaped)"); break;++ case META_POSIX: fprintf(stderr, "META_POSIX %d", *pptr++); break;+ case META_POSIX_NEG: fprintf(stderr, "META_POSIX_NEG %d", *pptr++); break;++ case META_ACCEPT: fprintf(stderr, "META (*ACCEPT)"); break;+ case META_FAIL: fprintf(stderr, "META (*FAIL)"); break;+ case META_COMMIT: fprintf(stderr, "META (*COMMIT)"); break;+ case META_PRUNE: fprintf(stderr, "META (*PRUNE)"); break;+ case META_SKIP: fprintf(stderr, "META (*SKIP)"); break;+ case META_THEN: fprintf(stderr, "META (*THEN)"); break;++ case META_OPTIONS:+ fprintf(stderr, "META_OPTIONS 0x%08x 0x%08x", pptr[0], pptr[1]);+ pptr += 2;+ break;++ case META_LOOKBEHIND:+ fprintf(stderr, "META (?<= %d %d", meta_arg, *pptr);+ pptr += 2;+ break;++ case META_LOOKBEHIND_NA:+ fprintf(stderr, "META (*naplb: %d %d", meta_arg, *pptr);+ pptr += 2;+ break;++ case META_LOOKBEHINDNOT:+ fprintf(stderr, "META (?<! %d %d", meta_arg, *pptr);+ pptr += 2;+ break;++ case META_CALLOUT_NUMBER:+ fprintf(stderr, "META (?C%d) next=%d/%d", pptr[2], pptr[0],+ pptr[1]);+ pptr += 3;+ break;++ case META_CALLOUT_STRING:+ {+ uint32_t patoffset = *pptr++; /* Offset of next pattern item */+ uint32_t patlength = *pptr++; /* Length of next pattern item */+ fprintf(stderr, "META (?Cstring) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd next=%d/%d", offset, patoffset, patlength);+ }+ break;++ case META_RECURSE_BYNAME:+ fprintf(stderr, "META (?(&name) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_BACKREF_BYNAME:+ fprintf(stderr, "META_BACKREF_BYNAME length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_COND_NUMBER:+ fprintf(stderr, "META_COND_NUMBER %d offset=", pptr[SIZEOFFSET]);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ pptr++;+ break;++ case META_COND_DEFINE:+ fprintf(stderr, "META (?(DEFINE) offset=");+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_COND_VERSION:+ fprintf(stderr, "META (?(VERSION%s", (*pptr++ == 0)? "=" : ">=");+ fprintf(stderr, "%d.", *pptr++);+ fprintf(stderr, "%d)", *pptr++);+ break;++ case META_COND_NAME:+ fprintf(stderr, "META (?(<name>) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_COND_RNAME:+ fprintf(stderr, "META (?(R&name) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ /* This is kept as a name, because it might be. */++ case META_COND_RNUMBER:+ fprintf(stderr, "META (?(Rnumber) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_MARK:+ fprintf(stderr, "META (*MARK:");+ goto SHOWARG;++ case META_COMMIT_ARG:+ fprintf(stderr, "META (*COMMIT:");+ goto SHOWARG;++ case META_PRUNE_ARG:+ fprintf(stderr, "META (*PRUNE:");+ goto SHOWARG;++ case META_SKIP_ARG:+ fprintf(stderr, "META (*SKIP:");+ goto SHOWARG;++ case META_THEN_ARG:+ fprintf(stderr, "META (*THEN:");+ SHOWARG:+ length = *pptr++;+ for (i = 0; i < length; i++)+ {+ uint32_t cc = *pptr++;+ if (cc > 32 && cc < 128) fprintf(stderr, "%c", cc);+ else fprintf(stderr, "\\x{%x}", cc);+ }+ fprintf(stderr, ") length=%u", length);+ break;+ }+ fprintf(stderr, "\n");+ }+return;+}+#endif /* DEBUG_SHOW_PARSED */++++/*************************************************+* Copy compiled code *+*************************************************/++/* Compiled JIT code cannot be copied, so the new compiled block has no+associated JIT data. */++PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION+pcre2_code_copy(const pcre2_code *code)+{+PCRE2_SIZE* ref_count;+pcre2_code *newcode;++if (code == NULL) return NULL;+newcode = code->memctl.malloc(code->blocksize, code->memctl.memory_data);+if (newcode == NULL) return NULL;+memcpy(newcode, code, code->blocksize);+newcode->executable_jit = NULL;++/* If the code is one that has been deserialized, increment the reference count+in the decoded tables. */++if ((code->flags & PCRE2_DEREF_TABLES) != 0)+ {+ ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH);+ (*ref_count)++;+ }++return newcode;+}++++/*************************************************+* Copy compiled code and character tables *+*************************************************/++/* Compiled JIT code cannot be copied, so the new compiled block has no+associated JIT data. This version of code_copy also makes a separate copy of+the character tables. */++PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION+pcre2_code_copy_with_tables(const pcre2_code *code)+{+PCRE2_SIZE* ref_count;+pcre2_code *newcode;+uint8_t *newtables;++if (code == NULL) return NULL;+newcode = code->memctl.malloc(code->blocksize, code->memctl.memory_data);+if (newcode == NULL) return NULL;+memcpy(newcode, code, code->blocksize);+newcode->executable_jit = NULL;++newtables = code->memctl.malloc(TABLES_LENGTH + sizeof(PCRE2_SIZE),+ code->memctl.memory_data);+if (newtables == NULL)+ {+ code->memctl.free((void *)newcode, code->memctl.memory_data);+ return NULL;+ }+memcpy(newtables, code->tables, TABLES_LENGTH);+ref_count = (PCRE2_SIZE *)(newtables + TABLES_LENGTH);+*ref_count = 1;++newcode->tables = newtables;+newcode->flags |= PCRE2_DEREF_TABLES;+return newcode;+}++++/*************************************************+* Free compiled code *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_code_free(pcre2_code *code)+{+PCRE2_SIZE* ref_count;++if (code != NULL)+ {+#ifdef SUPPORT_JIT+ if (code->executable_jit != NULL)+ PRIV(jit_free)(code->executable_jit, &code->memctl);+#endif++ if ((code->flags & PCRE2_DEREF_TABLES) != 0)+ {+ /* Decoded tables belong to the codes after deserialization, and they must+ be freed when there are no more references to them. The *ref_count should+ always be > 0. */++ ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH);+ if (*ref_count > 0)+ {+ (*ref_count)--;+ if (*ref_count == 0)+ code->memctl.free((void *)code->tables, code->memctl.memory_data);+ }+ }++ code->memctl.free(code, code->memctl.memory_data);+ }+}++++/*************************************************+* Read a number, possibly signed *+*************************************************/++/* This function is used to read numbers in the pattern. The initial pointer+must be at the sign or first digit of the number. When relative values+(introduced by + or -) are allowed, they are relative group numbers, and the+result must be greater than zero.++Arguments:+ ptrptr points to the character pointer variable+ ptrend points to the end of the input string+ allow_sign if < 0, sign not allowed; if >= 0, sign is relative to this+ max_value the largest number allowed+ max_error the error to give for an over-large number+ intptr where to put the result+ errcodeptr where to put an error code++Returns: TRUE - a number was read+ FALSE - errorcode == 0 => no number was found+ errorcode != 0 => an error occurred+*/++static BOOL+read_number(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, int32_t allow_sign,+ uint32_t max_value, uint32_t max_error, int *intptr, int *errorcodeptr)+{+int sign = 0;+uint32_t n = 0;+PCRE2_SPTR ptr = *ptrptr;+BOOL yield = FALSE;++*errorcodeptr = 0;++if (allow_sign >= 0 && ptr < ptrend)+ {+ if (*ptr == CHAR_PLUS)+ {+ sign = +1;+ max_value -= allow_sign;+ ptr++;+ }+ else if (*ptr == CHAR_MINUS)+ {+ sign = -1;+ ptr++;+ }+ }++if (ptr >= ptrend || !IS_DIGIT(*ptr)) return FALSE;+while (ptr < ptrend && IS_DIGIT(*ptr))+ {+ n = n * 10 + *ptr++ - CHAR_0;+ if (n > max_value)+ {+ *errorcodeptr = max_error;+ goto EXIT;+ }+ }++if (allow_sign >= 0 && sign != 0)+ {+ if (n == 0)+ {+ *errorcodeptr = ERR26; /* +0 and -0 are not allowed */+ goto EXIT;+ }++ if (sign > 0) n += allow_sign;+ else if ((int)n > allow_sign)+ {+ *errorcodeptr = ERR15; /* Non-existent subpattern */+ goto EXIT;+ }+ else n = allow_sign + 1 - n;+ }++yield = TRUE;++EXIT:+*intptr = n;+*ptrptr = ptr;+return yield;+}++++/*************************************************+* Read repeat counts *+*************************************************/++/* Read an item of the form {n,m} and return the values when non-NULL pointers+are supplied. Repeat counts must be less than 65536 (MAX_REPEAT_COUNT); a+larger value is used for "unlimited". We have to use signed arguments for+read_number() because it is capable of returning a signed value. As of Perl+5.34.0 either n or m may be absent, but not both. Perl also allows spaces and+tabs after { and before } and between the numbers and the comma, so we do too.++Arguments:+ ptrptr points to pointer to character after '{'+ ptrend pointer to end of input+ minp if not NULL, pointer to int for min+ maxp if not NULL, pointer to int for max+ errorcodeptr points to error code variable++Returns: FALSE if not a repeat quantifier, errorcode set zero+ FALSE on error, with errorcode set non-zero+ TRUE on success, with pointer updated to point after '}'+*/++static BOOL+read_repeat_counts(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *minp,+ uint32_t *maxp, int *errorcodeptr)+{+PCRE2_SPTR p = *ptrptr;+PCRE2_SPTR pp;+BOOL yield = FALSE;+BOOL had_minimum = FALSE;+int32_t min = 0;+int32_t max = REPEAT_UNLIMITED; /* This value is larger than MAX_REPEAT_COUNT */++*errorcodeptr = 0;+while (p < ptrend && (*p == CHAR_SPACE || *p == CHAR_HT)) p++;++/* Check the syntax before interpreting. Otherwise, a non-quantifier sequence+such as "X{123456ABC" would incorrectly give a "number too big in quantifier"+error. */++pp = p;+if (pp < ptrend && IS_DIGIT(*pp))+ {+ had_minimum = TRUE;+ while (++pp < ptrend && IS_DIGIT(*pp)) {}+ }++while (pp < ptrend && (*pp == CHAR_SPACE || *pp == CHAR_HT)) pp++;+if (pp >= ptrend) return FALSE;++if (*pp == CHAR_RIGHT_CURLY_BRACKET)+ {+ if (!had_minimum) return FALSE;+ }+else+ {+ if (*pp++ != CHAR_COMMA) return FALSE;+ while (pp < ptrend && (*pp == CHAR_SPACE || *pp == CHAR_HT)) pp++;+ if (pp >= ptrend) return FALSE;+ if (IS_DIGIT(*pp))+ {+ while (++pp < ptrend && IS_DIGIT(*pp)) {}+ }+ else if (!had_minimum) return FALSE;+ while (pp < ptrend && (*pp == CHAR_SPACE || *pp == CHAR_HT)) pp++;+ if (pp >= ptrend || *pp != CHAR_RIGHT_CURLY_BRACKET) return FALSE;+ }++/* Now process the quantifier for real. We know it must be {n} or (n,} or {,m}+or {n,m}. The only error that read_number() can return is for a number that is+too big. If *errorcodeptr is returned as zero it means no number was found. */++/* Deal with {,m} or n too big. If we successfully read m there is no need to+check m >= n because n defaults to zero. */++if (!read_number(&p, ptrend, -1, MAX_REPEAT_COUNT, ERR5, &min, errorcodeptr))+ {+ if (*errorcodeptr != 0) goto EXIT; /* n too big */+ p++; /* Skip comma and subsequent spaces */+ while (p < ptrend && (*p == CHAR_SPACE || *p == CHAR_HT)) p++;+ if (!read_number(&p, ptrend, -1, MAX_REPEAT_COUNT, ERR5, &max, errorcodeptr))+ {+ if (*errorcodeptr != 0) goto EXIT; /* m too big */+ }+ }++/* Have read one number. Deal with {n} or {n,} or {n,m} */++else+ {+ while (p < ptrend && (*p == CHAR_SPACE || *p == CHAR_HT)) p++;+ if (*p == CHAR_RIGHT_CURLY_BRACKET)+ {+ max = min;+ }+ else /* Handle {n,} or {n,m} */+ {+ p++; /* Skip comma and subsequent spaces */+ while (p < ptrend && (*p == CHAR_SPACE || *p == CHAR_HT)) p++;+ if (!read_number(&p, ptrend, -1, MAX_REPEAT_COUNT, ERR5, &max, errorcodeptr))+ {+ if (*errorcodeptr != 0) goto EXIT; /* m too big */+ }++ if (max < min)+ {+ *errorcodeptr = ERR4;+ goto EXIT;+ }+ }+ }++/* Valid quantifier exists */++while (p < ptrend && (*p == CHAR_SPACE || *p == CHAR_HT)) p++;+p++;+yield = TRUE;+if (minp != NULL) *minp = (uint32_t)min;+if (maxp != NULL) *maxp = (uint32_t)max;++/* Update the pattern pointer */++EXIT:+*ptrptr = p;+return yield;+}++++/*************************************************+* Handle escapes *+*************************************************/++/* This function is called when a \ has been encountered. It either returns a+positive value for a simple escape such as \d, or 0 for a data character, which+is placed in chptr. A backreference to group n is returned as negative n. On+entry, ptr is pointing at the character after \. On exit, it points after the+final code unit of the escape sequence.++This function is also called from pcre2_substitute() to handle escape sequences+in replacement strings. In this case, the cb argument is NULL, and in the case+of escapes that have further processing, only sequences that define a data+character are recognised. The isclass argument is not relevant; the options+argument is the final value of the compiled pattern's options.++Arguments:+ ptrptr points to the input position pointer+ ptrend points to the end of the input+ chptr points to a returned data character+ errorcodeptr points to the errorcode variable (containing zero)+ options the current options bits+ xoptions the current extra options bits+ isclass TRUE if inside a character class+ cb compile data block or NULL when called from pcre2_substitute()++Returns: zero => a data character+ positive => a special escape sequence+ negative => a numerical back reference+ on error, errorcodeptr is set non-zero+*/++int+PRIV(check_escape)(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *chptr,+ int *errorcodeptr, uint32_t options, uint32_t xoptions, BOOL isclass,+ compile_block *cb)+{+BOOL utf = (options & PCRE2_UTF) != 0;+BOOL alt_bsux =+ ((options & PCRE2_ALT_BSUX) | (xoptions & PCRE2_EXTRA_ALT_BSUX)) != 0;+PCRE2_SPTR ptr = *ptrptr;+uint32_t c, cc;+int escape = 0;+int i;++/* If backslash is at the end of the string, it's an error. */++if (ptr >= ptrend)+ {+ *errorcodeptr = ERR1;+ return 0;+ }++GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */+*errorcodeptr = 0; /* Be optimistic */++/* Non-alphanumerics are literals, so we just leave the value in c. An initial+value test saves a memory lookup for code points outside the alphanumeric+range. */++if (c < ESCAPES_FIRST || c > ESCAPES_LAST) {} /* Definitely literal */++/* Otherwise, do a table lookup. Non-zero values need little processing here. A+positive value is a literal value for something like \n. A negative value is+the negation of one of the ESC_ macros that is passed back for handling by the+calling function. Some extra checking is needed for \N because only \N{U+dddd}+is supported. If the value is zero, further processing is handled below. */++else if ((i = escapes[c - ESCAPES_FIRST]) != 0)+ {+ if (i > 0)+ {+ c = (uint32_t)i;+ if (c == CHAR_CR && (xoptions & PCRE2_EXTRA_ESCAPED_CR_IS_LF) != 0)+ c = CHAR_LF;+ }+ else /* Negative table entry */+ {+ escape = -i; /* Else return a special escape */+ if (cb != NULL && (escape == ESC_P || escape == ESC_p || escape == ESC_X))+ cb->external_flags |= PCRE2_HASBKPORX; /* Note \P, \p, or \X */++ /* Perl supports \N{name} for character names and \N{U+dddd} for numerical+ Unicode code points, as well as plain \N for "not newline". PCRE does not+ support \N{name}. However, it does support quantification such as \N{2,3},+ so if \N{ is not followed by U+dddd we check for a quantifier. */++ if (escape == ESC_N && ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET)+ {+ PCRE2_SPTR p = ptr + 1;++ /* Perl ignores spaces and tabs after { */++ while (p < ptrend && (*p == CHAR_SPACE || *p == CHAR_HT)) p++;++ /* \N{U+ can be handled by the \x{ code. However, this construction is+ not valid in EBCDIC environments because it specifies a Unicode+ character, not a codepoint in the local code. For example \N{U+0041}+ must be "A" in all environments. Also, in Perl, \N{U+ forces Unicode+ casing semantics for the entire pattern, so allow it only in UTF (i.e.+ Unicode) mode. */++ if (ptrend - p > 1 && *p == CHAR_U && p[1] == CHAR_PLUS)+ {+#ifdef EBCDIC+ *errorcodeptr = ERR93;+#else+ if (utf)+ {+ ptr = p + 2;+ escape = 0; /* Not a fancy escape after all */+ goto COME_FROM_NU;+ }+ else *errorcodeptr = ERR93;+#endif+ }++ /* Give an error if what follows is not a quantifier, but don't override+ an error set by the quantifier reader (e.g. number overflow). */++ else+ {+ if (!read_repeat_counts(&p, ptrend, NULL, NULL, errorcodeptr) &&+ *errorcodeptr == 0)+ *errorcodeptr = ERR37;+ }+ }+ }+ }++/* Escapes that need further processing, including those that are unknown, have+a zero entry in the lookup table. When called from pcre2_substitute(), only \c,+\o, and \x are recognized (\u and \U can never appear as they are used for case+forcing). */++else+ {+ int s;+ PCRE2_SPTR oldptr;+ BOOL overflow;++ /* Filter calls from pcre2_substitute(). */++ if (cb == NULL)+ {+ if (c != CHAR_c && c != CHAR_o && c != CHAR_x)+ {+ *errorcodeptr = ERR3;+ return 0;+ }+ alt_bsux = FALSE; /* Do not modify \x handling */+ }++ switch (c)+ {+ /* A number of Perl escapes are not handled by PCRE. We give an explicit+ error. */++ case CHAR_F:+ case CHAR_l:+ case CHAR_L:+ *errorcodeptr = ERR37;+ break;++ /* \u is unrecognized when neither PCRE2_ALT_BSUX nor PCRE2_EXTRA_ALT_BSUX+ is set. Otherwise, \u must be followed by exactly four hex digits or, if+ PCRE2_EXTRA_ALT_BSUX is set, by any number of hex digits in braces.+ Otherwise it is a lowercase u letter. This gives some compatibility with+ ECMAScript (aka JavaScript). Unlike other braced items, white space is NOT+ allowed. When \u{ is not followed by hex digits, a special return is given+ because otherwise \u{ 12} (for example) would be treated as u{12}. */++ case CHAR_u:+ if (!alt_bsux) *errorcodeptr = ERR37; else+ {+ uint32_t xc;++ if (ptr >= ptrend) break;+ if (*ptr == CHAR_LEFT_CURLY_BRACKET &&+ (xoptions & PCRE2_EXTRA_ALT_BSUX) != 0)+ {+ PCRE2_SPTR hptr = ptr + 1;++ cc = 0;+ while (hptr < ptrend && (xc = XDIGIT(*hptr)) != 0xff)+ {+ if ((cc & 0xf0000000) != 0) /* Test for 32-bit overflow */+ {+ *errorcodeptr = ERR77;+ ptr = hptr; /* Show where */+ break; /* *hptr != } will cause another break below */+ }+ cc = (cc << 4) | xc;+ hptr++;+ }++ if (hptr == ptr + 1 || /* No hex digits */+ hptr >= ptrend || /* Hit end of input */+ *hptr != CHAR_RIGHT_CURLY_BRACKET) /* No } terminator */+ {+ escape = ESC_ub; /* Special return */+ ptr++; /* Skip { */+ break; /* Hex escape not recognized */+ }++ c = cc; /* Accept the code point */+ ptr = hptr + 1;+ }++ else /* Must be exactly 4 hex digits */+ {+ if (ptrend - ptr < 4) break; /* Less than 4 chars */+ if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */+ if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */+ cc = (cc << 4) | xc;+ if ((xc = XDIGIT(ptr[2])) == 0xff) break; /* Not a hex digit */+ cc = (cc << 4) | xc;+ if ((xc = XDIGIT(ptr[3])) == 0xff) break; /* Not a hex digit */+ c = (cc << 4) | xc;+ ptr += 4;+ }++ if (utf)+ {+ if (c > 0x10ffffU) *errorcodeptr = ERR77;+ else+ if (c >= 0xd800 && c <= 0xdfff &&+ (xoptions & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)+ *errorcodeptr = ERR73;+ }+ else if (c > MAX_NON_UTF_CHAR) *errorcodeptr = ERR77;+ }+ break;++ /* \U is unrecognized unless PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set,+ in which case it is an upper case letter. */++ case CHAR_U:+ if (!alt_bsux) *errorcodeptr = ERR37;+ break;++ /* In a character class, \g is just a literal "g". Outside a character+ class, \g must be followed by one of a number of specific things:++ (1) A number, either plain or braced. If positive, it is an absolute+ backreference. If negative, it is a relative backreference. This is a Perl+ 5.10 feature.++ (2) Perl 5.10 also supports \g{name} as a reference to a named group. This+ is part of Perl's movement towards a unified syntax for back references. As+ this is synonymous with \k{name}, we fudge it up by pretending it really+ was \k{name}.++ (3) For Oniguruma compatibility we also support \g followed by a name or a+ number either in angle brackets or in single quotes. However, these are+ (possibly recursive) subroutine calls, _not_ backreferences. We return+ the ESC_g code.++ Summary: Return a negative number for a numerical back reference, ESC_k for+ a named back reference, and ESC_g for a named or numbered subroutine call.+ */++ case CHAR_g:+ if (isclass) break;++ if (ptr >= ptrend)+ {+ *errorcodeptr = ERR57;+ break;+ }++ if (*ptr == CHAR_LESS_THAN_SIGN || *ptr == CHAR_APOSTROPHE)+ {+ escape = ESC_g;+ break;+ }++ /* If there is a brace delimiter, try to read a numerical reference. If+ there isn't one, assume we have a name and treat it as \k. */++ if (*ptr == CHAR_LEFT_CURLY_BRACKET)+ {+ PCRE2_SPTR p = ptr + 1;++ while (p < ptrend && (*p == CHAR_SPACE || *p == CHAR_HT)) p++;+ if (!read_number(&p, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s,+ errorcodeptr))+ {+ if (*errorcodeptr == 0) escape = ESC_k; /* No number found */+ break;+ }+ while (p < ptrend && (*p == CHAR_SPACE || *p == CHAR_HT)) p++;++ if (p >= ptrend || *p != CHAR_RIGHT_CURLY_BRACKET)+ {+ *errorcodeptr = ERR57;+ break;+ }+ ptr = p + 1;+ }++ /* Read an undelimited number */++ else+ {+ if (!read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s,+ errorcodeptr))+ {+ if (*errorcodeptr == 0) *errorcodeptr = ERR57; /* No number found */+ break;+ }+ }++ if (s <= 0)+ {+ *errorcodeptr = ERR15;+ break;+ }++ escape = -s;+ break;++ /* The handling of escape sequences consisting of a string of digits+ starting with one that is not zero is not straightforward. Perl has changed+ over the years. Nowadays \g{} for backreferences and \o{} for octal are+ recommended to avoid the ambiguities in the old syntax.++ Outside a character class, the digits are read as a decimal number. If the+ number is less than 10, or if there are that many previous extracting left+ brackets, it is a back reference. Otherwise, up to three octal digits are+ read to form an escaped character code. Thus \123 is likely to be octal 123+ (cf \0123, which is octal 012 followed by the literal 3).++ Inside a character class, \ followed by a digit is always either a literal+ 8 or 9 or an octal number. */++ case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5:+ case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:++ if (!isclass)+ {+ oldptr = ptr;+ ptr--; /* Back to the digit */++ /* As we know we are at a digit, the only possible error from+ read_number() is a number that is too large to be a group number. In this+ case we fall through handle this as not a group reference. If we have+ read a small enough number, check for a back reference.++ \1 to \9 are always back references. \8x and \9x are too; \1x to \7x+ are octal escapes if there are not that many previous captures. */++ if (read_number(&ptr, ptrend, -1, INT_MAX/10 - 1, 0, &s, errorcodeptr) &&+ (s < 10 || oldptr[-1] >= CHAR_8 || s <= (int)cb->bracount))+ {+ if (s > (int)MAX_GROUP_NUMBER) *errorcodeptr = ERR61;+ else escape = -s; /* Indicates a back reference */+ break;+ }++ ptr = oldptr; /* Put the pointer back and fall through */+ }++ /* Handle a digit following \ when the number is not a back reference, or+ we are within a character class. If the first digit is 8 or 9, Perl used to+ generate a binary zero and then treat the digit as a following literal. At+ least by Perl 5.18 this changed so as not to insert the binary zero. */++ if (c >= CHAR_8) break;++ /* Fall through */++ /* \0 always starts an octal number, but we may drop through to here with a+ larger first octal digit. The original code used just to take the least+ significant 8 bits of octal numbers (I think this is what early Perls used+ to do). Nowadays we allow for larger numbers in UTF-8 mode and 16-bit mode,+ but no more than 3 octal digits. */++ case CHAR_0:+ c -= CHAR_0;+ while(i++ < 2 && ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7)+ c = c * 8 + *ptr++ - CHAR_0;+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (!utf && c > 0xff) *errorcodeptr = ERR51;+#endif+ break;++ /* \o is a relatively new Perl feature, supporting a more general way of+ specifying character codes in octal. The only supported form is \o{ddd},+ with optional spaces or tabs after { and before }. */++ case CHAR_o:+ if (ptr >= ptrend || *ptr++ != CHAR_LEFT_CURLY_BRACKET)+ {+ ptr--;+ *errorcodeptr = ERR55;+ break;+ }++ while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;+ if (ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)+ {+ *errorcodeptr = ERR78;+ break;+ }++ c = 0;+ overflow = FALSE;+ while (ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7)+ {+ cc = *ptr++;+ if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c >= 0x20000000l) { overflow = TRUE; break; }+#endif+ c = (c << 3) + (cc - CHAR_0);+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; }+#elif PCRE2_CODE_UNIT_WIDTH == 16+ if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; }+#elif PCRE2_CODE_UNIT_WIDTH == 32+ if (utf && c > 0x10ffffU) { overflow = TRUE; break; }+#endif+ }++ while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;++ if (overflow)+ {+ while (ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++;+ *errorcodeptr = ERR34;+ }+ else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)+ {+ if (utf && c >= 0xd800 && c <= 0xdfff &&+ (xoptions & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)+ {+ ptr--;+ *errorcodeptr = ERR73;+ }+ }+ else+ {+ ptr--;+ *errorcodeptr = ERR64;+ }+ break;++ /* When PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set, \x must be followed+ by two hexadecimal digits. Otherwise it is a lowercase x letter. */++ case CHAR_x:+ if (alt_bsux)+ {+ uint32_t xc;+ if (ptrend - ptr < 2) break; /* Less than 2 characters */+ if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */+ if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */+ c = (cc << 4) | xc;+ ptr += 2;+ }++ /* Handle \x in Perl's style. \x{ddd} is a character code which can be+ greater than 0xff in UTF-8 or non-8bit mode, but only if the ddd are hex+ digits. If not, { used to be treated as a data character. However, Perl+ seems to read hex digits up to the first non-such, and ignore the rest, so+ that, for example \x{zz} matches a binary zero. This seems crazy, so PCRE+ now gives an error. */++ else+ {+ if (ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET)+ {+ ptr++;+ while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;++#ifndef EBCDIC+ COME_FROM_NU:+#endif+ if (ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)+ {+ *errorcodeptr = ERR78;+ break;+ }+ c = 0;+ overflow = FALSE;++ while (ptr < ptrend && (cc = XDIGIT(*ptr)) != 0xff)+ {+ ptr++;+ if (c == 0 && cc == 0) continue; /* Leading zeroes */+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c >= 0x10000000l) { overflow = TRUE; break; }+#endif+ c = (c << 4) | cc;+ if ((utf && c > 0x10ffffU) || (!utf && c > MAX_NON_UTF_CHAR))+ {+ overflow = TRUE;+ break;+ }+ }++ /* Perl ignores spaces and tabs before } */++ while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;++ /* On overflow, skip remaining hex digits */++ if (overflow)+ {+ while (ptr < ptrend && XDIGIT(*ptr) != 0xff) ptr++;+ *errorcodeptr = ERR34;+ }+ else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)+ {+ if (utf && c >= 0xd800 && c <= 0xdfff &&+ (xoptions & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)+ {+ ptr--;+ *errorcodeptr = ERR73;+ }+ }++ /* If the sequence of hex digits (followed by optional space) does not+ end with '}', give an error. We used just to recognize this construct+ and fall through to the normal \x handling, but nowadays Perl gives an+ error, which seems much more sensible, so we do too. */++ else+ {+ ptr--;+ *errorcodeptr = ERR67;+ }+ } /* End of \x{} processing */++ /* Read a up to two hex digits after \x */++ else+ {+ c = 0;+ if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */+ ptr++;+ c = cc;+ if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */+ ptr++;+ c = (c << 4) | cc;+ } /* End of \xdd handling */+ } /* End of Perl-style \x handling */+ break;++ /* The handling of \c is different in ASCII and EBCDIC environments. In an+ ASCII (or Unicode) environment, an error is given if the character+ following \c is not a printable ASCII character. Otherwise, the following+ character is upper-cased if it is a letter, and after that the 0x40 bit is+ flipped. The result is the value of the escape.++ In an EBCDIC environment the handling of \c is compatible with the+ specification in the perlebcdic document. The following character must be+ a letter or one of small number of special characters. These provide a+ means of defining the character values 0-31.++ For testing the EBCDIC handling of \c in an ASCII environment, recognize+ the EBCDIC value of 'c' explicitly. */++#if defined EBCDIC && 'a' != 0x81+ case 0x83:+#else+ case CHAR_c:+#endif+ if (ptr >= ptrend)+ {+ *errorcodeptr = ERR2;+ break;+ }+ c = *ptr;+ if (c >= CHAR_a && c <= CHAR_z) c = UPPER_CASE(c);++ /* Handle \c in an ASCII/Unicode environment. */++#ifndef EBCDIC /* ASCII/UTF-8 coding */+ if (c < 32 || c > 126) /* Excludes all non-printable ASCII */+ {+ *errorcodeptr = ERR68;+ break;+ }+ c ^= 0x40;++ /* Handle \c in an EBCDIC environment. The special case \c? is converted to+ 255 (0xff) or 95 (0x5f) if other characters suggest we are using the+ POSIX-BC encoding. (This is the way Perl indicates that it handles \c?.)+ The other valid sequences correspond to a list of specific characters. */++#else+ if (c == CHAR_QUESTION_MARK)+ c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff;+ else+ {+ for (i = 0; i < 32; i++)+ {+ if (c == ebcdic_escape_c[i]) break;+ }+ if (i < 32) c = i; else *errorcodeptr = ERR68;+ }+#endif /* EBCDIC */++ ptr++;+ break;++ /* Any other alphanumeric following \ is an error. Perl gives an error only+ if in warning mode, but PCRE doesn't have a warning mode. */++ default:+ *errorcodeptr = ERR3;+ *ptrptr = ptr - 1; /* Point to the character at fault */+ return 0;+ }+ }++/* Set the pointer to the next character before returning. */++*ptrptr = ptr;+*chptr = c;+return escape;+}++++#ifdef SUPPORT_UNICODE+/*************************************************+* Handle \P and \p *+*************************************************/++/* This function is called after \P or \p has been encountered, provided that+PCRE2 is compiled with support for UTF and Unicode properties. On entry, the+contents of ptrptr are pointing after the P or p. On exit, it is left pointing+after the final code unit of the escape sequence.++Arguments:+ ptrptr the pattern position pointer+ negptr a boolean that is set TRUE for negation else FALSE+ ptypeptr an unsigned int that is set to the type value+ pdataptr an unsigned int that is set to the detailed property value+ errorcodeptr the error code variable+ cb the compile data++Returns: TRUE if the type value was found, or FALSE for an invalid type+*/++static BOOL+get_ucp(PCRE2_SPTR *ptrptr, BOOL *negptr, uint16_t *ptypeptr,+ uint16_t *pdataptr, int *errorcodeptr, compile_block *cb)+{+PCRE2_UCHAR c;+PCRE2_SIZE i, bot, top;+PCRE2_SPTR ptr = *ptrptr;+PCRE2_UCHAR name[50];+PCRE2_UCHAR *vptr = NULL;+uint16_t ptscript = PT_NOTSCRIPT;++if (ptr >= cb->end_pattern) goto ERROR_RETURN;+c = *ptr++;+*negptr = FALSE;++/* \P or \p can be followed by a name in {}, optionally preceded by ^ for+negation. */++if (c == CHAR_LEFT_CURLY_BRACKET)+ {+ if (ptr >= cb->end_pattern) goto ERROR_RETURN;++ if (*ptr == CHAR_CIRCUMFLEX_ACCENT)+ {+ *negptr = TRUE;+ ptr++;+ }++ for (i = 0; i < (int)(sizeof(name) / sizeof(PCRE2_UCHAR)) - 1; i++)+ {+ if (ptr >= cb->end_pattern) goto ERROR_RETURN;+ c = *ptr++;+#if PCRE2_CODE_UNIT_WIDTH != 8+ while (c == '_' || c == '-' || (c <= 0xff && isspace(c)))+#else+ while (c == '_' || c == '-' || isspace(c))+#endif+ {+ if (ptr >= cb->end_pattern) goto ERROR_RETURN;+ c = *ptr++;+ }+ if (c == CHAR_NUL) goto ERROR_RETURN;+ if (c == CHAR_RIGHT_CURLY_BRACKET) break;+ name[i] = tolower(c);+ if ((c == ':' || c == '=') && vptr == NULL) vptr = name + i;+ }++ if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN;+ name[i] = 0;+ }++/* If { doesn't follow \p or \P there is just one following character, which+must be an ASCII letter. */++else if (MAX_255(c) && (cb->ctypes[c] & ctype_letter) != 0)+ {+ name[0] = tolower(c);+ name[1] = 0;+ }+else goto ERROR_RETURN;++*ptrptr = ptr;++/* If the property contains ':' or '=' we have class name and value separately+specified. The following are supported:++ . Bidi_Class (synonym bc), for which the property names are "bidi<name>".+ . Script (synonym sc) for which the property name is the script name+ . Script_Extensions (synonym scx), ditto++As this is a small number, we currently just check the names directly. If this+grows, a sorted table and a switch will be neater.++For both the script properties, set a PT_xxx value so that (1) they can be+distinguished and (2) invalid script names that happen to be the name of+another property can be diagnosed. */++if (vptr != NULL)+ {+ int offset = 0;+ PCRE2_UCHAR sname[8];++ *vptr = 0; /* Terminate property name */+ if (PRIV(strcmp_c8)(name, STRING_bidiclass) == 0 ||+ PRIV(strcmp_c8)(name, STRING_bc) == 0)+ {+ offset = 4;+ sname[0] = CHAR_b;+ sname[1] = CHAR_i; /* There is no strcpy_c8 function */+ sname[2] = CHAR_d;+ sname[3] = CHAR_i;+ }++ else if (PRIV(strcmp_c8)(name, STRING_script) == 0 ||+ PRIV(strcmp_c8)(name, STRING_sc) == 0)+ ptscript = PT_SC;++ else if (PRIV(strcmp_c8)(name, STRING_scriptextensions) == 0 ||+ PRIV(strcmp_c8)(name, STRING_scx) == 0)+ ptscript = PT_SCX;++ else+ {+ *errorcodeptr = ERR47;+ return FALSE;+ }++ /* Adjust the string in name[] as needed */++ memmove(name + offset, vptr + 1, (name + i - vptr)*sizeof(PCRE2_UCHAR));+ if (offset != 0) memmove(name, sname, offset*sizeof(PCRE2_UCHAR));+ }++/* Search for a recognized property using binary chop. */++bot = 0;+top = PRIV(utt_size);++while (bot < top)+ {+ int r;+ i = (bot + top) >> 1;+ r = PRIV(strcmp_c8)(name, PRIV(utt_names) + PRIV(utt)[i].name_offset);++ /* When a matching property is found, some extra checking is needed when the+ \p{xx:yy} syntax is used and xx is either sc or scx. */++ if (r == 0)+ {+ *pdataptr = PRIV(utt)[i].value;+ if (vptr == NULL || ptscript == PT_NOTSCRIPT)+ {+ *ptypeptr = PRIV(utt)[i].type;+ return TRUE;+ }++ switch (PRIV(utt)[i].type)+ {+ case PT_SC:+ *ptypeptr = PT_SC;+ return TRUE;++ case PT_SCX:+ *ptypeptr = ptscript;+ return TRUE;+ }++ break; /* Non-script found */+ }++ if (r > 0) bot = i + 1; else top = i;+ }++*errorcodeptr = ERR47; /* Unrecognized property */+return FALSE;++ERROR_RETURN: /* Malformed \P or \p */+*errorcodeptr = ERR46;+*ptrptr = ptr;+return FALSE;+}+#endif++++/*************************************************+* Check for POSIX class syntax *+*************************************************/++/* This function is called when the sequence "[:" or "[." or "[=" is+encountered in a character class. It checks whether this is followed by a+sequence of characters terminated by a matching ":]" or ".]" or "=]". If we+reach an unescaped ']' without the special preceding character, return FALSE.++Originally, this function only recognized a sequence of letters between the+terminators, but it seems that Perl recognizes any sequence of characters,+though of course unknown POSIX names are subsequently rejected. Perl gives an+"Unknown POSIX class" error for [:f\oo:] for example, where previously PCRE+didn't consider this to be a POSIX class. Likewise for [:1234:].++The problem in trying to be exactly like Perl is in the handling of escapes. We+have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX+class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code+below handles the special cases \\ and \], but does not try to do any other+escape processing. This makes it different from Perl for cases such as+[:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does+not recognize "l\ower". This is a lesser evil than not diagnosing bad classes+when Perl does, I think.++A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not.+It seems that the appearance of a nested POSIX class supersedes an apparent+external class. For example, [:a[:digit:]b:] matches "a", "b", ":", or+a digit. This is handled by returning FALSE if the start of a new group with+the same terminator is encountered, since the next closing sequence must close+the nested group, not the outer one.++In Perl, unescaped square brackets may also appear as part of class names. For+example, [:a[:abc]b:] gives unknown POSIX class "[:abc]b:]". However, for+[:a[:abc]b][b:] it gives unknown POSIX class "[:abc]b][b:]", which does not+seem right at all. PCRE does not allow closing square brackets in POSIX class+names.++Arguments:+ ptr pointer to the character after the initial [ (colon, dot, equals)+ ptrend pointer to the end of the pattern+ endptr where to return a pointer to the terminating ':', '.', or '='++Returns: TRUE or FALSE+*/++static BOOL+check_posix_syntax(PCRE2_SPTR ptr, PCRE2_SPTR ptrend, PCRE2_SPTR *endptr)+{+PCRE2_UCHAR terminator; /* Don't combine these lines; the Solaris cc */+terminator = *ptr++; /* compiler warns about "non-constant" initializer. */++for (; ptrend - ptr >= 2; ptr++)+ {+ if (*ptr == CHAR_BACKSLASH &&+ (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET || ptr[1] == CHAR_BACKSLASH))+ ptr++;++ else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) ||+ *ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;++ else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)+ {+ *endptr = ptr;+ return TRUE;+ }+ }++return FALSE;+}++++/*************************************************+* Check POSIX class name *+*************************************************/++/* This function is called to check the name given in a POSIX-style class entry+such as [:alnum:].++Arguments:+ ptr points to the first letter+ len the length of the name++Returns: a value representing the name, or -1 if unknown+*/++static int+check_posix_name(PCRE2_SPTR ptr, int len)+{+const char *pn = posix_names;+int yield = 0;+while (posix_name_lengths[yield] != 0)+ {+ if (len == posix_name_lengths[yield] &&+ PRIV(strncmp_c8)(ptr, pn, (unsigned int)len) == 0) return yield;+ pn += posix_name_lengths[yield] + 1;+ yield++;+ }+return -1;+}++++/*************************************************+* Read a subpattern or VERB name *+*************************************************/++/* This function is called from parse_regex() below whenever it needs to read+the name of a subpattern or a (*VERB) or an (*alpha_assertion). The initial+pointer must be to the preceding character. If that character is '*' we are+reading a verb or alpha assertion name. The pointer is updated to point after+the name, for a VERB or alpha assertion name, or after tha name's terminator+for a subpattern name. Returning both the offset and the name pointer is+redundant information, but some callers use one and some the other, so it is+simplest just to return both. When the name is in braces, spaces and tabs are+allowed (and ignored) at either end.++Arguments:+ ptrptr points to the character pointer variable+ ptrend points to the end of the input string+ utf true if the input is UTF-encoded+ terminator the terminator of a subpattern name must be this+ offsetptr where to put the offset from the start of the pattern+ nameptr where to put a pointer to the name in the input+ namelenptr where to put the length of the name+ errcodeptr where to put an error code+ cb pointer to the compile data block++Returns: TRUE if a name was read+ FALSE otherwise, with error code set+*/++static BOOL+read_name(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, BOOL utf, uint32_t terminator,+ PCRE2_SIZE *offsetptr, PCRE2_SPTR *nameptr, uint32_t *namelenptr,+ int *errorcodeptr, compile_block *cb)+{+PCRE2_SPTR ptr = *ptrptr;+BOOL is_group = (*ptr++ != CHAR_ASTERISK);+BOOL is_braced = terminator == CHAR_RIGHT_CURLY_BRACKET;++if (is_braced)+ while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;++if (ptr >= ptrend) /* No characters in name */+ {+ *errorcodeptr = is_group? ERR62: /* Subpattern name expected */+ ERR60; /* Verb not recognized or malformed */+ goto FAILED;+ }++*nameptr = ptr;+*offsetptr = (PCRE2_SIZE)(ptr - cb->start_pattern);++/* In UTF mode, a group name may contain letters and decimal digits as defined+by Unicode properties, and underscores, but must not start with a digit. */++#ifdef SUPPORT_UNICODE+if (utf && is_group)+ {+ uint32_t c, type;++ GETCHAR(c, ptr);+ type = UCD_CHARTYPE(c);++ if (type == ucp_Nd)+ {+ *errorcodeptr = ERR44;+ goto FAILED;+ }++ for(;;)+ {+ if (type != ucp_Nd && PRIV(ucp_gentype)[type] != ucp_L &&+ c != CHAR_UNDERSCORE) break;+ ptr++;+ FORWARDCHARTEST(ptr, ptrend);+ if (ptr >= ptrend) break;+ GETCHAR(c, ptr);+ type = UCD_CHARTYPE(c);+ }+ }+else+#else+(void)utf; /* Avoid compiler warning */+#endif /* SUPPORT_UNICODE */++/* Handle non-group names and group names in non-UTF modes. A group name must+not start with a digit. If either of the others start with a digit it just+won't be recognized. */++ {+ if (is_group && IS_DIGIT(*ptr))+ {+ *errorcodeptr = ERR44;+ goto FAILED;+ }++ while (ptr < ptrend && MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype_word) != 0)+ {+ ptr++;+ }+ }++/* Check name length */++if (ptr > *nameptr + MAX_NAME_SIZE)+ {+ *errorcodeptr = ERR48;+ goto FAILED;+ }+*namelenptr = (uint32_t)(ptr - *nameptr);++/* Subpattern names must not be empty, and their terminator is checked here.+(What follows a verb or alpha assertion name is checked separately.) */++if (is_group)+ {+ if (ptr == *nameptr)+ {+ *errorcodeptr = ERR62; /* Subpattern name expected */+ goto FAILED;+ }+ if (is_braced)+ while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;+ if (ptr >= ptrend || *ptr != (PCRE2_UCHAR)terminator)+ {+ *errorcodeptr = ERR42;+ goto FAILED;+ }+ ptr++;+ }++*ptrptr = ptr;+return TRUE;++FAILED:+*ptrptr = ptr;+return FALSE;+}++++/*************************************************+* Manage callouts at start of cycle *+*************************************************/++/* At the start of a new item in parse_regex() we are able to record the+details of the previous item in a prior callout, and also to set up an+automatic callout if enabled. Avoid having two adjacent automatic callouts,+which would otherwise happen for items such as \Q that contribute nothing to+the parsed pattern.++Arguments:+ ptr current pattern pointer+ pcalloutptr points to a pointer to previous callout, or NULL+ auto_callout TRUE if auto_callouts are enabled+ parsed_pattern the parsed pattern pointer+ cb compile block++Returns: possibly updated parsed_pattern pointer.+*/++static uint32_t *+manage_callouts(PCRE2_SPTR ptr, uint32_t **pcalloutptr, BOOL auto_callout,+ uint32_t *parsed_pattern, compile_block *cb)+{+uint32_t *previous_callout = *pcalloutptr;++if (previous_callout != NULL) previous_callout[2] = (uint32_t)(ptr -+ cb->start_pattern - (PCRE2_SIZE)previous_callout[1]);++if (!auto_callout) previous_callout = NULL; else+ {+ if (previous_callout == NULL ||+ previous_callout != parsed_pattern - 4 ||+ previous_callout[3] != 255)+ {+ previous_callout = parsed_pattern; /* Set up new automatic callout */+ parsed_pattern += 4;+ previous_callout[0] = META_CALLOUT_NUMBER;+ previous_callout[2] = 0;+ previous_callout[3] = 255;+ }+ previous_callout[1] = (uint32_t)(ptr - cb->start_pattern);+ }++*pcalloutptr = previous_callout;+return parsed_pattern;+}++++/*************************************************+* Handle \d, \D, \s, \S, \w, \W *+*************************************************/++/* This function is called from parse_regex() below, both for freestanding+escapes, and those within classes, to handle those escapes that may change when+Unicode property support is requested. Note that PCRE2_UCP will never be set+without Unicode support because that is checked when pcre2_compile() is called.++Arguments:+ escape the ESC_... value+ parsed_pattern where to add the code+ options options bits+ xoptions extra options bits++Returns: updated value of parsed_pattern+*/+static uint32_t *+handle_escdsw(int escape, uint32_t *parsed_pattern, uint32_t options,+ uint32_t xoptions)+{+uint32_t ascii_option = 0;+uint32_t prop = ESC_p;++switch(escape)+ {+ case ESC_D:+ prop = ESC_P;+ /* Fall through */+ case ESC_d:+ ascii_option = PCRE2_EXTRA_ASCII_BSD;+ break;++ case ESC_S:+ prop = ESC_P;+ /* Fall through */+ case ESC_s:+ ascii_option = PCRE2_EXTRA_ASCII_BSS;+ break;++ case ESC_W:+ prop = ESC_P;+ /* Fall through */+ case ESC_w:+ ascii_option = PCRE2_EXTRA_ASCII_BSW;+ break;+ }++if ((options & PCRE2_UCP) == 0 || (xoptions & ascii_option) != 0)+ {+ *parsed_pattern++ = META_ESCAPE + escape;+ }+else+ {+ *parsed_pattern++ = META_ESCAPE + prop;+ switch(escape)+ {+ case ESC_d:+ case ESC_D:+ *parsed_pattern++ = (PT_PC << 16) | ucp_Nd;+ break;++ case ESC_s:+ case ESC_S:+ *parsed_pattern++ = PT_SPACE << 16;+ break;++ case ESC_w:+ case ESC_W:+ *parsed_pattern++ = PT_WORD << 16;+ break;+ }+ }++return parsed_pattern;+}++++/*************************************************+* Parse regex and identify named groups *+*************************************************/++/* This function is called first of all. It scans the pattern and does two+things: (1) It identifies capturing groups and makes a table of named capturing+groups so that information about them is fully available to both the compiling+scans. (2) It writes a parsed version of the pattern with comments omitted and+escapes processed into the parsed_pattern vector.++Arguments:+ ptr points to the start of the pattern+ options compiling dynamic options (may change during the scan)+ has_lookbehind points to a boolean, set TRUE if a lookbehind is found+ cb pointer to the compile data block++Returns: zero on success or a non-zero error code, with the+ error offset placed in the cb field+*/++/* A structure and some flags for dealing with nested groups. */++typedef struct nest_save {+ uint16_t nest_depth;+ uint16_t reset_group;+ uint16_t max_group;+ uint16_t flags;+ uint32_t options;+ uint32_t xoptions;+} nest_save;++#define NSF_RESET 0x0001u+#define NSF_CONDASSERT 0x0002u+#define NSF_ATOMICSR 0x0004u++/* Options that are changeable within the pattern must be tracked during+parsing. Some (e.g. PCRE2_EXTENDED) are implemented entirely during parsing,+but all must be tracked so that META_OPTIONS items set the correct values for+the main compiling phase. */++#define PARSE_TRACKED_OPTIONS (PCRE2_CASELESS|PCRE2_DOTALL|PCRE2_DUPNAMES| \+ PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_MULTILINE|PCRE2_NO_AUTO_CAPTURE| \+ PCRE2_UNGREEDY)++#define PARSE_TRACKED_EXTRA_OPTIONS (PCRE2_EXTRA_CASELESS_RESTRICT| \+ PCRE2_EXTRA_ASCII_BSD|PCRE2_EXTRA_ASCII_BSS|PCRE2_EXTRA_ASCII_BSW| \+ PCRE2_EXTRA_ASCII_DIGIT|PCRE2_EXTRA_ASCII_POSIX)++/* States used for analyzing ranges in character classes. The two OK values+must be last. */++enum { RANGE_NO, RANGE_STARTED, RANGE_OK_ESCAPED, RANGE_OK_LITERAL };++/* Only in 32-bit mode can there be literals > META_END. A macro encapsulates+the storing of literal values in the main parsed pattern, where they can always+be quantified. */++#if PCRE2_CODE_UNIT_WIDTH == 32+#define PARSED_LITERAL(c, p) \+ { \+ if (c >= META_END) *p++ = META_BIGVALUE; \+ *p++ = c; \+ okquantifier = TRUE; \+ }+#else+#define PARSED_LITERAL(c, p) *p++ = c; okquantifier = TRUE;+#endif++/* Here's the actual function. */++static int parse_regex(PCRE2_SPTR ptr, uint32_t options, BOOL *has_lookbehind,+ compile_block *cb)+{+uint32_t c;+uint32_t delimiter;+uint32_t namelen;+uint32_t class_range_state;+uint32_t *verblengthptr = NULL; /* Value avoids compiler warning */+uint32_t *verbstartptr = NULL;+uint32_t *previous_callout = NULL;+uint32_t *parsed_pattern = cb->parsed_pattern;+uint32_t *parsed_pattern_end = cb->parsed_pattern_end;+uint32_t *this_parsed_item = NULL;+uint32_t *prev_parsed_item = NULL;+uint32_t meta_quantifier = 0;+uint32_t add_after_mark = 0;+uint32_t xoptions = cb->cx->extra_options;+uint16_t nest_depth = 0;+int after_manual_callout = 0;+int expect_cond_assert = 0;+int errorcode = 0;+int escape;+int i;+BOOL inescq = FALSE;+BOOL inverbname = FALSE;+BOOL utf = (options & PCRE2_UTF) != 0;+BOOL auto_callout = (options & PCRE2_AUTO_CALLOUT) != 0;+BOOL isdupname;+BOOL negate_class;+BOOL okquantifier = FALSE;+PCRE2_SPTR thisptr;+PCRE2_SPTR name;+PCRE2_SPTR ptrend = cb->end_pattern;+PCRE2_SPTR verbnamestart = NULL; /* Value avoids compiler warning */+named_group *ng;+nest_save *top_nest, *end_nests;++/* Insert leading items for word and line matching (features provided for the+benefit of pcre2grep). */++if ((xoptions & PCRE2_EXTRA_MATCH_LINE) != 0)+ {+ *parsed_pattern++ = META_CIRCUMFLEX;+ *parsed_pattern++ = META_NOCAPTURE;+ }+else if ((xoptions & PCRE2_EXTRA_MATCH_WORD) != 0)+ {+ *parsed_pattern++ = META_ESCAPE + ESC_b;+ *parsed_pattern++ = META_NOCAPTURE;+ }++/* If the pattern is actually a literal string, process it separately to avoid+cluttering up the main loop. */++if ((options & PCRE2_LITERAL) != 0)+ {+ while (ptr < ptrend)+ {+ if (parsed_pattern >= parsed_pattern_end)+ {+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */+ goto FAILED;+ }+ thisptr = ptr;+ GETCHARINCTEST(c, ptr);+ if (auto_callout)+ parsed_pattern = manage_callouts(thisptr, &previous_callout,+ auto_callout, parsed_pattern, cb);+ PARSED_LITERAL(c, parsed_pattern);+ }+ goto PARSED_END;+ }++/* Process a real regex which may contain meta-characters. */++top_nest = NULL;+end_nests = (nest_save *)(cb->start_workspace + cb->workspace_size);++/* The size of the nest_save structure might not be a factor of the size of the+workspace. Therefore we must round down end_nests so as to correctly avoid+creating a nest_save that spans the end of the workspace. */++end_nests = (nest_save *)((char *)end_nests -+ ((cb->workspace_size * sizeof(PCRE2_UCHAR)) % sizeof(nest_save)));++/* PCRE2_EXTENDED_MORE implies PCRE2_EXTENDED */++if ((options & PCRE2_EXTENDED_MORE) != 0) options |= PCRE2_EXTENDED;++/* Now scan the pattern */++while (ptr < ptrend)+ {+ int prev_expect_cond_assert;+ uint32_t min_repeat = 0, max_repeat = 0;+ uint32_t set, unset, *optset;+ uint32_t xset, xunset, *xoptset;+ uint32_t terminator;+ uint32_t prev_meta_quantifier;+ BOOL prev_okquantifier;+ PCRE2_SPTR tempptr;+ PCRE2_SIZE offset;++ if (parsed_pattern >= parsed_pattern_end)+ {+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */+ goto FAILED;+ }++ if (nest_depth > cb->cx->parens_nest_limit)+ {+ errorcode = ERR19;+ goto FAILED; /* Parentheses too deeply nested */+ }++ /* If the last time round this loop something was added, parsed_pattern will+ no longer be equal to this_parsed_item. Remember where the previous item+ started and reset for the next item. Note that sometimes round the loop,+ nothing gets added (e.g. for ignored white space). */++ if (this_parsed_item != parsed_pattern)+ {+ prev_parsed_item = this_parsed_item;+ this_parsed_item = parsed_pattern;+ }++ /* Get next input character, save its position for callout handling. */++ thisptr = ptr;+ GETCHARINCTEST(c, ptr);++ /* Copy quoted literals until \E, allowing for the possibility of automatic+ callouts, except when processing a (*VERB) "name". */++ if (inescq)+ {+ if (c == CHAR_BACKSLASH && ptr < ptrend && *ptr == CHAR_E)+ {+ inescq = FALSE;+ ptr++; /* Skip E */+ }+ else+ {+ if (expect_cond_assert > 0) /* A literal is not allowed if we are */+ { /* expecting a conditional assertion, */+ ptr--; /* but an empty \Q\E sequence is OK. */+ errorcode = ERR28;+ goto FAILED;+ }+ if (inverbname)+ { /* Don't use PARSED_LITERAL() because it */+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;+#endif+ *parsed_pattern++ = c;+ }+ else+ {+ if (after_manual_callout-- <= 0)+ parsed_pattern = manage_callouts(thisptr, &previous_callout,+ auto_callout, parsed_pattern, cb);+ PARSED_LITERAL(c, parsed_pattern);+ }+ meta_quantifier = 0;+ }+ continue; /* Next character */+ }++ /* If we are processing the "name" part of a (*VERB:NAME) item, all+ characters up to the closing parenthesis are literals except when+ PCRE2_ALT_VERBNAMES is set. That causes backslash interpretation, but only \Q+ and \E and escaped characters are allowed (no character types such as \d). If+ PCRE2_EXTENDED is also set, we must ignore white space and # comments. Do+ this by not entering the special (*VERB:NAME) processing - they are then+ picked up below. Note that c is a character, not a code unit, so we must not+ use MAX_255 to test its size because MAX_255 tests code units and is assumed+ TRUE in 8-bit mode. */++ if (inverbname &&+ (+ /* EITHER: not both options set */+ ((options & (PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) !=+ (PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) ||+#ifdef SUPPORT_UNICODE+ /* OR: character > 255 AND not Unicode Pattern White Space */+ (c > 255 && (c|1) != 0x200f && (c|1) != 0x2029) ||+#endif+ /* OR: not a # comment or isspace() white space */+ (c < 256 && c != CHAR_NUMBER_SIGN && (cb->ctypes[c] & ctype_space) == 0+#ifdef SUPPORT_UNICODE+ /* and not CHAR_NEL when Unicode is supported */+ && c != CHAR_NEL+#endif+ )))+ {+ PCRE2_SIZE verbnamelength;++ switch(c)+ {+ default: /* Don't use PARSED_LITERAL() because it */+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;+#endif+ *parsed_pattern++ = c;+ break;++ case CHAR_RIGHT_PARENTHESIS:+ inverbname = FALSE;+ /* This is the length in characters */+ verbnamelength = (PCRE2_SIZE)(parsed_pattern - verblengthptr - 1);+ /* But the limit on the length is in code units */+ if (ptr - verbnamestart - 1 > (int)MAX_MARK)+ {+ ptr--;+ errorcode = ERR76;+ goto FAILED;+ }+ *verblengthptr = (uint32_t)verbnamelength;++ /* If this name was on a verb such as (*ACCEPT) which does not continue,+ a (*MARK) was generated for the name. We now add the original verb as the+ next item. */++ if (add_after_mark != 0)+ {+ *parsed_pattern++ = add_after_mark;+ add_after_mark = 0;+ }+ break;++ case CHAR_BACKSLASH:+ if ((options & PCRE2_ALT_VERBNAMES) != 0)+ {+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,+ xoptions, FALSE, cb);+ if (errorcode != 0) goto FAILED;+ }+ else escape = 0; /* Treat all as literal */++ switch(escape)+ {+ case 0: /* Don't use PARSED_LITERAL() because it */+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;+#endif+ *parsed_pattern++ = c;+ break;++ case ESC_ub:+ *parsed_pattern++ = CHAR_u;+ PARSED_LITERAL(CHAR_LEFT_CURLY_BRACKET, parsed_pattern);+ break;++ case ESC_Q:+ inescq = TRUE;+ break;++ case ESC_E: /* Ignore */+ break;++ default:+ errorcode = ERR40; /* Invalid in verb name */+ goto FAILED;+ }+ }+ continue; /* Next character in pattern */+ }++ /* Not a verb name character. At this point we must process everything that+ must not change the quantification state. This is mainly comments, but we+ handle \Q and \E here as well, so that an item such as A\Q\E+ is treated as+ A+, as in Perl. An isolated \E is ignored. */++ if (c == CHAR_BACKSLASH && ptr < ptrend)+ {+ if (*ptr == CHAR_Q || *ptr == CHAR_E)+ {+ inescq = *ptr == CHAR_Q;+ ptr++;+ continue;+ }+ }++ /* Skip over whitespace and # comments in extended mode. Note that c is a+ character, not a code unit, so we must not use MAX_255 to test its size+ because MAX_255 tests code units and is assumed TRUE in 8-bit mode. The+ whitespace characters are those designated as "Pattern White Space" by+ Unicode, which are the isspace() characters plus CHAR_NEL (newline), which is+ U+0085 in Unicode, plus U+200E, U+200F, U+2028, and U+2029. These are a+ subset of space characters that match \h and \v. */++ if ((options & PCRE2_EXTENDED) != 0)+ {+ if (c < 256 && (cb->ctypes[c] & ctype_space) != 0) continue;+#ifdef SUPPORT_UNICODE+ if (c == CHAR_NEL || (c|1) == 0x200f || (c|1) == 0x2029) continue;+#endif+ if (c == CHAR_NUMBER_SIGN)+ {+ while (ptr < ptrend)+ {+ if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */+ { /* IS_NEWLINE sets cb->nllen. */+ ptr += cb->nllen;+ break;+ }+ ptr++;+#ifdef SUPPORT_UNICODE+ if (utf) FORWARDCHARTEST(ptr, ptrend);+#endif+ }+ continue; /* Next character in pattern */+ }+ }++ /* Skip over bracketed comments */++ if (c == CHAR_LEFT_PARENTHESIS && ptrend - ptr >= 2 &&+ ptr[0] == CHAR_QUESTION_MARK && ptr[1] == CHAR_NUMBER_SIGN)+ {+ while (++ptr < ptrend && *ptr != CHAR_RIGHT_PARENTHESIS);+ if (ptr >= ptrend)+ {+ errorcode = ERR18; /* A special error for missing ) in a comment */+ goto FAILED; /* to make it easier to debug. */+ }+ ptr++;+ continue; /* Next character in pattern */+ }++ /* If the next item is not a quantifier, fill in length of any previous+ callout and create an auto callout if required. */++ if (c != CHAR_ASTERISK && c != CHAR_PLUS && c != CHAR_QUESTION_MARK &&+ (c != CHAR_LEFT_CURLY_BRACKET ||+ (tempptr = ptr,+ !read_repeat_counts(&tempptr, ptrend, NULL, NULL, &errorcode))))+ {+ if (after_manual_callout-- <= 0)+ {+ parsed_pattern = manage_callouts(thisptr, &previous_callout, auto_callout,+ parsed_pattern, cb);+ this_parsed_item = parsed_pattern; /* New start for current item */+ }+ }++ /* If expect_cond_assert is 2, we have just passed (?( and are expecting an+ assertion, possibly preceded by a callout. If the value is 1, we have just+ had the callout and expect an assertion. There must be at least 3 more+ characters in all cases. When expect_cond_assert is 2, we know that the+ current character is an opening parenthesis, as otherwise we wouldn't be+ here. However, when it is 1, we need to check, and it's easiest just to check+ always. Note that expect_cond_assert may be negative, since all callouts just+ decrement it. */++ if (expect_cond_assert > 0)+ {+ BOOL ok = c == CHAR_LEFT_PARENTHESIS && ptrend - ptr >= 3 &&+ (ptr[0] == CHAR_QUESTION_MARK || ptr[0] == CHAR_ASTERISK);+ if (ok)+ {+ if (ptr[0] == CHAR_ASTERISK) /* New alpha assertion format, possibly */+ {+ ok = MAX_255(ptr[1]) && (cb->ctypes[ptr[1]] & ctype_lcletter) != 0;+ }+ else switch(ptr[1]) /* Traditional symbolic format */+ {+ case CHAR_C:+ ok = expect_cond_assert == 2;+ break;++ case CHAR_EQUALS_SIGN:+ case CHAR_EXCLAMATION_MARK:+ break;++ case CHAR_LESS_THAN_SIGN:+ ok = ptr[2] == CHAR_EQUALS_SIGN || ptr[2] == CHAR_EXCLAMATION_MARK;+ break;++ default:+ ok = FALSE;+ }+ }++ if (!ok)+ {+ ptr--; /* Adjust error offset */+ errorcode = ERR28;+ goto FAILED;+ }+ }++ /* Remember whether we are expecting a conditional assertion, and set the+ default for this item. */++ prev_expect_cond_assert = expect_cond_assert;+ expect_cond_assert = 0;++ /* Remember quantification status for the previous significant item, then set+ default for this item. */++ prev_okquantifier = okquantifier;+ prev_meta_quantifier = meta_quantifier;+ okquantifier = FALSE;+ meta_quantifier = 0;++ /* If the previous significant item was a quantifier, adjust the parsed code+ if there is a following modifier. The base meta value is always followed by+ the PLUS and QUERY values, in that order. We do this here rather than after+ reading a quantifier so that intervening comments and /x whitespace can be+ ignored without having to replicate code. */++ if (prev_meta_quantifier != 0 && (c == CHAR_QUESTION_MARK || c == CHAR_PLUS))+ {+ parsed_pattern[(prev_meta_quantifier == META_MINMAX)? -3 : -1] =+ prev_meta_quantifier + ((c == CHAR_QUESTION_MARK)?+ 0x00020000u : 0x00010000u);+ continue; /* Next character in pattern */+ }++ /* Process the next item in the main part of a pattern. */++ switch(c)+ {+ default: /* Non-special character */+ PARSED_LITERAL(c, parsed_pattern);+ break;+++ /* ---- Escape sequence ---- */++ case CHAR_BACKSLASH:+ tempptr = ptr;+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,+ xoptions, FALSE, cb);+ if (errorcode != 0)+ {+ ESCAPE_FAILED:+ if ((xoptions & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)+ goto FAILED;+ ptr = tempptr;+ if (ptr >= ptrend) c = CHAR_BACKSLASH; else+ {+ GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */+ }+ escape = 0; /* Treat as literal character */+ }++ /* The escape was a data escape or literal character. */++ if (escape == 0)+ {+ PARSED_LITERAL(c, parsed_pattern);+ }++ /* The escape was a back (or forward) reference. We keep the offset in+ order to give a more useful diagnostic for a bad forward reference. For+ references to groups numbered less than 10 we can't use more than two items+ in parsed_pattern because they may be just two characters in the input (and+ in a 64-bit world an offset may need two elements). So for them, the offset+ of the first occurrent is held in a special vector. */++ else if (escape < 0)+ {+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 1);+ escape = -escape;+ *parsed_pattern++ = META_BACKREF | (uint32_t)escape;+ if (escape < 10)+ {+ if (cb->small_ref_offset[escape] == PCRE2_UNSET)+ cb->small_ref_offset[escape] = offset;+ }+ else+ {+ PUTOFFSET(offset, parsed_pattern);+ }+ okquantifier = TRUE;+ }++ /* The escape was a character class such as \d etc. or other special+ escape indicator such as \A or \X. Most of them generate just a single+ parsed item, but \P and \p are followed by a 16-bit type and a 16-bit+ value. They are supported only when Unicode is available. The type and+ value are packed into a single 32-bit value so that the whole sequences+ uses only two elements in the parsed_vector. This is because the same+ coding is used if \d (for example) is turned into \p{Nd} when PCRE2_UCP is+ set.++ There are also some cases where the escape sequence is followed by a name:+ \k{name}, \k<name>, and \k'name' are backreferences by name, and \g<name>+ and \g'name' are subroutine calls by name; \g{name} is a synonym for+ \k{name}. Note that \g<number> and \g'number' are handled by check_escape()+ and returned as a negative value (handled above). A name is coded as an+ offset into the pattern and a length. */++ else switch (escape)+ {+ case ESC_C:+#ifdef NEVER_BACKSLASH_C+ errorcode = ERR85;+ goto ESCAPE_FAILED;+#else+ if ((options & PCRE2_NEVER_BACKSLASH_C) != 0)+ {+ errorcode = ERR83;+ goto ESCAPE_FAILED;+ }+#endif+ okquantifier = TRUE;+ *parsed_pattern++ = META_ESCAPE + escape;+ break;++ /* This is a special return that happens only in EXTRA_ALT_BSUX mode,+ when \u{ is not followed by hex digits and }. It requests two literal+ characters, u and { and we need this, as otherwise \u{ 12} (for example)+ would be treated as u{12} now that spaces are allowed in quantifiers. */++ case ESC_ub:+ *parsed_pattern++ = CHAR_u;+ PARSED_LITERAL(CHAR_LEFT_CURLY_BRACKET, parsed_pattern);+ break;++ case ESC_X:+#ifndef SUPPORT_UNICODE+ errorcode = ERR45; /* Supported only with Unicode support */+ goto ESCAPE_FAILED;+#endif+ case ESC_H:+ case ESC_h:+ case ESC_N:+ case ESC_R:+ case ESC_V:+ case ESC_v:+ okquantifier = TRUE;+ *parsed_pattern++ = META_ESCAPE + escape;+ break;++ default: /* \A, \B, \b, \G, \K, \Z, \z cannot be quantified. */+ *parsed_pattern++ = META_ESCAPE + escape;+ break;++ /* Escapes that may change in UCP mode. */++ case ESC_d:+ case ESC_D:+ case ESC_s:+ case ESC_S:+ case ESC_w:+ case ESC_W:+ okquantifier = TRUE;+ parsed_pattern = handle_escdsw(escape, parsed_pattern, options,+ xoptions);+ break;++ /* Unicode property matching */++ case ESC_P:+ case ESC_p:+#ifdef SUPPORT_UNICODE+ {+ BOOL negated;+ uint16_t ptype = 0, pdata = 0;+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))+ goto ESCAPE_FAILED;+ if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P;+ *parsed_pattern++ = META_ESCAPE + escape;+ *parsed_pattern++ = (ptype << 16) | pdata;+ okquantifier = TRUE;+ }+#else+ errorcode = ERR45;+ goto ESCAPE_FAILED;+#endif+ break; /* End \P and \p */++ /* When \g is used with quotes or angle brackets as delimiters, it is a+ numerical or named subroutine call, and control comes here. When used+ with brace delimiters it is a numberical back reference and does not come+ here because check_escape() returns it directly as a reference. \k is+ always a named back reference. */++ case ESC_g:+ case ESC_k:+ if (ptr >= ptrend || (*ptr != CHAR_LEFT_CURLY_BRACKET &&+ *ptr != CHAR_LESS_THAN_SIGN && *ptr != CHAR_APOSTROPHE))+ {+ errorcode = (escape == ESC_g)? ERR57 : ERR69;+ goto ESCAPE_FAILED;+ }+ terminator = (*ptr == CHAR_LESS_THAN_SIGN)?+ CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)?+ CHAR_APOSTROPHE : CHAR_RIGHT_CURLY_BRACKET;++ /* For a non-braced \g, check for a numerical recursion. */++ if (escape == ESC_g && terminator != CHAR_RIGHT_CURLY_BRACKET)+ {+ PCRE2_SPTR p = ptr + 1;++ if (read_number(&p, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &i,+ &errorcode))+ {+ if (p >= ptrend || *p != terminator)+ {+ errorcode = ERR57;+ goto ESCAPE_FAILED;+ }+ ptr = p;+ goto SET_RECURSION;+ }+ if (errorcode != 0) goto ESCAPE_FAILED;+ }++ /* Not a numerical recursion. Perl allows spaces and tabs after { and+ before } but not for other delimiters. */++ if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,+ &errorcode, cb)) goto ESCAPE_FAILED;++ /* \k and \g when used with braces are back references, whereas \g used+ with quotes or angle brackets is a recursion */++ *parsed_pattern++ =+ (escape == ESC_k || terminator == CHAR_RIGHT_CURLY_BRACKET)?+ META_BACKREF_BYNAME : META_RECURSE_BYNAME;+ *parsed_pattern++ = namelen;++ PUTOFFSET(offset, parsed_pattern);+ okquantifier = TRUE;+ break; /* End special escape processing */+ }+ break; /* End escape sequence processing */+++ /* ---- Single-character special items ---- */++ case CHAR_CIRCUMFLEX_ACCENT:+ *parsed_pattern++ = META_CIRCUMFLEX;+ break;++ case CHAR_DOLLAR_SIGN:+ *parsed_pattern++ = META_DOLLAR;+ break;++ case CHAR_DOT:+ *parsed_pattern++ = META_DOT;+ okquantifier = TRUE;+ break;+++ /* ---- Single-character quantifiers ---- */++ case CHAR_ASTERISK:+ meta_quantifier = META_ASTERISK;+ goto CHECK_QUANTIFIER;++ case CHAR_PLUS:+ meta_quantifier = META_PLUS;+ goto CHECK_QUANTIFIER;++ case CHAR_QUESTION_MARK:+ meta_quantifier = META_QUERY;+ goto CHECK_QUANTIFIER;+++ /* ---- Potential {n,m} quantifier ---- */++ case CHAR_LEFT_CURLY_BRACKET:+ if (!read_repeat_counts(&ptr, ptrend, &min_repeat, &max_repeat,+ &errorcode))+ {+ if (errorcode != 0) goto FAILED; /* Error in quantifier. */+ PARSED_LITERAL(c, parsed_pattern); /* Not a quantifier */+ break; /* No more quantifier processing */+ }+ meta_quantifier = META_MINMAX;+ /* Fall through */+++ /* ---- Quantifier post-processing ---- */++ /* Check that a quantifier is allowed after the previous item. This+ guarantees that there is a previous item. */++ CHECK_QUANTIFIER:+ if (!prev_okquantifier)+ {+ errorcode = ERR9;+ goto FAILED_BACK;+ }++ /* Most (*VERB)s are not allowed to be quantified, but an ungreedy+ quantifier can be useful for (*ACCEPT) - meaning "succeed on backtrack", a+ sort of negated (*COMMIT). We therefore allow (*ACCEPT) to be quantified by+ wrapping it in non-capturing brackets, but we have to allow for a preceding+ (*MARK) for when (*ACCEPT) has an argument. */++ if (*prev_parsed_item == META_ACCEPT)+ {+ uint32_t *p;+ for (p = parsed_pattern - 1; p >= verbstartptr; p--) p[1] = p[0];+ *verbstartptr = META_NOCAPTURE;+ parsed_pattern[1] = META_KET;+ parsed_pattern += 2;+ }++ /* Now we can put the quantifier into the parsed pattern vector. At this+ stage, we have only the basic quantifier. The check for a following + or ?+ modifier happens at the top of the loop, after any intervening comments+ have been removed. */++ *parsed_pattern++ = meta_quantifier;+ if (c == CHAR_LEFT_CURLY_BRACKET)+ {+ *parsed_pattern++ = min_repeat;+ *parsed_pattern++ = max_repeat;+ }+ break;+++ /* ---- Character class ---- */++ case CHAR_LEFT_SQUARE_BRACKET:+ okquantifier = TRUE;++ /* In another (POSIX) regex library, the ugly syntax [[:<:]] and [[:>:]] is+ used for "start of word" and "end of word". As these are otherwise illegal+ sequences, we don't break anything by recognizing them. They are replaced+ by \b(?=\w) and \b(?<=\w) respectively. Sequences like [a[:<:]] are+ erroneous and are handled by the normal code below. */++ if (ptrend - ptr >= 6 &&+ (PRIV(strncmp_c8)(ptr, STRING_WEIRD_STARTWORD, 6) == 0 ||+ PRIV(strncmp_c8)(ptr, STRING_WEIRD_ENDWORD, 6) == 0))+ {+ *parsed_pattern++ = META_ESCAPE + ESC_b;++ if (ptr[2] == CHAR_LESS_THAN_SIGN)+ {+ *parsed_pattern++ = META_LOOKAHEAD;+ }+ else+ {+ *parsed_pattern++ = META_LOOKBEHIND;+ *has_lookbehind = TRUE;++ /* The offset is used only for the "non-fixed length" error; this won't+ occur here, so just store zero. */++ PUTOFFSET((PCRE2_SIZE)0, parsed_pattern);+ }++ if ((options & PCRE2_UCP) == 0)+ *parsed_pattern++ = META_ESCAPE + ESC_w;+ else+ {+ *parsed_pattern++ = META_ESCAPE + ESC_p;+ *parsed_pattern++ = PT_WORD << 16;+ }+ *parsed_pattern++ = META_KET;+ ptr += 6;+ break;+ }++ /* PCRE supports POSIX class stuff inside a class. Perl gives an error if+ they are encountered at the top level, so we'll do that too. */++ if (ptr < ptrend && (*ptr == CHAR_COLON || *ptr == CHAR_DOT ||+ *ptr == CHAR_EQUALS_SIGN) &&+ check_posix_syntax(ptr, ptrend, &tempptr))+ {+ errorcode = (*ptr-- == CHAR_COLON)? ERR12 : ERR13;+ goto FAILED;+ }++ /* Process a regular character class. If the first character is '^', set+ the negation flag. If the first few characters (either before or after ^)+ are \Q\E or \E or space or tab in extended-more mode, we skip them too.+ This makes for compatibility with Perl. */++ negate_class = FALSE;+ while (ptr < ptrend)+ {+ GETCHARINCTEST(c, ptr);+ if (c == CHAR_BACKSLASH)+ {+ if (ptr < ptrend && *ptr == CHAR_E) ptr++;+ else if (ptrend - ptr >= 3 &&+ PRIV(strncmp_c8)(ptr, STR_Q STR_BACKSLASH STR_E, 3) == 0)+ ptr += 3;+ else+ break;+ }+ else if ((options & PCRE2_EXTENDED_MORE) != 0 &&+ (c == CHAR_SPACE || c == CHAR_HT)) /* Note: just these two */+ continue;+ else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT)+ negate_class = TRUE;+ else break;+ }++ /* Now the real contents of the class; c has the first "real" character.+ Empty classes are permitted only if the option is set. */++ if (c == CHAR_RIGHT_SQUARE_BRACKET &&+ (cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)+ {+ *parsed_pattern++ = negate_class? META_CLASS_EMPTY_NOT : META_CLASS_EMPTY;+ break; /* End of class processing */+ }++ /* Process a non-empty class. */++ *parsed_pattern++ = negate_class? META_CLASS_NOT : META_CLASS;+ class_range_state = RANGE_NO;++ /* In an EBCDIC environment, Perl treats alphabetic ranges specially+ because there are holes in the encoding, and simply using the range A-Z+ (for example) would include the characters in the holes. This applies only+ to ranges where both values are literal; [\xC1-\xE9] is different to [A-Z]+ in this respect. In order to accommodate this, we keep track of whether+ character values are literal or not, and a state variable for handling+ ranges. */++ /* Loop for the contents of the class */++ for (;;)+ {+ BOOL char_is_literal = TRUE;++ /* Inside \Q...\E everything is literal except \E */++ if (inescq)+ {+ if (c == CHAR_BACKSLASH && ptr < ptrend && *ptr == CHAR_E)+ {+ inescq = FALSE; /* Reset literal state */+ ptr++; /* Skip the 'E' */+ goto CLASS_CONTINUE;+ }+ goto CLASS_LITERAL;+ }++ /* Skip over space and tab (only) in extended-more mode. */++ if ((options & PCRE2_EXTENDED_MORE) != 0 &&+ (c == CHAR_SPACE || c == CHAR_HT))+ goto CLASS_CONTINUE;++ /* Handle POSIX class names. Perl allows a negation extension of the+ form [:^name:]. A square bracket that doesn't match the syntax is+ treated as a literal. We also recognize the POSIX constructions+ [.ch.] and [=ch=] ("collating elements") and fault them, as Perl+ 5.6 and 5.8 do. */++ if (c == CHAR_LEFT_SQUARE_BRACKET &&+ ptrend - ptr >= 3 &&+ (*ptr == CHAR_COLON || *ptr == CHAR_DOT ||+ *ptr == CHAR_EQUALS_SIGN) &&+ check_posix_syntax(ptr, ptrend, &tempptr))+ {+ BOOL posix_negate = FALSE;+ int posix_class;++ /* Perl treats a hyphen before a POSIX class as a literal, not the+ start of a range. However, it gives a warning in its warning mode. PCRE+ does not have a warning mode, so we give an error, because this is+ likely an error on the user's part. */++ if (class_range_state == RANGE_STARTED)+ {+ errorcode = ERR50;+ goto FAILED;+ }++ if (*ptr != CHAR_COLON)+ {+ errorcode = ERR13;+ goto FAILED_BACK;+ }++ if (*(++ptr) == CHAR_CIRCUMFLEX_ACCENT)+ {+ posix_negate = TRUE;+ ptr++;+ }++ posix_class = check_posix_name(ptr, (int)(tempptr - ptr));+ if (posix_class < 0)+ {+ errorcode = ERR30;+ goto FAILED;+ }+ ptr = tempptr + 2;++ /* Perl treats a hyphen after a POSIX class as a literal, not the+ start of a range. However, it gives a warning in its warning mode+ unless the hyphen is the last character in the class. PCRE does not+ have a warning mode, so we give an error, because this is likely an+ error on the user's part. */++ if (ptr < ptrend - 1 && *ptr == CHAR_MINUS &&+ ptr[1] != CHAR_RIGHT_SQUARE_BRACKET)+ {+ errorcode = ERR50;+ goto FAILED;+ }++ /* Set "a hyphen is not the start of a range" for the -] case, and also+ in case the POSIX class is followed by \E or \Q\E (possibly repeated -+ fuzzers do that kind of thing) and *then* a hyphen. This causes that+ hyphen to be treated as a literal. I don't think it's worth setting up+ special apparatus to do otherwise. */++ class_range_state = RANGE_NO;++ /* When PCRE2_UCP is set, unless PCRE2_EXTRA_ASCII_POSIX is set, some+ of the POSIX classes are converted to use Unicode properties \p or \P+ or, in one case, \h or \H. The substitutes table has two values per+ class, containing the type and value of a \p or \P item. The special+ cases are specified with a negative type: a non-zero value causes \h or+ \H to be used, and a zero value falls through to behave like a non-UCP+ POSIX class. There are now also some extra options that force ASCII for+ some classes. */++#ifdef SUPPORT_UNICODE+ if ((options & PCRE2_UCP) != 0 &&+ (xoptions & PCRE2_EXTRA_ASCII_POSIX) == 0 &&+ !((xoptions & PCRE2_EXTRA_ASCII_DIGIT) != 0 &&+ (posix_class == PC_DIGIT || posix_class == PC_XDIGIT)))+ {+ int ptype = posix_substitutes[2*posix_class];+ int pvalue = posix_substitutes[2*posix_class + 1];++ if (ptype >= 0)+ {+ *parsed_pattern++ = META_ESCAPE + (posix_negate? ESC_P : ESC_p);+ *parsed_pattern++ = (ptype << 16) | pvalue;+ goto CLASS_CONTINUE;+ }++ if (pvalue != 0)+ {+ *parsed_pattern++ = META_ESCAPE + (posix_negate? ESC_H : ESC_h);+ goto CLASS_CONTINUE;+ }++ /* Fall through */+ }+#endif /* SUPPORT_UNICODE */++ /* Non-UCP POSIX class */++ *parsed_pattern++ = posix_negate? META_POSIX_NEG : META_POSIX;+ *parsed_pattern++ = posix_class;+ }++ /* Handle potential start of range */++ else if (c == CHAR_MINUS && class_range_state >= RANGE_OK_ESCAPED)+ {+ *parsed_pattern++ = (class_range_state == RANGE_OK_LITERAL)?+ META_RANGE_LITERAL : META_RANGE_ESCAPED;+ class_range_state = RANGE_STARTED;+ }++ /* Handle a literal character */++ else if (c != CHAR_BACKSLASH)+ {+ CLASS_LITERAL:+ if (class_range_state == RANGE_STARTED)+ {+ if (c == parsed_pattern[-2]) /* Optimize one-char range */+ parsed_pattern--;+ else if (parsed_pattern[-2] > c) /* Check range is in order */+ {+ errorcode = ERR8;+ goto FAILED_BACK;+ }+ else+ {+ if (!char_is_literal && parsed_pattern[-1] == META_RANGE_LITERAL)+ parsed_pattern[-1] = META_RANGE_ESCAPED;+ PARSED_LITERAL(c, parsed_pattern);+ }+ class_range_state = RANGE_NO;+ }+ else /* Potential start of range */+ {+ class_range_state = char_is_literal?+ RANGE_OK_LITERAL : RANGE_OK_ESCAPED;+ PARSED_LITERAL(c, parsed_pattern);+ }+ }++ /* Handle escapes in a class */++ else+ {+ tempptr = ptr;+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,+ xoptions, TRUE, cb);++ if (errorcode != 0)+ {+ if ((xoptions & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)+ goto FAILED;+ ptr = tempptr;+ if (ptr >= ptrend) c = CHAR_BACKSLASH; else+ {+ GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */+ }+ escape = 0; /* Treat as literal character */+ }++ switch(escape)+ {+ case 0: /* Escaped character code point is in c */+ char_is_literal = FALSE;+ goto CLASS_LITERAL; /* (a few lines above) */++ case ESC_b:+ c = CHAR_BS; /* \b is backspace in a class */+ char_is_literal = FALSE;+ goto CLASS_LITERAL;++ case ESC_Q:+ inescq = TRUE; /* Enter literal mode */+ goto CLASS_CONTINUE;++ case ESC_E: /* Ignore orphan \E */+ goto CLASS_CONTINUE;++ case ESC_B: /* Always an error in a class */+ case ESC_R:+ case ESC_X:+ errorcode = ERR7;+ ptr--;+ goto FAILED;+ }++ /* The second part of a range can be a single-character escape+ sequence (detected above), but not any of the other escapes. Perl+ treats a hyphen as a literal in such circumstances. However, in Perl's+ warning mode, a warning is given, so PCRE now faults it, as it is+ almost certainly a mistake on the user's part. */++ if (class_range_state == RANGE_STARTED)+ {+ errorcode = ERR50;+ goto FAILED; /* Not CLASS_ESCAPE_FAILED; always an error */+ }++ /* Of the remaining escapes, only those that define characters are+ allowed in a class. None may start a range. */++ class_range_state = RANGE_NO;+ switch(escape)+ {+ case ESC_N:+ errorcode = ERR71;+ goto FAILED;++ case ESC_H:+ case ESC_h:+ case ESC_V:+ case ESC_v:+ *parsed_pattern++ = META_ESCAPE + escape;+ break;++ /* These escapes may be converted to Unicode property tests when+ PCRE2_UCP is set. */++ case ESC_d:+ case ESC_D:+ case ESC_s:+ case ESC_S:+ case ESC_w:+ case ESC_W:+ parsed_pattern = handle_escdsw(escape, parsed_pattern, options,+ xoptions);+ break;++ /* Explicit Unicode property matching */++ case ESC_P:+ case ESC_p:+#ifdef SUPPORT_UNICODE+ {+ BOOL negated;+ uint16_t ptype = 0, pdata = 0;+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))+ goto FAILED;+ if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P;+ *parsed_pattern++ = META_ESCAPE + escape;+ *parsed_pattern++ = (ptype << 16) | pdata;+ }+#else+ errorcode = ERR45;+ goto FAILED;+#endif+ break; /* End \P and \p */++ default: /* All others are not allowed in a class */+ errorcode = ERR7;+ ptr--;+ goto FAILED;+ }++ /* Perl gives a warning unless a following hyphen is the last character+ in the class. PCRE throws an error. */++ if (ptr < ptrend - 1 && *ptr == CHAR_MINUS &&+ ptr[1] != CHAR_RIGHT_SQUARE_BRACKET)+ {+ errorcode = ERR50;+ goto FAILED;+ }+ }++ /* Proceed to next thing in the class. */++ CLASS_CONTINUE:+ if (ptr >= ptrend)+ {+ errorcode = ERR6; /* Missing terminating ']' */+ goto FAILED;+ }+ GETCHARINCTEST(c, ptr);+ if (c == CHAR_RIGHT_SQUARE_BRACKET && !inescq) break;+ } /* End of class-processing loop */++ /* -] at the end of a class is a literal '-' */++ if (class_range_state == RANGE_STARTED)+ {+ parsed_pattern[-1] = CHAR_MINUS;+ class_range_state = RANGE_NO;+ }++ *parsed_pattern++ = META_CLASS_END;+ break; /* End of character class */+++ /* ---- Opening parenthesis ---- */++ case CHAR_LEFT_PARENTHESIS:+ if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;++ /* If ( is not followed by ? it is either a capture or a special verb or an+ alpha assertion or a positive non-atomic lookahead. */++ if (*ptr != CHAR_QUESTION_MARK)+ {+ const char *vn;++ /* Handle capturing brackets (or non-capturing if auto-capture is turned+ off). */++ if (*ptr != CHAR_ASTERISK)+ {+ nest_depth++;+ if ((options & PCRE2_NO_AUTO_CAPTURE) == 0)+ {+ if (cb->bracount >= MAX_GROUP_NUMBER)+ {+ errorcode = ERR97;+ goto FAILED;+ }+ cb->bracount++;+ *parsed_pattern++ = META_CAPTURE | cb->bracount;+ }+ else *parsed_pattern++ = META_NOCAPTURE;+ }++ /* Do nothing for (* followed by end of pattern or ) so it gives a "bad+ quantifier" error rather than "(*MARK) must have an argument". */++ else if (ptrend - ptr <= 1 || (c = ptr[1]) == CHAR_RIGHT_PARENTHESIS)+ break;++ /* Handle "alpha assertions" such as (*pla:...). Most of these are+ synonyms for the historical symbolic assertions, but the script run and+ non-atomic lookaround ones are new. They are distinguished by starting+ with a lower case letter. Checking both ends of the alphabet makes this+ work in all character codes. */++ else if (CHMAX_255(c) && (cb->ctypes[c] & ctype_lcletter) != 0)+ {+ uint32_t meta;++ vn = alasnames;+ if (!read_name(&ptr, ptrend, utf, 0, &offset, &name, &namelen,+ &errorcode, cb)) goto FAILED;+ if (ptr >= ptrend || *ptr != CHAR_COLON)+ {+ errorcode = ERR95; /* Malformed */+ goto FAILED;+ }++ /* Scan the table of alpha assertion names */++ for (i = 0; i < alascount; i++)+ {+ if (namelen == alasmeta[i].len &&+ PRIV(strncmp_c8)(name, vn, namelen) == 0)+ break;+ vn += alasmeta[i].len + 1;+ }++ if (i >= alascount)+ {+ errorcode = ERR95; /* Alpha assertion not recognized */+ goto FAILED;+ }++ /* Check for expecting an assertion condition. If so, only atomic+ lookaround assertions are valid. */++ meta = alasmeta[i].meta;+ if (prev_expect_cond_assert > 0 &&+ (meta < META_LOOKAHEAD || meta > META_LOOKBEHINDNOT))+ {+ errorcode = (meta == META_LOOKAHEAD_NA || meta == META_LOOKBEHIND_NA)?+ ERR98 : ERR28; /* (Atomic) assertion expected */+ goto FAILED;+ }++ /* The lookaround alphabetic synonyms can mostly be handled by jumping+ to the code that handles the traditional symbolic forms. */++ switch(meta)+ {+ default:+ errorcode = ERR89; /* Unknown code; should never occur because */+ goto FAILED; /* the meta values come from a table above. */++ case META_ATOMIC:+ goto ATOMIC_GROUP;++ case META_LOOKAHEAD:+ goto POSITIVE_LOOK_AHEAD;++ case META_LOOKAHEAD_NA:+ goto POSITIVE_NONATOMIC_LOOK_AHEAD;++ case META_LOOKAHEADNOT:+ goto NEGATIVE_LOOK_AHEAD;++ case META_LOOKBEHIND:+ case META_LOOKBEHINDNOT:+ case META_LOOKBEHIND_NA:+ *parsed_pattern++ = meta;+ ptr--;+ goto POST_LOOKBEHIND;++ /* The script run facilities are handled here. Unicode support is+ required (give an error if not, as this is a security issue). Always+ record a META_SCRIPT_RUN item. Then, for the atomic version, insert+ META_ATOMIC and remember that we need two META_KETs at the end. */++ case META_SCRIPT_RUN:+ case META_ATOMIC_SCRIPT_RUN:+#ifdef SUPPORT_UNICODE+ *parsed_pattern++ = META_SCRIPT_RUN;+ nest_depth++;+ ptr++;+ if (meta == META_ATOMIC_SCRIPT_RUN)+ {+ *parsed_pattern++ = META_ATOMIC;+ if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);+ else if (++top_nest >= end_nests)+ {+ errorcode = ERR84;+ goto FAILED;+ }+ top_nest->nest_depth = nest_depth;+ top_nest->flags = NSF_ATOMICSR;+ top_nest->options = options & PARSE_TRACKED_OPTIONS;+ top_nest->xoptions = xoptions & PARSE_TRACKED_EXTRA_OPTIONS;+ }+ break;+#else /* SUPPORT_UNICODE */+ errorcode = ERR96;+ goto FAILED;+#endif+ }+ }+++ /* ---- Handle (*VERB) and (*VERB:NAME) ---- */++ else+ {+ vn = verbnames;+ if (!read_name(&ptr, ptrend, utf, 0, &offset, &name, &namelen,+ &errorcode, cb)) goto FAILED;+ if (ptr >= ptrend || (*ptr != CHAR_COLON &&+ *ptr != CHAR_RIGHT_PARENTHESIS))+ {+ errorcode = ERR60; /* Malformed */+ goto FAILED;+ }++ /* Scan the table of verb names */++ for (i = 0; i < verbcount; i++)+ {+ if (namelen == verbs[i].len &&+ PRIV(strncmp_c8)(name, vn, namelen) == 0)+ break;+ vn += verbs[i].len + 1;+ }++ if (i >= verbcount)+ {+ errorcode = ERR60; /* Verb not recognized */+ goto FAILED;+ }++ /* An empty argument is treated as no argument. */++ if (*ptr == CHAR_COLON && ptr + 1 < ptrend &&+ ptr[1] == CHAR_RIGHT_PARENTHESIS)+ ptr++; /* Advance to the closing parens */++ /* Check for mandatory non-empty argument; this is (*MARK) */++ if (verbs[i].has_arg > 0 && *ptr != CHAR_COLON)+ {+ errorcode = ERR66;+ goto FAILED;+ }++ /* Remember where this verb, possibly with a preceding (*MARK), starts,+ for handling quantified (*ACCEPT). */++ verbstartptr = parsed_pattern;+ okquantifier = (verbs[i].meta == META_ACCEPT);++ /* It appears that Perl allows any characters whatsoever, other than a+ closing parenthesis, to appear in arguments ("names"), so we no longer+ insist on letters, digits, and underscores. Perl does not, however, do+ any interpretation within arguments, and has no means of including a+ closing parenthesis. PCRE supports escape processing but only when it+ is requested by an option. We set inverbname TRUE here, and let the+ main loop take care of this so that escape and \x processing is done by+ the main code above. */++ if (*ptr++ == CHAR_COLON) /* Skip past : or ) */+ {+ /* Some optional arguments can be treated as a preceding (*MARK) */++ if (verbs[i].has_arg < 0)+ {+ add_after_mark = verbs[i].meta;+ *parsed_pattern++ = META_MARK;+ }++ /* The remaining verbs with arguments (except *MARK) need a different+ opcode. */++ else+ {+ *parsed_pattern++ = verbs[i].meta ++ ((verbs[i].meta != META_MARK)? 0x00010000u:0);+ }++ /* Set up for reading the name in the main loop. */++ verblengthptr = parsed_pattern++;+ verbnamestart = ptr;+ inverbname = TRUE;+ }+ else /* No verb "name" argument */+ {+ *parsed_pattern++ = verbs[i].meta;+ }+ } /* End of (*VERB) handling */+ break; /* Done with this parenthesis */+ } /* End of groups that don't start with (? */+++ /* ---- Items starting (? ---- */++ /* The type of item is determined by what follows (?. Handle (?| and option+ changes under "default" because both need a new block on the nest stack.+ Comments starting with (?# are handled above. Note that there is some+ ambiguity about the sequence (?- because if a digit follows it's a relative+ recursion or subroutine call whereas otherwise it's an option unsetting. */++ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;++ switch(*ptr)+ {+ default:+ if (*ptr == CHAR_MINUS && ptrend - ptr > 1 && IS_DIGIT(ptr[1]))+ goto RECURSION_BYNUMBER; /* The + case is handled by CHAR_PLUS */++ /* We now have either (?| or a (possibly empty) option setting,+ optionally followed by a non-capturing group. */++ nest_depth++;+ if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);+ else if (++top_nest >= end_nests)+ {+ errorcode = ERR84;+ goto FAILED;+ }+ top_nest->nest_depth = nest_depth;+ top_nest->flags = 0;+ top_nest->options = options & PARSE_TRACKED_OPTIONS;+ top_nest->xoptions = xoptions & PARSE_TRACKED_EXTRA_OPTIONS;++ /* Start of non-capturing group that resets the capture count for each+ branch. */++ if (*ptr == CHAR_VERTICAL_LINE)+ {+ top_nest->reset_group = (uint16_t)cb->bracount;+ top_nest->max_group = (uint16_t)cb->bracount;+ top_nest->flags |= NSF_RESET;+ cb->external_flags |= PCRE2_DUPCAPUSED;+ *parsed_pattern++ = META_NOCAPTURE;+ ptr++;+ }++ /* Scan for options imnrsxJU to be set or unset. */++ else+ {+ BOOL hyphenok = TRUE;+ uint32_t oldoptions = options;+ uint32_t oldxoptions = xoptions;++ top_nest->reset_group = 0;+ top_nest->max_group = 0;+ set = unset = 0;+ optset = &set;+ xset = xunset = 0;+ xoptset = &xset;++ /* ^ at the start unsets irmnsx and disables the subsequent use of - */++ if (ptr < ptrend && *ptr == CHAR_CIRCUMFLEX_ACCENT)+ {+ options &= ~(PCRE2_CASELESS|PCRE2_MULTILINE|PCRE2_NO_AUTO_CAPTURE|+ PCRE2_DOTALL|PCRE2_EXTENDED|PCRE2_EXTENDED_MORE);+ xoptions &= ~(PCRE2_EXTRA_CASELESS_RESTRICT);+ hyphenok = FALSE;+ ptr++;+ }++ while (ptr < ptrend && *ptr != CHAR_RIGHT_PARENTHESIS &&+ *ptr != CHAR_COLON)+ {+ switch (*ptr++)+ {+ case CHAR_MINUS:+ if (!hyphenok)+ {+ errorcode = ERR94;+ ptr--; /* Correct the offset */+ goto FAILED;+ }+ optset = &unset;+ xoptset = &xunset;+ hyphenok = FALSE;+ break;++ /* There are some two-character sequences that start with 'a'. */++ case CHAR_a:+ if (ptr < ptrend)+ {+ if (*ptr == CHAR_D)+ {+ *xoptset |= PCRE2_EXTRA_ASCII_BSD;+ ptr++;+ break;+ }+ if (*ptr == CHAR_P)+ {+ *xoptset |= (PCRE2_EXTRA_ASCII_POSIX|PCRE2_EXTRA_ASCII_DIGIT);+ ptr++;+ break;+ }+ if (*ptr == CHAR_S)+ {+ *xoptset |= PCRE2_EXTRA_ASCII_BSS;+ ptr++;+ break;+ }+ if (*ptr == CHAR_T)+ {+ *xoptset |= PCRE2_EXTRA_ASCII_DIGIT;+ ptr++;+ break;+ }+ if (*ptr == CHAR_W)+ {+ *xoptset |= PCRE2_EXTRA_ASCII_BSW;+ ptr++;+ break;+ }+ }+ *xoptset |= PCRE2_EXTRA_ASCII_BSD|PCRE2_EXTRA_ASCII_BSS|+ PCRE2_EXTRA_ASCII_BSW|+ PCRE2_EXTRA_ASCII_DIGIT|PCRE2_EXTRA_ASCII_POSIX;+ break;++ case CHAR_J: /* Record that it changed in the external options */+ *optset |= PCRE2_DUPNAMES;+ cb->external_flags |= PCRE2_JCHANGED;+ break;++ case CHAR_i: *optset |= PCRE2_CASELESS; break;+ case CHAR_m: *optset |= PCRE2_MULTILINE; break;+ case CHAR_n: *optset |= PCRE2_NO_AUTO_CAPTURE; break;+ case CHAR_r: *xoptset|= PCRE2_EXTRA_CASELESS_RESTRICT; break;+ case CHAR_s: *optset |= PCRE2_DOTALL; break;+ case CHAR_U: *optset |= PCRE2_UNGREEDY; break;++ /* If x appears twice it sets the extended extended option. */++ case CHAR_x:+ *optset |= PCRE2_EXTENDED;+ if (ptr < ptrend && *ptr == CHAR_x)+ {+ *optset |= PCRE2_EXTENDED_MORE;+ ptr++;+ }+ break;++ default:+ errorcode = ERR11;+ ptr--; /* Correct the offset */+ goto FAILED;+ }+ }++ /* If we are setting extended without extended-more, ensure that any+ existing extended-more gets unset. Also, unsetting extended must also+ unset extended-more. */++ if ((set & (PCRE2_EXTENDED|PCRE2_EXTENDED_MORE)) == PCRE2_EXTENDED ||+ (unset & PCRE2_EXTENDED) != 0)+ unset |= PCRE2_EXTENDED_MORE;++ options = (options | set) & (~unset);+ xoptions = (xoptions | xset) & (~xunset);++ /* If the options ended with ')' this is not the start of a nested+ group with option changes, so the options change at this level.+ In this case, if the previous level set up a nest block, discard the+ one we have just created. Otherwise adjust it for the previous level.+ If the options ended with ':' we are starting a non-capturing group,+ possibly with an options setting. */++ if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;+ if (*ptr++ == CHAR_RIGHT_PARENTHESIS)+ {+ nest_depth--; /* This is not a nested group after all. */+ if (top_nest > (nest_save *)(cb->start_workspace) &&+ (top_nest-1)->nest_depth == nest_depth) top_nest--;+ else top_nest->nest_depth = nest_depth;+ }+ else *parsed_pattern++ = META_NOCAPTURE;++ /* If nothing changed, no need to record. */++ if (options != oldoptions || xoptions != oldxoptions)+ {+ *parsed_pattern++ = META_OPTIONS;+ *parsed_pattern++ = options;+ *parsed_pattern++ = xoptions;+ }+ } /* End options processing */+ break; /* End default case after (? */+++ /* ---- Python syntax support ---- */++ case CHAR_P:+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;++ /* (?P<name> is the same as (?<name>, which defines a named group. */++ if (*ptr == CHAR_LESS_THAN_SIGN)+ {+ terminator = CHAR_GREATER_THAN_SIGN;+ goto DEFINE_NAME;+ }++ /* (?P>name) is the same as (?&name), which is a recursion or subroutine+ call. */++ if (*ptr == CHAR_GREATER_THAN_SIGN) goto RECURSE_BY_NAME;++ /* (?P=name) is the same as \k<name>, a back reference by name. Anything+ else after (?P is an error. */++ if (*ptr != CHAR_EQUALS_SIGN)+ {+ errorcode = ERR41;+ goto FAILED;+ }+ if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,+ &namelen, &errorcode, cb)) goto FAILED;+ *parsed_pattern++ = META_BACKREF_BYNAME;+ *parsed_pattern++ = namelen;+ PUTOFFSET(offset, parsed_pattern);+ okquantifier = TRUE;+ break; /* End of (?P processing */+++ /* ---- Recursion/subroutine calls by number ---- */++ case CHAR_R:+ i = 0; /* (?R) == (?R0) */+ ptr++;+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR58;+ goto FAILED;+ }+ goto SET_RECURSION;++ /* An item starting (?- followed by a digit comes here via the "default"+ case because (?- followed by a non-digit is an options setting. */++ case CHAR_PLUS:+ if (ptrend - ptr < 2 || !IS_DIGIT(ptr[1]))+ {+ errorcode = ERR29; /* Missing number */+ goto FAILED;+ }+ /* Fall through */++ case CHAR_0: case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4:+ case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:+ RECURSION_BYNUMBER:+ if (!read_number(&ptr, ptrend,+ (IS_DIGIT(*ptr))? -1:(int)(cb->bracount), /* + and - are relative */+ MAX_GROUP_NUMBER, ERR61,+ &i, &errorcode)) goto FAILED;+ if (i < 0) /* NB (?0) is permitted */+ {+ errorcode = ERR15; /* Unknown group */+ goto FAILED_BACK;+ }+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ goto UNCLOSED_PARENTHESIS;++ SET_RECURSION:+ *parsed_pattern++ = META_RECURSE | (uint32_t)i;+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern);+ ptr++;+ PUTOFFSET(offset, parsed_pattern);+ okquantifier = TRUE;+ break; /* End of recursive call by number handling */+++ /* ---- Recursion/subroutine calls by name ---- */++ case CHAR_AMPERSAND:+ RECURSE_BY_NAME:+ if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,+ &namelen, &errorcode, cb)) goto FAILED;+ *parsed_pattern++ = META_RECURSE_BYNAME;+ *parsed_pattern++ = namelen;+ PUTOFFSET(offset, parsed_pattern);+ okquantifier = TRUE;+ break;++ /* ---- Callout with numerical or string argument ---- */++ case CHAR_C:+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;++ /* If the previous item was a condition starting (?(? an assertion,+ optionally preceded by a callout, is expected. This is checked later on,+ during actual compilation. However we need to identify this kind of+ assertion in this pass because it must not be qualified. The value of+ expect_cond_assert is set to 2 after (?(? is processed. We decrement it+ for a callout - still leaving a positive value that identifies the+ assertion. Multiple callouts or any other items will make it zero or+ less, which doesn't matter because they will cause an error later. */++ expect_cond_assert = prev_expect_cond_assert - 1;++ /* If previous_callout is not NULL, it means this follows a previous+ callout. If it was a manual callout, do nothing; this means its "length+ of next pattern item" field will remain zero. If it was an automatic+ callout, abolish it. */++ if (previous_callout != NULL && (options & PCRE2_AUTO_CALLOUT) != 0 &&+ previous_callout == parsed_pattern - 4 &&+ parsed_pattern[-1] == 255)+ parsed_pattern = previous_callout;++ /* Save for updating next pattern item length, and skip one item before+ completing. */++ previous_callout = parsed_pattern;+ after_manual_callout = 1;++ /* Handle a string argument; specific delimiter is required. */++ if (*ptr != CHAR_RIGHT_PARENTHESIS && !IS_DIGIT(*ptr))+ {+ PCRE2_SIZE calloutlength;+ PCRE2_SPTR startptr = ptr;++ delimiter = 0;+ for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)+ {+ if (*ptr == PRIV(callout_start_delims)[i])+ {+ delimiter = PRIV(callout_end_delims)[i];+ break;+ }+ }+ if (delimiter == 0)+ {+ errorcode = ERR82;+ goto FAILED;+ }++ *parsed_pattern = META_CALLOUT_STRING;+ parsed_pattern += 3; /* Skip pattern info */++ for (;;)+ {+ if (++ptr >= ptrend)+ {+ errorcode = ERR81;+ ptr = startptr; /* To give a more useful message */+ goto FAILED;+ }+ if (*ptr == delimiter && (++ptr >= ptrend || *ptr != delimiter))+ break;+ }++ calloutlength = (PCRE2_SIZE)(ptr - startptr);+ if (calloutlength > UINT32_MAX)+ {+ errorcode = ERR72;+ goto FAILED;+ }+ *parsed_pattern++ = (uint32_t)calloutlength;+ offset = (PCRE2_SIZE)(startptr - cb->start_pattern);+ PUTOFFSET(offset, parsed_pattern);+ }++ /* Handle a callout with an optional numerical argument, which must be+ less than or equal to 255. A missing argument gives 0. */++ else+ {+ int n = 0;+ *parsed_pattern = META_CALLOUT_NUMBER; /* Numerical callout */+ parsed_pattern += 3; /* Skip pattern info */+ while (ptr < ptrend && IS_DIGIT(*ptr))+ {+ n = n * 10 + *ptr++ - CHAR_0;+ if (n > 255)+ {+ errorcode = ERR38;+ goto FAILED;+ }+ }+ *parsed_pattern++ = n;+ }++ /* Both formats must have a closing parenthesis */++ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR39;+ goto FAILED;+ }+ ptr++;++ /* Remember the offset to the next item in the pattern, and set a default+ length. This should get updated after the next item is read. */++ previous_callout[1] = (uint32_t)(ptr - cb->start_pattern);+ previous_callout[2] = 0;+ break; /* End callout */+++ /* ---- Conditional group ---- */++ /* A condition can be an assertion, a number (referring to a numbered+ group's having been set), a name (referring to a named group), or 'R',+ referring to overall recursion. R<digits> and R&name are also permitted+ for recursion state tests. Numbers may be preceded by + or - to specify a+ relative group number.++ There are several syntaxes for testing a named group: (?(name)) is used+ by Python; Perl 5.10 onwards uses (?(<name>) or (?('name')).++ There are two unfortunate ambiguities. 'R' can be the recursive thing or+ the name 'R' (and similarly for 'R' followed by digits). 'DEFINE' can be+ the Perl DEFINE feature or the Python named test. We look for a name+ first; if not found, we try the other case.++ For compatibility with auto-callouts, we allow a callout to be specified+ before a condition that is an assertion. */++ case CHAR_LEFT_PARENTHESIS:+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;+ nest_depth++;++ /* If the next character is ? or * there must be an assertion next+ (optionally preceded by a callout). We do not check this here, but+ instead we set expect_cond_assert to 2. If this is still greater than+ zero (callouts decrement it) when the next assertion is read, it will be+ marked as a condition that must not be repeated. A value greater than+ zero also causes checking that an assertion (possibly with callout)+ follows. */++ if (*ptr == CHAR_QUESTION_MARK || *ptr == CHAR_ASTERISK)+ {+ *parsed_pattern++ = META_COND_ASSERT;+ ptr--; /* Pull pointer back to the opening parenthesis. */+ expect_cond_assert = 2;+ break; /* End of conditional */+ }++ /* Handle (?([+-]number)... */++ if (read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &i,+ &errorcode))+ {+ if (i <= 0)+ {+ errorcode = ERR15;+ goto FAILED;+ }+ *parsed_pattern++ = META_COND_NUMBER;+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);+ PUTOFFSET(offset, parsed_pattern);+ *parsed_pattern++ = i;+ }+ else if (errorcode != 0) goto FAILED; /* Number too big */++ /* No number found. Handle the special case (?(VERSION[>]=n.m)... */++ else if (ptrend - ptr >= 10 &&+ PRIV(strncmp_c8)(ptr, STRING_VERSION, 7) == 0 &&+ ptr[7] != CHAR_RIGHT_PARENTHESIS)+ {+ uint32_t ge = 0;+ int major = 0;+ int minor = 0;++ ptr += 7;+ if (*ptr == CHAR_GREATER_THAN_SIGN)+ {+ ge = 1;+ ptr++;+ }++ /* NOTE: cannot write IS_DIGIT(*(++ptr)) here because IS_DIGIT+ references its argument twice. */++ if (*ptr != CHAR_EQUALS_SIGN || (ptr++, !IS_DIGIT(*ptr)))+ goto BAD_VERSION_CONDITION;++ if (!read_number(&ptr, ptrend, -1, 1000, ERR79, &major, &errorcode))+ goto FAILED;++ if (ptr >= ptrend) goto BAD_VERSION_CONDITION;+ if (*ptr == CHAR_DOT)+ {+ if (++ptr >= ptrend || !IS_DIGIT(*ptr)) goto BAD_VERSION_CONDITION;+ minor = (*ptr++ - CHAR_0) * 10;+ if (ptr >= ptrend) goto BAD_VERSION_CONDITION;+ if (IS_DIGIT(*ptr)) minor += *ptr++ - CHAR_0;+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ goto BAD_VERSION_CONDITION;+ }++ *parsed_pattern++ = META_COND_VERSION;+ *parsed_pattern++ = ge;+ *parsed_pattern++ = major;+ *parsed_pattern++ = minor;+ }++ /* All the remaining cases now require us to read a name. We cannot at+ this stage distinguish ambiguous cases such as (?(R12) which might be a+ recursion test by number or a name, because the named groups have not yet+ all been identified. Those cases are treated as names, but given a+ different META code. */++ else+ {+ BOOL was_r_ampersand = FALSE;++ if (*ptr == CHAR_R && ptrend - ptr > 1 && ptr[1] == CHAR_AMPERSAND)+ {+ terminator = CHAR_RIGHT_PARENTHESIS;+ was_r_ampersand = TRUE;+ ptr++;+ }+ else if (*ptr == CHAR_LESS_THAN_SIGN)+ terminator = CHAR_GREATER_THAN_SIGN;+ else if (*ptr == CHAR_APOSTROPHE)+ terminator = CHAR_APOSTROPHE;+ else+ {+ terminator = CHAR_RIGHT_PARENTHESIS;+ ptr--; /* Point to char before name */+ }+ if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,+ &errorcode, cb)) goto FAILED;++ /* Handle (?(R&name) */++ if (was_r_ampersand)+ {+ *parsed_pattern = META_COND_RNAME;+ ptr--; /* Back to closing parens */+ }++ /* Handle (?(name). If the name is "DEFINE" we identify it with a+ special code. Likewise if the name consists of R followed only by+ digits. Otherwise, handle it like a quoted name. */++ else if (terminator == CHAR_RIGHT_PARENTHESIS)+ {+ if (namelen == 6 && PRIV(strncmp_c8)(name, STRING_DEFINE, 6) == 0)+ *parsed_pattern = META_COND_DEFINE;+ else+ {+ for (i = 1; i < (int)namelen; i++)+ if (!IS_DIGIT(name[i])) break;+ *parsed_pattern = (*name == CHAR_R && i >= (int)namelen)?+ META_COND_RNUMBER : META_COND_NAME;+ }+ ptr--; /* Back to closing parens */+ }++ /* Handle (?('name') or (?(<name>) */++ else *parsed_pattern = META_COND_NAME;++ /* All these cases except DEFINE end with the name length and offset;+ DEFINE just has an offset (for the "too many branches" error). */++ if (*parsed_pattern++ != META_COND_DEFINE) *parsed_pattern++ = namelen;+ PUTOFFSET(offset, parsed_pattern);+ } /* End cases that read a name */++ /* Check the closing parenthesis of the condition */++ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR24;+ goto FAILED;+ }+ ptr++;+ break; /* End of condition processing */+++ /* ---- Atomic group ---- */++ case CHAR_GREATER_THAN_SIGN:+ ATOMIC_GROUP: /* Come from (*atomic: */+ *parsed_pattern++ = META_ATOMIC;+ nest_depth++;+ ptr++;+ break;+++ /* ---- Lookahead assertions ---- */++ case CHAR_EQUALS_SIGN:+ POSITIVE_LOOK_AHEAD: /* Come from (*pla: */+ *parsed_pattern++ = META_LOOKAHEAD;+ ptr++;+ goto POST_ASSERTION;++ case CHAR_ASTERISK:+ POSITIVE_NONATOMIC_LOOK_AHEAD: /* Come from (?* */+ *parsed_pattern++ = META_LOOKAHEAD_NA;+ ptr++;+ goto POST_ASSERTION;++ case CHAR_EXCLAMATION_MARK:+ NEGATIVE_LOOK_AHEAD: /* Come from (*nla: */+ *parsed_pattern++ = META_LOOKAHEADNOT;+ ptr++;+ goto POST_ASSERTION;+++ /* ---- Lookbehind assertions ---- */++ /* (?< followed by = or ! or * is a lookbehind assertion. Otherwise (?<+ is the start of the name of a capturing group. */++ case CHAR_LESS_THAN_SIGN:+ if (ptrend - ptr <= 1 ||+ (ptr[1] != CHAR_EQUALS_SIGN &&+ ptr[1] != CHAR_EXCLAMATION_MARK &&+ ptr[1] != CHAR_ASTERISK))+ {+ terminator = CHAR_GREATER_THAN_SIGN;+ goto DEFINE_NAME;+ }+ *parsed_pattern++ = (ptr[1] == CHAR_EQUALS_SIGN)?+ META_LOOKBEHIND : (ptr[1] == CHAR_EXCLAMATION_MARK)?+ META_LOOKBEHINDNOT : META_LOOKBEHIND_NA;++ POST_LOOKBEHIND: /* Come from (*plb: (*naplb: and (*nlb: */+ *has_lookbehind = TRUE;+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);+ PUTOFFSET(offset, parsed_pattern);+ ptr += 2;+ /* Fall through */++ /* If the previous item was a condition starting (?(? an assertion,+ optionally preceded by a callout, is expected. This is checked later on,+ during actual compilation. However we need to identify this kind of+ assertion in this pass because it must not be qualified. The value of+ expect_cond_assert is set to 2 after (?(? is processed. We decrement it+ for a callout - still leaving a positive value that identifies the+ assertion. Multiple callouts or any other items will make it zero or+ less, which doesn't matter because they will cause an error later. */++ POST_ASSERTION:+ nest_depth++;+ if (prev_expect_cond_assert > 0)+ {+ if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);+ else if (++top_nest >= end_nests)+ {+ errorcode = ERR84;+ goto FAILED;+ }+ top_nest->nest_depth = nest_depth;+ top_nest->flags = NSF_CONDASSERT;+ top_nest->options = options & PARSE_TRACKED_OPTIONS;+ top_nest->xoptions = xoptions & PARSE_TRACKED_EXTRA_OPTIONS;+ }+ break;+++ /* ---- Define a named group ---- */++ /* A named group may be defined as (?'name') or (?<name>). In the latter+ case we jump to DEFINE_NAME from the disambiguation of (?< above with the+ terminator set to '>'. */++ case CHAR_APOSTROPHE:+ terminator = CHAR_APOSTROPHE; /* Terminator */++ DEFINE_NAME:+ if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,+ &errorcode, cb)) goto FAILED;++ /* We have a name for this capturing group. It is also assigned a number,+ which is its primary means of identification. */++ if (cb->bracount >= MAX_GROUP_NUMBER)+ {+ errorcode = ERR97;+ goto FAILED;+ }+ cb->bracount++;+ *parsed_pattern++ = META_CAPTURE | cb->bracount;+ nest_depth++;++ /* Check not too many names */++ if (cb->names_found >= MAX_NAME_COUNT)+ {+ errorcode = ERR49;+ goto FAILED;+ }++ /* Adjust the entry size to accommodate the longest name found. */++ if (namelen + IMM2_SIZE + 1 > cb->name_entry_size)+ cb->name_entry_size = (uint16_t)(namelen + IMM2_SIZE + 1);++ /* Scan the list to check for duplicates. For duplicate names, if the+ number is the same, break the loop, which causes the name to be+ discarded; otherwise, if DUPNAMES is not set, give an error.+ If it is set, allow the name with a different number, but continue+ scanning in case this is a duplicate with the same number. For+ non-duplicate names, give an error if the number is duplicated. */++ isdupname = FALSE;+ ng = cb->named_groups;+ for (i = 0; i < cb->names_found; i++, ng++)+ {+ if (namelen == ng->length &&+ PRIV(strncmp)(name, ng->name, (PCRE2_SIZE)namelen) == 0)+ {+ if (ng->number == cb->bracount) break;+ if ((options & PCRE2_DUPNAMES) == 0)+ {+ errorcode = ERR43;+ goto FAILED;+ }+ isdupname = ng->isdup = TRUE; /* Mark as a duplicate */+ cb->dupnames = TRUE; /* Duplicate names exist */+ }+ else if (ng->number == cb->bracount)+ {+ errorcode = ERR65;+ goto FAILED;+ }+ }++ if (i < cb->names_found) break; /* Ignore duplicate with same number */++ /* Increase the list size if necessary */++ if (cb->names_found >= cb->named_group_list_size)+ {+ uint32_t newsize = cb->named_group_list_size * 2;+ named_group *newspace =+ cb->cx->memctl.malloc(newsize * sizeof(named_group),+ cb->cx->memctl.memory_data);+ if (newspace == NULL)+ {+ errorcode = ERR21;+ goto FAILED;+ }++ memcpy(newspace, cb->named_groups,+ cb->named_group_list_size * sizeof(named_group));+ if (cb->named_group_list_size > NAMED_GROUP_LIST_SIZE)+ cb->cx->memctl.free((void *)cb->named_groups,+ cb->cx->memctl.memory_data);+ cb->named_groups = newspace;+ cb->named_group_list_size = newsize;+ }++ /* Add this name to the list */++ cb->named_groups[cb->names_found].name = name;+ cb->named_groups[cb->names_found].length = (uint16_t)namelen;+ cb->named_groups[cb->names_found].number = cb->bracount;+ cb->named_groups[cb->names_found].isdup = (uint16_t)isdupname;+ cb->names_found++;+ break;+ } /* End of (? switch */+ break; /* End of ( handling */+++ /* ---- Branch terminators ---- */++ /* Alternation: reset the capture count if we are in a (?| group. */++ case CHAR_VERTICAL_LINE:+ if (top_nest != NULL && top_nest->nest_depth == nest_depth &&+ (top_nest->flags & NSF_RESET) != 0)+ {+ if (cb->bracount > top_nest->max_group)+ top_nest->max_group = (uint16_t)cb->bracount;+ cb->bracount = top_nest->reset_group;+ }+ *parsed_pattern++ = META_ALT;+ break;++ /* End of group; reset the capture count to the maximum if we are in a (?|+ group and/or reset the options that are tracked during parsing. Disallow+ quantifier for a condition that is an assertion. */++ case CHAR_RIGHT_PARENTHESIS:+ okquantifier = TRUE;+ if (top_nest != NULL && top_nest->nest_depth == nest_depth)+ {+ options = (options & ~PARSE_TRACKED_OPTIONS) | top_nest->options;+ xoptions = (xoptions & ~PARSE_TRACKED_EXTRA_OPTIONS) | top_nest->xoptions;+ if ((top_nest->flags & NSF_RESET) != 0 &&+ top_nest->max_group > cb->bracount)+ cb->bracount = top_nest->max_group;+ if ((top_nest->flags & NSF_CONDASSERT) != 0)+ okquantifier = FALSE;++ if ((top_nest->flags & NSF_ATOMICSR) != 0)+ {+ *parsed_pattern++ = META_KET;+ }++ if (top_nest == (nest_save *)(cb->start_workspace)) top_nest = NULL;+ else top_nest--;+ }+ if (nest_depth == 0) /* Unmatched closing parenthesis */+ {+ errorcode = ERR22;+ goto FAILED_BACK;+ }+ nest_depth--;+ *parsed_pattern++ = META_KET;+ break;+ } /* End of switch on pattern character */+ } /* End of main character scan loop */++/* End of pattern reached. Check for missing ) at the end of a verb name. */++if (inverbname && ptr >= ptrend)+ {+ errorcode = ERR60;+ goto FAILED;+ }++/* Manage callout for the final item */++PARSED_END:+parsed_pattern = manage_callouts(ptr, &previous_callout, auto_callout,+ parsed_pattern, cb);++/* Insert trailing items for word and line matching (features provided for the+benefit of pcre2grep). */++if ((xoptions & PCRE2_EXTRA_MATCH_LINE) != 0)+ {+ *parsed_pattern++ = META_KET;+ *parsed_pattern++ = META_DOLLAR;+ }+else if ((xoptions & PCRE2_EXTRA_MATCH_WORD) != 0)+ {+ *parsed_pattern++ = META_KET;+ *parsed_pattern++ = META_ESCAPE + ESC_b;+ }++/* Terminate the parsed pattern, then return success if all groups are closed.+Otherwise we have unclosed parentheses. */++if (parsed_pattern >= parsed_pattern_end)+ {+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */+ goto FAILED;+ }++*parsed_pattern = META_END;+if (nest_depth == 0) return 0;++UNCLOSED_PARENTHESIS:+errorcode = ERR14;++/* Come here for all failures. */++FAILED:+cb->erroroffset = (PCRE2_SIZE)(ptr - cb->start_pattern);+return errorcode;++/* Some errors need to indicate the previous character. */++FAILED_BACK:+ptr--;+goto FAILED;++/* This failure happens several times. */++BAD_VERSION_CONDITION:+errorcode = ERR79;+goto FAILED;+}++++/*************************************************+* Find first significant opcode *+*************************************************/++/* This is called by several functions that scan a compiled expression looking+for a fixed first character, or an anchoring opcode etc. It skips over things+that do not influence this. For some calls, it makes sense to skip negative+forward and all backward assertions, and also the \b assertion; for others it+does not.++Arguments:+ code pointer to the start of the group+ skipassert TRUE if certain assertions are to be skipped++Returns: pointer to the first significant opcode+*/++static const PCRE2_UCHAR*+first_significant_code(PCRE2_SPTR code, BOOL skipassert)+{+for (;;)+ {+ switch ((int)*code)+ {+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERTBACK_NA:+ if (!skipassert) return code;+ do code += GET(code, 1); while (*code == OP_ALT);+ code += PRIV(OP_lengths)[*code];+ break;++ case OP_WORD_BOUNDARY:+ case OP_NOT_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:+ case OP_NOT_UCP_WORD_BOUNDARY:+ if (!skipassert) return code;+ /* Fall through */++ case OP_CALLOUT:+ case OP_CREF:+ case OP_DNCREF:+ case OP_RREF:+ case OP_DNRREF:+ case OP_FALSE:+ case OP_TRUE:+ code += PRIV(OP_lengths)[*code];+ break;++ case OP_CALLOUT_STR:+ code += GET(code, 1 + 2*LINK_SIZE);+ break;++ case OP_SKIPZERO:+ code += 2 + GET(code, 2) + LINK_SIZE;+ break;++ case OP_COND:+ case OP_SCOND:+ if (code[1+LINK_SIZE] != OP_FALSE || /* Not DEFINE */+ code[GET(code, 1)] != OP_KET) /* More than one branch */+ return code;+ code += GET(code, 1) + 1 + LINK_SIZE;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ code += code[1] + PRIV(OP_lengths)[*code];+ break;++ default:+ return code;+ }+ }+/* Control never reaches here */+}++++#ifdef SUPPORT_UNICODE+/*************************************************+* Get othercase range *+*************************************************/++/* This function is passed the start and end of a class range in UCP mode. For+single characters the range may be just one character long. The function+searches up the characters, looking for ranges of characters in the "other"+case. Each call returns the next one, updating the start address. A character+with multiple other cases is returned on its own with a special return value.++Arguments:+ cptr points to starting character value; updated+ d end value+ ocptr where to put start of othercase range+ odptr where to put end of othercase range+ restricted TRUE if caseless restriction applies++Yield: -1 when no more+ 0 when a range is returned+ >0 the CASESET offset for char with multiple other cases;+ for this return, *ocptr contains the original+*/++static int+get_othercase_range(uint32_t *cptr, uint32_t d, uint32_t *ocptr,+ uint32_t *odptr, BOOL restricted)+{+uint32_t c, othercase, next;+unsigned int co;++/* Find the first character that has an other case. If it has multiple other+cases, return its case offset value. When CASELESS_RESTRICT is set, ignore the+multi-case entries that begin with ASCII values. In 32-bit mode, a value+greater than the Unicode maximum ends the range. */++for (c = *cptr; c <= d; c++)+ {+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c > MAX_UTF_CODE_POINT) return -1;+#endif+ if ((co = UCD_CASESET(c)) != 0 &&+ (!restricted || PRIV(ucd_caseless_sets)[co] > 127))+ {+ *ocptr = c++; /* Character that has the set */+ *cptr = c; /* Rest of input range */+ return (int)co;+ }++ /* This is not a valid multiple-case character. Check that the single other+ case is different to the original. We don't need to check "restricted" here+ because the non-ASCII characters with multiple cases that include an ASCII+ character don't have a different "othercase". */++ if ((othercase = UCD_OTHERCASE(c)) != c) break;+ }++if (c > d) return -1; /* Reached end of range */++/* Found a character that has a single other case. Search for the end of the+range, which is either the end of the input range, or a character that has zero+or more than one other cases. */++*ocptr = othercase;+next = othercase + 1;++for (++c; c <= d; c++)+ {+ if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break;+ next++;+ }++*odptr = next - 1; /* End of othercase range */+*cptr = c; /* Rest of input range */+return 0;+}+#endif /* SUPPORT_UNICODE */++++/*************************************************+* Add a character or range to a class (internal) *+*************************************************/++/* This function packages up the logic of adding a character or range of+characters to a class. The character values in the arguments will be within the+valid values for the current mode (8-bit, 16-bit, UTF, etc). This function is+called only from within the "add to class" group of functions, some of which+are recursive and mutually recursive. The external entry point is+add_to_class().++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options bits+ xoptions the extra options bits+ cb compile data+ start start of range character+ end end of range character++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr,+ uint32_t options, uint32_t xoptions, compile_block *cb, uint32_t start,+ uint32_t end)+{+uint32_t c;+uint32_t classbits_end = (end <= 0xff ? end : 0xff);+unsigned int n8 = 0;++/* If caseless matching is required, scan the range and process alternate+cases. In Unicode, there are 8-bit characters that have alternate cases that+are greater than 255 and vice-versa (though these may be ignored if caseless+restriction is in force). Sometimes we can just extend the original range. */++if ((options & PCRE2_CASELESS) != 0)+ {+#ifdef SUPPORT_UNICODE+ if ((options & (PCRE2_UTF|PCRE2_UCP)) != 0)+ {+ int rc;+ uint32_t oc, od;++ options &= ~PCRE2_CASELESS; /* Remove for recursive calls */+ c = start;++ while ((rc = get_othercase_range(&c, end, &oc, &od,+ (xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0)) >= 0)+ {+ /* Handle a single character that has more than one other case. */++ if (rc > 0) n8 += add_list_to_class_internal(classbits, uchardptr,+ options, xoptions, cb, PRIV(ucd_caseless_sets) + rc, oc);++ /* Do nothing if the other case range is within the original range. */++ else if (oc >= cb->class_range_start && od <= cb->class_range_end)+ continue;++ /* Extend the original range if there is overlap, noting that if oc < c,+ we can't have od > end because a subrange is always shorter than the+ basic range. Otherwise, use a recursive call to add the additional range.+ */++ else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */+ else if (od > end && oc <= end + 1)+ {+ end = od; /* Extend upwards */+ if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff);+ }+ else n8 += add_to_class_internal(classbits, uchardptr, options, xoptions,+ cb, oc, od);+ }+ }+ else+#else+ (void)xoptions; /* Avoid compiler warning */+#endif /* SUPPORT_UNICODE */++ /* Not UTF mode */++ for (c = start; c <= classbits_end; c++)+ {+ SETBIT(classbits, cb->fcc[c]);+ n8++;+ }+ }++/* Now handle the originally supplied range. Adjust the final value according+to the bit length - this means that the same lists of (e.g.) horizontal spaces+can be used in all cases. */++if ((options & PCRE2_UTF) == 0 && end > MAX_NON_UTF_CHAR)+ end = MAX_NON_UTF_CHAR;++if (start > cb->class_range_start && end < cb->class_range_end) return n8;++/* Use the bitmap for characters < 256. Otherwise use extra data.*/++for (c = start; c <= classbits_end; c++)+ {+ /* Regardless of start, c will always be <= 255. */+ SETBIT(classbits, c);+ n8++;+ }++#ifdef SUPPORT_WIDE_CHARS+if (start <= 0xff) start = 0xff + 1;++if (end >= start)+ {+ PCRE2_UCHAR *uchardata = *uchardptr;++#ifdef SUPPORT_UNICODE+ if ((options & PCRE2_UTF) != 0)+ {+ if (start < end)+ {+ *uchardata++ = XCL_RANGE;+ uchardata += PRIV(ord2utf)(start, uchardata);+ uchardata += PRIV(ord2utf)(end, uchardata);+ }+ else if (start == end)+ {+ *uchardata++ = XCL_SINGLE;+ uchardata += PRIV(ord2utf)(start, uchardata);+ }+ }+ else+#endif /* SUPPORT_UNICODE */++ /* Without UTF support, character values are constrained by the bit length,+ and can only be > 256 for 16-bit and 32-bit libraries. */++#if PCRE2_CODE_UNIT_WIDTH == 8+ {}+#else+ if (start < end)+ {+ *uchardata++ = XCL_RANGE;+ *uchardata++ = start;+ *uchardata++ = end;+ }+ else if (start == end)+ {+ *uchardata++ = XCL_SINGLE;+ *uchardata++ = start;+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ *uchardptr = uchardata; /* Updata extra data pointer */+ }+#else /* SUPPORT_WIDE_CHARS */+ (void)uchardptr; /* Avoid compiler warning */+#endif /* SUPPORT_WIDE_CHARS */++return n8; /* Number of 8-bit characters */+}++++#ifdef SUPPORT_UNICODE+/*************************************************+* Add a list of characters to a class (internal) *+*************************************************/++/* This function is used for adding a list of case-equivalent characters to a+class when in UTF mode. This function is called only from within+add_to_class_internal(), with which it is mutually recursive.++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options bits+ xoptions the extra options bits+ cb contains pointers to tables etc.+ p points to row of 32-bit values, terminated by NOTACHAR+ except character to omit; this is used when adding lists of+ case-equivalent characters to avoid including the one we+ already know about++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_list_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr,+ uint32_t options, uint32_t xoptions, compile_block *cb, const uint32_t *p,+ unsigned int except)+{+unsigned int n8 = 0;+while (p[0] < NOTACHAR)+ {+ unsigned int n = 0;+ if (p[0] != except)+ {+ while(p[n+1] == p[0] + n + 1) n++;+ n8 += add_to_class_internal(classbits, uchardptr, options, xoptions, cb,+ p[0], p[n]);+ }+ p += n + 1;+ }+return n8;+}+#endif++++/*************************************************+* External entry point for add range to class *+*************************************************/++/* This function sets the overall range so that the internal functions can try+to avoid duplication when handling case-independence.++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options bits+ xoptions the extra options bits+ cb compile data+ start start of range character+ end end of range character++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,+ uint32_t xoptions, compile_block *cb, uint32_t start, uint32_t end)+{+cb->class_range_start = start;+cb->class_range_end = end;+return add_to_class_internal(classbits, uchardptr, options, xoptions, cb,+ start, end);+}+++/*************************************************+* External entry point for add list to class *+*************************************************/++/* This function is used for adding a list of horizontal or vertical whitespace+characters to a class. The list must be in order so that ranges of characters+can be detected and handled appropriately. This function sets the overall range+so that the internal functions can try to avoid duplication when handling+case-independence.++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options bits+ xoptions the extra options bits+ cb contains pointers to tables etc.+ p points to row of 32-bit values, terminated by NOTACHAR+ except character to omit; this is used when adding lists of+ case-equivalent characters to avoid including the one we+ already know about++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,+ uint32_t xoptions, compile_block *cb, const uint32_t *p, unsigned int except)+{+unsigned int n8 = 0;+while (p[0] < NOTACHAR)+ {+ unsigned int n = 0;+ if (p[0] != except)+ {+ while(p[n+1] == p[0] + n + 1) n++;+ cb->class_range_start = p[0];+ cb->class_range_end = p[n];+ n8 += add_to_class_internal(classbits, uchardptr, options, xoptions, cb,+ p[0], p[n]);+ }+ p += n + 1;+ }+return n8;+}++++/*************************************************+* Add characters not in a list to a class *+*************************************************/++/* This function is used for adding the complement of a list of horizontal or+vertical whitespace to a class. The list must be in order.++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options bits+ xoptions the extra options bits+ cb contains pointers to tables etc.+ p points to row of 32-bit values, terminated by NOTACHAR++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_not_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr,+ uint32_t options, uint32_t xoptions, compile_block *cb, const uint32_t *p)+{+BOOL utf = (options & PCRE2_UTF) != 0;+unsigned int n8 = 0;+if (p[0] > 0)+ n8 += add_to_class(classbits, uchardptr, options, xoptions, cb, 0, p[0] - 1);+while (p[0] < NOTACHAR)+ {+ while (p[1] == p[0] + 1) p++;+ n8 += add_to_class(classbits, uchardptr, options, xoptions, cb, p[0] + 1,+ (p[1] == NOTACHAR) ? (utf ? 0x10ffffu : 0xffffffffu) : p[1] - 1);+ p++;+ }+return n8;+}++++/*************************************************+* Find details of duplicate group names *+*************************************************/++/* This is called from compile_branch() when it needs to know the index and+count of duplicates in the names table when processing named backreferences,+either directly, or as conditions.++Arguments:+ name points to the name+ length the length of the name+ indexptr where to put the index+ countptr where to put the count of duplicates+ errorcodeptr where to put an error code+ cb the compile block++Returns: TRUE if OK, FALSE if not, error code set+*/++static BOOL+find_dupname_details(PCRE2_SPTR name, uint32_t length, int *indexptr,+ int *countptr, int *errorcodeptr, compile_block *cb)+{+uint32_t i, groupnumber;+int count;+PCRE2_UCHAR *slot = cb->name_table;++/* Find the first entry in the table */++for (i = 0; i < cb->names_found; i++)+ {+ if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) == 0 &&+ slot[IMM2_SIZE+length] == 0) break;+ slot += cb->name_entry_size;+ }++/* This should not occur, because this function is called only when we know we+have duplicate names. Give an internal error. */++if (i >= cb->names_found)+ {+ *errorcodeptr = ERR53;+ cb->erroroffset = name - cb->start_pattern;+ return FALSE;+ }++/* Record the index and then see how many duplicates there are, updating the+backref map and maximum back reference as we do. */++*indexptr = i;+count = 0;++for (;;)+ {+ count++;+ groupnumber = GET2(slot,0);+ cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;+ if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;+ if (++i >= cb->names_found) break;+ slot += cb->name_entry_size;+ if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) != 0 ||+ (slot+IMM2_SIZE)[length] != 0) break;+ }++*countptr = count;+return TRUE;+}++++/*************************************************+* Compile one branch *+*************************************************/++/* Scan the parsed pattern, compiling it into the a vector of PCRE2_UCHAR. If+the options are changed during the branch, the pointer is used to change the+external options bits. This function is used during the pre-compile phase when+we are trying to find out the amount of memory needed, as well as during the+real compile phase. The value of lengthptr distinguishes the two phases.++Arguments:+ optionsptr pointer to the option bits+ xoptionsptr pointer to the extra option bits+ codeptr points to the pointer to the current code point+ pptrptr points to the current parsed pattern pointer+ errorcodeptr points to error code variable+ firstcuptr place to put the first required code unit+ firstcuflagsptr place to put the first code unit flags+ reqcuptr place to put the last required code unit+ reqcuflagsptr place to put the last required code unit flags+ bcptr points to current branch chain+ open_caps points to current capitem+ cb contains pointers to tables etc.+ lengthptr NULL during the real compile phase+ points to length accumulator during pre-compile phase++Returns: 0 There's been an error, *errorcodeptr is non-zero+ +1 Success, this branch must match at least one character+ -1 Success, this branch may match an empty string+*/++static int+compile_branch(uint32_t *optionsptr, uint32_t *xoptionsptr,+ PCRE2_UCHAR **codeptr, uint32_t **pptrptr, int *errorcodeptr,+ uint32_t *firstcuptr, uint32_t *firstcuflagsptr, uint32_t *reqcuptr,+ uint32_t *reqcuflagsptr, branch_chain *bcptr, open_capitem *open_caps,+ compile_block *cb, PCRE2_SIZE *lengthptr)+{+int bravalue = 0;+int okreturn = -1;+int group_return = 0;+uint32_t repeat_min = 0, repeat_max = 0; /* To please picky compilers */+uint32_t greedy_default, greedy_non_default;+uint32_t repeat_type, op_type;+uint32_t options = *optionsptr; /* May change dynamically */+uint32_t xoptions = *xoptionsptr; /* May change dynamically */+uint32_t firstcu, reqcu;+uint32_t zeroreqcu, zerofirstcu;+uint32_t escape;+uint32_t *pptr = *pptrptr;+uint32_t meta, meta_arg;+uint32_t firstcuflags, reqcuflags;+uint32_t zeroreqcuflags, zerofirstcuflags;+uint32_t req_caseopt, reqvary, tempreqvary;+PCRE2_SIZE offset = 0;+PCRE2_SIZE length_prevgroup = 0;+PCRE2_UCHAR *code = *codeptr;+PCRE2_UCHAR *last_code = code;+PCRE2_UCHAR *orig_code = code;+PCRE2_UCHAR *tempcode;+PCRE2_UCHAR *previous = NULL;+PCRE2_UCHAR op_previous;+BOOL groupsetfirstcu = FALSE;+BOOL had_accept = FALSE;+BOOL matched_char = FALSE;+BOOL previous_matched_char = FALSE;+BOOL reset_caseful = FALSE;+const uint8_t *cbits = cb->cbits;+uint8_t classbits[32];++/* We can fish out the UTF setting once and for all into a BOOL, but we must+not do this for other options (e.g. PCRE2_EXTENDED) that may change dynamically+as we process the pattern. */++#ifdef SUPPORT_UNICODE+BOOL utf = (options & PCRE2_UTF) != 0;+BOOL ucp = (options & PCRE2_UCP) != 0;+#else /* No Unicode support */+BOOL utf = FALSE;+#endif++/* Helper variables for OP_XCLASS opcode (for characters > 255). We define+class_uchardata always so that it can be passed to add_to_class() always,+though it will not be used in non-UTF 8-bit cases. This avoids having to supply+alternative calls for the different cases. */++PCRE2_UCHAR *class_uchardata;+#ifdef SUPPORT_WIDE_CHARS+BOOL xclass;+PCRE2_UCHAR *class_uchardata_base;+#endif++/* Set up the default and non-default settings for greediness */++greedy_default = ((options & PCRE2_UNGREEDY) != 0);+greedy_non_default = greedy_default ^ 1;++/* Initialize no first unit, no required unit. REQ_UNSET means "no char+matching encountered yet". It gets changed to REQ_NONE if we hit something that+matches a non-fixed first unit; reqcu just remains unset if we never find one.++When we hit a repeat whose minimum is zero, we may have to adjust these values+to take the zero repeat into account. This is implemented by setting them to+zerofirstcu and zeroreqcu when such a repeat is encountered. The individual+item types that can be repeated set these backoff variables appropriately. */++firstcu = reqcu = zerofirstcu = zeroreqcu = 0;+firstcuflags = reqcuflags = zerofirstcuflags = zeroreqcuflags = REQ_UNSET;++/* The variable req_caseopt contains either the REQ_CASELESS bit or zero,+according to the current setting of the caseless flag. The REQ_CASELESS value+leaves the lower 28 bit empty. It is added into the firstcu or reqcu variables+to record the case status of the value. This is used only for ASCII characters.+*/++req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0;++/* Switch on next META item until the end of the branch */++for (;; pptr++)+ {+#ifdef SUPPORT_WIDE_CHARS+ BOOL xclass_has_prop;+#endif+ BOOL negate_class;+ BOOL should_flip_negation;+ BOOL match_all_or_no_wide_chars;+ BOOL possessive_quantifier;+ BOOL note_group_empty;+ int class_has_8bitchar;+ uint32_t mclength;+ uint32_t skipunits;+ uint32_t subreqcu, subfirstcu;+ uint32_t groupnumber;+ uint32_t verbarglen, verbculen;+ uint32_t subreqcuflags, subfirstcuflags;+ open_capitem *oc;+ PCRE2_UCHAR mcbuffer[8];++ /* Get next META item in the pattern and its potential argument. */++ meta = META_CODE(*pptr);+ meta_arg = META_DATA(*pptr);++ /* If we are in the pre-compile phase, accumulate the length used for the+ previous cycle of this loop, unless the next item is a quantifier. */++ if (lengthptr != NULL)+ {+ if (code > cb->start_workspace + cb->workspace_size -+ WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */+ {+ *errorcodeptr = (code >= cb->start_workspace + cb->workspace_size)?+ ERR52 : ERR86;+ return 0;+ }++ /* There is at least one situation where code goes backwards: this is the+ case of a zero quantifier after a class (e.g. [ab]{0}). When the quantifier+ is processed, the whole class is eliminated. However, it is created first,+ so we have to allow memory for it. Therefore, don't ever reduce the length+ at this point. */++ if (code < last_code) code = last_code;++ /* If the next thing is not a quantifier, we add the length of the previous+ item into the total, and reset the code pointer to the start of the+ workspace. Otherwise leave the previous item available to be quantified. */++ if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)+ {+ if (OFLOW_MAX - *lengthptr < (PCRE2_SIZE)(code - orig_code))+ {+ *errorcodeptr = ERR20; /* Integer overflow */+ return 0;+ }+ *lengthptr += (PCRE2_SIZE)(code - orig_code);+ if (*lengthptr > MAX_PATTERN_SIZE)+ {+ *errorcodeptr = ERR20; /* Pattern is too large */+ return 0;+ }+ code = orig_code;+ }++ /* Remember where this code item starts so we can catch the "backwards"+ case above next time round. */++ last_code = code;+ }++ /* Process the next parsed pattern item. If it is not a quantifier, remember+ where it starts so that it can be quantified when a quantifier follows.+ Checking for the legality of quantifiers happens in parse_regex(), except for+ a quantifier after an assertion that is a condition. */++ if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)+ {+ previous = code;+ if (matched_char && !had_accept) okreturn = 1;+ }++ previous_matched_char = matched_char;+ matched_char = FALSE;+ note_group_empty = FALSE;+ skipunits = 0; /* Default value for most subgroups */++ switch(meta)+ {+ /* ===================================================================*/+ /* The branch terminates at pattern end or | or ) */++ case META_END:+ case META_ALT:+ case META_KET:+ *firstcuptr = firstcu;+ *firstcuflagsptr = firstcuflags;+ *reqcuptr = reqcu;+ *reqcuflagsptr = reqcuflags;+ *codeptr = code;+ *pptrptr = pptr;+ return okreturn;+++ /* ===================================================================*/+ /* Handle single-character metacharacters. In multiline mode, ^ disables+ the setting of any following char as a first character. */++ case META_CIRCUMFLEX:+ if ((options & PCRE2_MULTILINE) != 0)+ {+ if (firstcuflags == REQ_UNSET)+ zerofirstcuflags = firstcuflags = REQ_NONE;+ *code++ = OP_CIRCM;+ }+ else *code++ = OP_CIRC;+ break;++ case META_DOLLAR:+ *code++ = ((options & PCRE2_MULTILINE) != 0)? OP_DOLLM : OP_DOLL;+ break;++ /* There can never be a first char if '.' is first, whatever happens about+ repeats. The value of reqcu doesn't change either. */++ case META_DOT:+ matched_char = TRUE;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;+ *code++ = ((options & PCRE2_DOTALL) != 0)? OP_ALLANY: OP_ANY;+ break;+++ /* ===================================================================*/+ /* Empty character classes are allowed if PCRE2_ALLOW_EMPTY_CLASS is set.+ Otherwise, an initial ']' is taken as a data character. When empty classes+ are allowed, [] must always fail, so generate OP_FAIL, whereas [^] must+ match any character, so generate OP_ALLANY. */++ case META_CLASS_EMPTY:+ case META_CLASS_EMPTY_NOT:+ matched_char = TRUE;+ *code++ = (meta == META_CLASS_EMPTY_NOT)? OP_ALLANY : OP_FAIL;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ break;+++ /* ===================================================================*/+ /* Non-empty character class. If the included characters are all < 256, we+ build a 32-byte bitmap of the permitted characters, except in the special+ case where there is only one such character. For negated classes, we build+ the map as usual, then invert it at the end. However, we use a different+ opcode so that data characters > 255 can be handled correctly.++ If the class contains characters outside the 0-255 range, a different+ opcode is compiled. It may optionally have a bit map for characters < 256,+ but those above are explicitly listed afterwards. A flag code unit tells+ whether the bitmap is present, and whether this is a negated class or+ not. */++ case META_CLASS_NOT:+ case META_CLASS:+ matched_char = TRUE;+ negate_class = meta == META_CLASS_NOT;++ /* We can optimize the case of a single character in a class by generating+ OP_CHAR or OP_CHARI if it's positive, or OP_NOT or OP_NOTI if it's+ negative. In the negative case there can be no first char if this item is+ first, whatever repeat count may follow. In the case of reqcu, save the+ previous value for reinstating. */++ /* NOTE: at present this optimization is not effective if the only+ character in a class in 32-bit, non-UCP mode has its top bit set. */++ if (pptr[1] < META_END && pptr[2] == META_CLASS_END)+ {+#ifdef SUPPORT_UNICODE+ uint32_t d;+#endif+ uint32_t c = pptr[1];++ pptr += 2; /* Move on to class end */+ if (meta == META_CLASS) /* A positive one-char class can be */+ { /* handled as a normal literal character. */+ meta = c; /* Set up the character */+ goto NORMAL_CHAR_SET;+ }++ /* Handle a negative one-character class */++ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;++ /* For caseless UTF or UCP mode, check whether this character has more+ than one other case. If so, generate a special OP_NOTPROP item instead of+ OP_NOTI. When restricted by PCRE2_EXTRA_CASELESS_RESTRICT, ignore any+ caseless set that starts with an ASCII character. */++#ifdef SUPPORT_UNICODE+ if ((utf||ucp) && (options & PCRE2_CASELESS) != 0 &&+ (d = UCD_CASESET(c)) != 0 &&+ ((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) == 0 ||+ PRIV(ucd_caseless_sets)[d] > 127))+ {+ *code++ = OP_NOTPROP;+ *code++ = PT_CLIST;+ *code++ = d;+ break; /* We are finished with this class */+ }+#endif+ /* Char has only one other (usable) case, or UCP not available */++ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_NOTI: OP_NOT;+ code += PUTCHAR(c, code);+ break; /* We are finished with this class */+ } /* End of 1-char optimization */++ /* Handle character classes that contain more than just one literal+ character. If there are exactly two characters in a positive class, see if+ they are case partners. This can be optimized to generate a caseless single+ character match (which also sets first/required code units if relevant).+ When casing restrictions apply, ignore a caseless set if both characters+ are ASCII. */++ if (meta == META_CLASS && pptr[1] < META_END && pptr[2] < META_END &&+ pptr[3] == META_CLASS_END)+ {+ uint32_t c = pptr[1];++#ifdef SUPPORT_UNICODE+ if (UCD_CASESET(c) == 0 ||+ ((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0 &&+ c < 128 && pptr[2] < 128))+#endif+ {+ uint32_t d;++#ifdef SUPPORT_UNICODE+ if ((utf || ucp) && c > 127) d = UCD_OTHERCASE(c); else+#endif+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ if (c > 255) d = c; else+#endif+ d = TABLE_GET(c, cb->fcc, c);+ }++ if (c != d && pptr[2] == d)+ {+ pptr += 3; /* Move on to class end */+ meta = c;+ if ((options & PCRE2_CASELESS) == 0)+ {+ reset_caseful = TRUE;+ options |= PCRE2_CASELESS;+ req_caseopt = REQ_CASELESS;+ }+ goto CLASS_CASELESS_CHAR;+ }+ }+ }++ /* If a non-extended class contains a negative special such as \S, we need+ to flip the negation flag at the end, so that support for characters > 255+ works correctly (they are all included in the class). An extended class may+ need to insert specific matching or non-matching code for wide characters.+ */++ should_flip_negation = match_all_or_no_wide_chars = FALSE;++ /* Extended class (xclass) will be used when characters > 255+ might match. */++#ifdef SUPPORT_WIDE_CHARS+ xclass = FALSE;+ class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */+ class_uchardata_base = class_uchardata; /* Save the start */+#endif++ /* For optimization purposes, we track some properties of the class:+ class_has_8bitchar will be non-zero if the class contains at least one+ character with a code point less than 256; xclass_has_prop will be TRUE if+ Unicode property checks are present in the class. */++ class_has_8bitchar = 0;+#ifdef SUPPORT_WIDE_CHARS+ xclass_has_prop = FALSE;+#endif++ /* Initialize the 256-bit (32-byte) bit map to all zeros. We build the map+ in a temporary bit of memory, in case the class contains fewer than two+ 8-bit characters because in that case the compiled code doesn't use the bit+ map. */++ memset(classbits, 0, 32 * sizeof(uint8_t));++ /* Process items until META_CLASS_END is reached. */++ while ((meta = *(++pptr)) != META_CLASS_END)+ {+ /* Handle POSIX classes such as [:alpha:] etc. */++ if (meta == META_POSIX || meta == META_POSIX_NEG)+ {+ BOOL local_negate = (meta == META_POSIX_NEG);+ int posix_class = *(++pptr);+ int taboffset, tabopt;+ uint8_t pbits[32];++ should_flip_negation = local_negate; /* Note negative special */++ /* If matching is caseless, upper and lower are converted to alpha.+ This relies on the fact that the class table starts with alpha,+ lower, upper as the first 3 entries. */++ if ((options & PCRE2_CASELESS) != 0 && posix_class <= 2)+ posix_class = 0;++ /* When PCRE2_UCP is set, some of the POSIX classes are converted to+ different escape sequences that use Unicode properties \p or \P.+ Others that are not available via \p or \P have to generate+ XCL_PROP/XCL_NOTPROP directly, which is done here. */++#ifdef SUPPORT_UNICODE+ if ((options & PCRE2_UCP) != 0 &&+ (xoptions & PCRE2_EXTRA_ASCII_POSIX) == 0)+ {+ switch(posix_class)+ {+ case PC_GRAPH:+ case PC_PRINT:+ case PC_PUNCT:+ *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;+ *class_uchardata++ = (PCRE2_UCHAR)+ ((posix_class == PC_GRAPH)? PT_PXGRAPH :+ (posix_class == PC_PRINT)? PT_PXPRINT : PT_PXPUNCT);+ *class_uchardata++ = 0;+ xclass_has_prop = TRUE;+ goto CONTINUE_CLASS;++ /* For the other POSIX classes (ex: ascii) we are going to+ fall through to the non-UCP case and build a bit map for+ characters with code points less than 256. However, if we are in+ a negated POSIX class, characters with code points greater than+ 255 must either all match or all not match, depending on whether+ the whole class is not or is negated. For example, for+ [[:^ascii:]... they must all match, whereas for [^[:^ascii:]...+ they must not.++ In the special case where there are no xclass items, this is+ automatically handled by the use of OP_CLASS or OP_NCLASS, but an+ explicit range is needed for OP_XCLASS. Setting a flag here+ causes the range to be generated later when it is known that+ OP_XCLASS is required. In the 8-bit library this is relevant only in+ utf mode, since no wide characters can exist otherwise. */++ default:+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (utf)+#endif+ match_all_or_no_wide_chars |= local_negate;+ break;+ }+ }+#endif /* SUPPORT_UNICODE */++ /* In the non-UCP case, or when UCP makes no difference, we build the+ bit map for the POSIX class in a chunk of local store because we may+ be adding and subtracting from it, and we don't want to subtract bits+ that may be in the main map already. At the end we or the result into+ the bit map that is being built. */++ posix_class *= 3;++ /* Copy in the first table (always present) */++ memcpy(pbits, cbits + posix_class_maps[posix_class],+ 32 * sizeof(uint8_t));++ /* If there is a second table, add or remove it as required. */++ taboffset = posix_class_maps[posix_class + 1];+ tabopt = posix_class_maps[posix_class + 2];++ if (taboffset >= 0)+ {+ if (tabopt >= 0)+ for (int i = 0; i < 32; i++) pbits[i] |= cbits[(int)i + taboffset];+ else+ for (int i = 0; i < 32; i++) pbits[i] &= ~cbits[(int)i + taboffset];+ }++ /* Now see if we need to remove any special characters. An option+ value of 1 removes vertical space and 2 removes underscore. */++ if (tabopt < 0) tabopt = -tabopt;+ if (tabopt == 1) pbits[1] &= ~0x3c;+ else if (tabopt == 2) pbits[11] &= 0x7f;++ /* Add the POSIX table or its complement into the main table that is+ being built and we are done. */++ if (local_negate)+ for (int i = 0; i < 32; i++) classbits[i] |= (uint8_t)(~pbits[i]);+ else+ for (int i = 0; i < 32; i++) classbits[i] |= pbits[i];++ /* Every class contains at least one < 256 character. */++ class_has_8bitchar = 1;+ goto CONTINUE_CLASS; /* End of POSIX handling */+ }++ /* Other than POSIX classes, the only items we should encounter are+ \d-type escapes and literal characters (possibly as ranges). */++ if (meta == META_BIGVALUE)+ {+ meta = *(++pptr);+ goto CLASS_LITERAL;+ }++ /* Any other non-literal must be an escape */++ if (meta >= META_END)+ {+ if (META_CODE(meta) != META_ESCAPE)+ {+#ifdef DEBUG_SHOW_PARSED+ fprintf(stderr, "** Unrecognized parsed pattern item 0x%.8x "+ "in character class\n", meta);+#endif+ *errorcodeptr = ERR89; /* Internal error - unrecognized. */+ return 0;+ }+ escape = META_DATA(meta);++ /* Every class contains at least one < 256 character. */++ class_has_8bitchar++;++ switch(escape)+ {+ case ESC_d:+ for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_digit];+ break;++ case ESC_D:+ should_flip_negation = TRUE;+ for (int i = 0; i < 32; i++)+ classbits[i] |= (uint8_t)(~cbits[i+cbit_digit]);+ break;++ case ESC_w:+ for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_word];+ break;++ case ESC_W:+ should_flip_negation = TRUE;+ for (int i = 0; i < 32; i++)+ classbits[i] |= (uint8_t)(~cbits[i+cbit_word]);+ break;++ /* Perl 5.004 onwards omitted VT from \s, but restored it at Perl+ 5.18. Before PCRE 8.34, we had to preserve the VT bit if it was+ previously set by something earlier in the character class.+ Luckily, the value of CHAR_VT is 0x0b in both ASCII and EBCDIC, so+ we could just adjust the appropriate bit. From PCRE 8.34 we no+ longer treat \s and \S specially. */++ case ESC_s:+ for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_space];+ break;++ case ESC_S:+ should_flip_negation = TRUE;+ for (int i = 0; i < 32; i++)+ classbits[i] |= (uint8_t)(~cbits[i+cbit_space]);+ break;++ /* When adding the horizontal or vertical space lists to a class, or+ their complements, disable PCRE2_CASELESS, because it justs wastes+ time, and in the "not-x" UTF cases can create unwanted duplicates in+ the XCLASS list (provoked by characters that have more than one other+ case and by both cases being in the same "not-x" sublist). */++ case ESC_h:+ (void)add_list_to_class(classbits, &class_uchardata,+ options & ~PCRE2_CASELESS, xoptions, cb, PRIV(hspace_list),+ NOTACHAR);+ break;++ case ESC_H:+ (void)add_not_list_to_class(classbits, &class_uchardata,+ options & ~PCRE2_CASELESS, xoptions, cb, PRIV(hspace_list));+ break;++ case ESC_v:+ (void)add_list_to_class(classbits, &class_uchardata,+ options & ~PCRE2_CASELESS, xoptions, cb, PRIV(vspace_list),+ NOTACHAR);+ break;++ case ESC_V:+ (void)add_not_list_to_class(classbits, &class_uchardata,+ options & ~PCRE2_CASELESS, xoptions, cb, PRIV(vspace_list));+ break;++ /* If Unicode is not supported, \P and \p are not allowed and are+ faulted at parse time, so will never appear here. */++#ifdef SUPPORT_UNICODE+ case ESC_p:+ case ESC_P:+ {+ uint32_t ptype = *(++pptr) >> 16;+ uint32_t pdata = *pptr & 0xffff;+ *class_uchardata++ = (escape == ESC_p)? XCL_PROP : XCL_NOTPROP;+ *class_uchardata++ = ptype;+ *class_uchardata++ = pdata;+ xclass_has_prop = TRUE;+ class_has_8bitchar--; /* Undo! */+ }+ break;+#endif+ }++ goto CONTINUE_CLASS;+ } /* End handling \d-type escapes */++ /* A literal character may be followed by a range meta. At parse time+ there are checks for out-of-order characters, for ranges where the two+ characters are equal, and for hyphens that cannot indicate a range. At+ this point, therefore, no checking is needed. */++ else+ {+ uint32_t c, d;++ CLASS_LITERAL:+ c = d = meta;++ /* Remember if \r or \n were explicitly used */++ if (c == CHAR_CR || c == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;++ /* Process a character range */++ if (pptr[1] == META_RANGE_LITERAL || pptr[1] == META_RANGE_ESCAPED)+ {+#ifdef EBCDIC+ BOOL range_is_literal = (pptr[1] == META_RANGE_LITERAL);+#endif+ pptr += 2;+ d = *pptr;+ if (d == META_BIGVALUE) d = *(++pptr);++ /* Remember an explicit \r or \n, and add the range to the class. */++ if (d == CHAR_CR || d == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;++ /* In an EBCDIC environment, Perl treats alphabetic ranges specially+ because there are holes in the encoding, and simply using the range+ A-Z (for example) would include the characters in the holes. This+ applies only to literal ranges; [\xC1-\xE9] is different to [A-Z]. */++#ifdef EBCDIC+ if (range_is_literal &&+ (cb->ctypes[c] & ctype_letter) != 0 &&+ (cb->ctypes[d] & ctype_letter) != 0 &&+ (c <= CHAR_z) == (d <= CHAR_z))+ {+ uint32_t uc = (d <= CHAR_z)? 0 : 64;+ uint32_t C = c - uc;+ uint32_t D = d - uc;++ if (C <= CHAR_i)+ {+ class_has_8bitchar +=+ add_to_class(classbits, &class_uchardata, options, xoptions,+ cb, C + uc, ((D < CHAR_i)? D : CHAR_i) + uc);+ C = CHAR_j;+ }++ if (C <= D && C <= CHAR_r)+ {+ class_has_8bitchar +=+ add_to_class(classbits, &class_uchardata, options, xoptions,+ cb, C + uc, ((D < CHAR_r)? D : CHAR_r) + uc);+ C = CHAR_s;+ }++ if (C <= D)+ {+ class_has_8bitchar +=+ add_to_class(classbits, &class_uchardata, options, xoptions,+ cb, C + uc, D + uc);+ }+ }+ else+#endif+ /* Not an EBCDIC special range */++ class_has_8bitchar += add_to_class(classbits, &class_uchardata,+ options, xoptions, cb, c, d);+ goto CONTINUE_CLASS; /* Go get the next char in the class */+ } /* End of range handling */+++ /* Handle a single character. */++ class_has_8bitchar +=+ add_to_class(classbits, &class_uchardata, options, xoptions, cb,+ meta, meta);+ }++ /* Continue to the next item in the class. */++ CONTINUE_CLASS:++#ifdef SUPPORT_WIDE_CHARS+ /* If any wide characters or Unicode properties have been encountered,+ set xclass = TRUE. Then, in the pre-compile phase, accumulate the length+ of the extra data and reset the pointer. This is so that very large+ classes that contain a zillion wide characters or Unicode property tests+ do not overwrite the workspace (which is on the stack). */++ if (class_uchardata > class_uchardata_base)+ {+ xclass = TRUE;+ if (lengthptr != NULL)+ {+ *lengthptr += class_uchardata - class_uchardata_base;+ class_uchardata = class_uchardata_base;+ }+ }+#endif++ continue; /* Needed to avoid error when not supporting wide chars */+ } /* End of main class-processing loop */++ /* If this class is the first thing in the branch, there can be no first+ char setting, whatever the repeat count. Any reqcu setting must remain+ unchanged after any kind of repeat. */++ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;++ /* If there are characters with values > 255, or Unicode property settings+ (\p or \P), we have to compile an extended class, with its own opcode,+ unless there were no property settings and there was a negated special such+ as \S in the class, and PCRE2_UCP is not set, because in that case all+ characters > 255 are in or not in the class, so any that were explicitly+ given as well can be ignored.++ In the UCP case, if certain negated POSIX classes (ex: [:^ascii:]) were+ were present in a class, we either have to match or not match all wide+ characters (depending on whether the whole class is or is not negated).+ This requirement is indicated by match_all_or_no_wide_chars being true.+ We do this by including an explicit range, which works in both cases.+ This applies only in UTF and 16-bit and 32-bit non-UTF modes, since there+ cannot be any wide characters in 8-bit non-UTF mode.++ When there *are* properties in a positive UTF-8 or any 16-bit or 32_bit+ class where \S etc is present without PCRE2_UCP, causing an extended class+ to be compiled, we make sure that all characters > 255 are included by+ forcing match_all_or_no_wide_chars to be true.++ If, when generating an xclass, there are no characters < 256, we can omit+ the bitmap in the actual compiled code. */++#ifdef SUPPORT_WIDE_CHARS /* Defined for 16/32 bits, or 8-bit with Unicode */+ if (xclass && (+#ifdef SUPPORT_UNICODE+ (options & PCRE2_UCP) != 0 ||+#endif+ xclass_has_prop || !should_flip_negation))+ {+ if (match_all_or_no_wide_chars || (+#if PCRE2_CODE_UNIT_WIDTH == 8+ utf &&+#endif+ should_flip_negation && !negate_class && (options & PCRE2_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)(MAX_UTF_CODE_POINT, class_uchardata);+ }+ else /* Can only happen for the 16-bit & 32-bit libraries */+ {+#if PCRE2_CODE_UNIT_WIDTH == 16+ *class_uchardata++ = 0x100;+ *class_uchardata++ = 0xffffu;+#elif PCRE2_CODE_UNIT_WIDTH == 32+ *class_uchardata++ = 0x100;+ *class_uchardata++ = 0xffffffffu;+#endif+ }+ }+ *class_uchardata++ = XCL_END; /* Marks the end of extra data */+ *code++ = OP_XCLASS;+ code += LINK_SIZE;+ *code = negate_class? XCL_NOT:0;+ if (xclass_has_prop) *code |= XCL_HASPROP;++ /* If the map is required, move up the extra data to make room for it;+ otherwise just move the code pointer to the end of the extra data. */++ if (class_has_8bitchar > 0)+ {+ *code++ |= XCL_MAP;+ (void)memmove(code + (32 / sizeof(PCRE2_UCHAR)), code,+ CU2BYTES(class_uchardata - code));+ if (negate_class && !xclass_has_prop)+ {+ /* Using 255 ^ instead of ~ avoids clang sanitize warning. */+ for (int i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];+ }+ memcpy(code, classbits, 32);+ code = class_uchardata + (32 / sizeof(PCRE2_UCHAR));+ }+ else code = class_uchardata;++ /* Now fill in the complete length of the item */++ PUT(previous, 1, (int)(code - previous));+ break; /* End of class handling */+ }+#endif /* SUPPORT_WIDE_CHARS */++ /* If there are no characters > 255, or they are all to be included or+ excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the+ whole class was negated and whether there were negative specials such as \S+ (non-UCP) in the class. Then copy the 32-byte map into the code vector,+ negating it if necessary. */++ *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;+ if (lengthptr == NULL) /* Save time in the pre-compile phase */+ {+ if (negate_class)+ {+ /* Using 255 ^ instead of ~ avoids clang sanitize warning. */+ for (int i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];+ }+ memcpy(code, classbits, 32);+ }+ code += 32 / sizeof(PCRE2_UCHAR);+ break; /* End of class processing */+++ /* ===================================================================*/+ /* Deal with (*VERB)s. */++ /* Check for open captures before ACCEPT and close those that are within+ the same assertion level, also converting ACCEPT to ASSERT_ACCEPT in an+ assertion. In the first pass, just accumulate the length required;+ otherwise hitting (*ACCEPT) inside many nested parentheses can cause+ workspace overflow. Do not set firstcu after *ACCEPT. */++ case META_ACCEPT:+ cb->had_accept = had_accept = TRUE;+ for (oc = open_caps;+ oc != NULL && oc->assert_depth >= cb->assert_depth;+ oc = oc->next)+ {+ if (lengthptr != NULL)+ {+ *lengthptr += CU2BYTES(1) + IMM2_SIZE;+ }+ else+ {+ *code++ = OP_CLOSE;+ PUT2INC(code, 0, oc->number);+ }+ }+ *code++ = (cb->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ break;++ case META_PRUNE:+ case META_SKIP:+ cb->had_pruneorskip = TRUE;+ /* Fall through */+ case META_COMMIT:+ case META_FAIL:+ *code++ = verbops[(meta - META_MARK) >> 16];+ break;++ case META_THEN:+ cb->external_flags |= PCRE2_HASTHEN;+ *code++ = OP_THEN;+ break;++ /* Handle verbs with arguments. Arguments can be very long, especially in+ 16- and 32-bit modes, and can overflow the workspace in the first pass.+ However, the argument length is constrained to be small enough to fit in+ one code unit. This check happens in parse_regex(). In the first pass,+ instead of putting the argument into memory, we just update the length+ counter and set up an empty argument. */++ case META_THEN_ARG:+ cb->external_flags |= PCRE2_HASTHEN;+ goto VERB_ARG;++ case META_PRUNE_ARG:+ case META_SKIP_ARG:+ cb->had_pruneorskip = TRUE;+ /* Fall through */+ case META_MARK:+ case META_COMMIT_ARG:+ VERB_ARG:+ *code++ = verbops[(meta - META_MARK) >> 16];+ /* The length is in characters. */+ verbarglen = *(++pptr);+ verbculen = 0;+ tempcode = code++;+ for (int i = 0; i < (int)verbarglen; i++)+ {+ meta = *(++pptr);+#ifdef SUPPORT_UNICODE+ if (utf) mclength = PRIV(ord2utf)(meta, mcbuffer); else+#endif+ {+ mclength = 1;+ mcbuffer[0] = meta;+ }+ if (lengthptr != NULL) *lengthptr += mclength; else+ {+ memcpy(code, mcbuffer, CU2BYTES(mclength));+ code += mclength;+ verbculen += mclength;+ }+ }++ *tempcode = verbculen; /* Fill in the code unit length */+ *code++ = 0; /* Terminating zero */+ break;+++ /* ===================================================================*/+ /* Handle options change. The new setting must be passed back for use in+ subsequent branches. Reset the greedy defaults and the case value for+ firstcu and reqcu. */++ case META_OPTIONS:+ *optionsptr = options = *(++pptr);+ *xoptionsptr = xoptions = *(++pptr);+ greedy_default = ((options & PCRE2_UNGREEDY) != 0);+ greedy_non_default = greedy_default ^ 1;+ req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0;+ break;+++ /* ===================================================================*/+ /* Handle conditional subpatterns. The case of (?(Rdigits) is ambiguous+ because it could be a numerical check on recursion, or a name check on a+ group's being set. The pre-pass sets up META_COND_RNUMBER as a name so that+ we can handle it either way. We first try for a name; if not found, process+ the number. */++ case META_COND_RNUMBER: /* (?(Rdigits) */+ case META_COND_NAME: /* (?(name) or (?'name') or ?(<name>) */+ case META_COND_RNAME: /* (?(R&name) - test for recursion */+ bravalue = OP_COND;+ {+ int count, index;+ unsigned int i;+ PCRE2_SPTR name;+ named_group *ng = cb->named_groups;+ uint32_t length = *(++pptr);++ GETPLUSOFFSET(offset, pptr);+ name = cb->start_pattern + offset;++ /* In the first pass, the names generated in the pre-pass are available,+ but the main name table has not yet been created. Scan the list of names+ generated in the pre-pass in order to get a number and whether or not+ this name is duplicated. If it is not duplicated, we can handle it as a+ numerical group. */++ for (i = 0; i < cb->names_found; i++, ng++)+ {+ if (length == ng->length &&+ PRIV(strncmp)(name, ng->name, length) == 0)+ {+ if (!ng->isdup)+ {+ code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;+ PUT2(code, 2+LINK_SIZE, ng->number);+ if (ng->number > cb->top_backref) cb->top_backref = ng->number;+ skipunits = 1+IMM2_SIZE;+ goto GROUP_PROCESS_NOTE_EMPTY;+ }+ break; /* Found a duplicated name */+ }+ }++ /* If the name was not found we have a bad reference, unless we are+ dealing with R<digits>, which is treated as a recursion test by number.+ */++ if (i >= cb->names_found)+ {+ groupnumber = 0;+ if (meta == META_COND_RNUMBER)+ {+ for (i = 1; i < length; i++)+ {+ groupnumber = groupnumber * 10 + name[i] - CHAR_0;+ if (groupnumber > MAX_GROUP_NUMBER)+ {+ *errorcodeptr = ERR61;+ cb->erroroffset = offset + i;+ return 0;+ }+ }+ }++ if (meta != META_COND_RNUMBER || groupnumber > cb->bracount)+ {+ *errorcodeptr = ERR15;+ cb->erroroffset = offset;+ return 0;+ }++ /* (?Rdigits) treated as a recursion reference by number. A value of+ zero (which is the result of both (?R) and (?R0)) means "any", and is+ translated into RREF_ANY (which is 0xffff). */++ if (groupnumber == 0) groupnumber = RREF_ANY;+ code[1+LINK_SIZE] = OP_RREF;+ PUT2(code, 2+LINK_SIZE, groupnumber);+ skipunits = 1+IMM2_SIZE;+ goto GROUP_PROCESS_NOTE_EMPTY;+ }++ /* A duplicated name was found. Note that if an R<digits> name is found+ (META_COND_RNUMBER), it is a reference test, not a recursion test. */++ code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;++ /* We have a duplicated name. In the compile pass we have to search the+ main table in order to get the index and count values. */++ count = 0; /* Values for first pass (avoids compiler warning) */+ index = 0;+ if (lengthptr == NULL && !find_dupname_details(name, length, &index,+ &count, errorcodeptr, cb)) return 0;++ /* Add one to the opcode to change CREF/RREF into DNCREF/DNRREF and+ insert appropriate data values. */++ code[1+LINK_SIZE]++;+ skipunits = 1+2*IMM2_SIZE;+ PUT2(code, 2+LINK_SIZE, index);+ PUT2(code, 2+LINK_SIZE+IMM2_SIZE, count);+ }+ goto GROUP_PROCESS_NOTE_EMPTY;++ /* The DEFINE condition is always false. Its internal groups may never+ be called, so matched_char must remain false, hence the jump to+ GROUP_PROCESS rather than GROUP_PROCESS_NOTE_EMPTY. */++ case META_COND_DEFINE:+ bravalue = OP_COND;+ GETPLUSOFFSET(offset, pptr);+ code[1+LINK_SIZE] = OP_DEFINE;+ skipunits = 1;+ goto GROUP_PROCESS;++ /* Conditional test of a group's being set. */++ case META_COND_NUMBER:+ bravalue = OP_COND;+ GETPLUSOFFSET(offset, pptr);+ groupnumber = *(++pptr);+ if (groupnumber > cb->bracount)+ {+ *errorcodeptr = ERR15;+ cb->erroroffset = offset;+ return 0;+ }+ if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;+ offset -= 2; /* Point at initial ( for too many branches error */+ code[1+LINK_SIZE] = OP_CREF;+ skipunits = 1+IMM2_SIZE;+ PUT2(code, 2+LINK_SIZE, groupnumber);+ goto GROUP_PROCESS_NOTE_EMPTY;++ /* Test for the PCRE2 version. */++ case META_COND_VERSION:+ bravalue = OP_COND;+ if (pptr[1] > 0)+ code[1+LINK_SIZE] = ((PCRE2_MAJOR > pptr[2]) ||+ (PCRE2_MAJOR == pptr[2] && PCRE2_MINOR >= pptr[3]))?+ OP_TRUE : OP_FALSE;+ else+ code[1+LINK_SIZE] = (PCRE2_MAJOR == pptr[2] && PCRE2_MINOR == pptr[3])?+ OP_TRUE : OP_FALSE;+ skipunits = 1;+ pptr += 3;+ goto GROUP_PROCESS_NOTE_EMPTY;++ /* The condition is an assertion, possibly preceded by a callout. */++ case META_COND_ASSERT:+ bravalue = OP_COND;+ goto GROUP_PROCESS_NOTE_EMPTY;+++ /* ===================================================================*/+ /* Handle all kinds of nested bracketed groups. The non-capturing,+ non-conditional cases are here; others come to GROUP_PROCESS via goto. */++ case META_LOOKAHEAD:+ bravalue = OP_ASSERT;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ case META_LOOKAHEAD_NA:+ bravalue = OP_ASSERT_NA;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ /* Optimize (?!) to (*FAIL) unless it is quantified - which is a weird+ thing to do, but Perl allows all assertions to be quantified, and when+ they contain capturing parentheses there may be a potential use for+ this feature. Not that that applies to a quantified (?!) but we allow+ it for uniformity. */++ case META_LOOKAHEADNOT:+ if (pptr[1] == META_KET &&+ (pptr[2] < META_ASTERISK || pptr[2] > META_MINMAX_QUERY))+ {+ *code++ = OP_FAIL;+ pptr++;+ }+ else+ {+ bravalue = OP_ASSERT_NOT;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;+ }+ break;++ case META_LOOKBEHIND:+ bravalue = OP_ASSERTBACK;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ case META_LOOKBEHINDNOT:+ bravalue = OP_ASSERTBACK_NOT;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ case META_LOOKBEHIND_NA:+ bravalue = OP_ASSERTBACK_NA;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ case META_ATOMIC:+ bravalue = OP_ONCE;+ goto GROUP_PROCESS_NOTE_EMPTY;++ case META_SCRIPT_RUN:+ bravalue = OP_SCRIPT_RUN;+ goto GROUP_PROCESS_NOTE_EMPTY;++ case META_NOCAPTURE:+ bravalue = OP_BRA;+ /* Fall through */++ /* Process nested bracketed regex. The nesting depth is maintained for the+ benefit of the stackguard function. The test for too deep nesting is now+ done in parse_regex(). Assertion and DEFINE groups come to GROUP_PROCESS;+ others come to GROUP_PROCESS_NOTE_EMPTY, to indicate that we need to take+ note of whether or not they may match an empty string. */++ GROUP_PROCESS_NOTE_EMPTY:+ note_group_empty = TRUE;++ GROUP_PROCESS:+ cb->parens_depth += 1;+ *code = bravalue;+ pptr++;+ tempcode = code;+ tempreqvary = cb->req_varyopt; /* Save value before group */+ length_prevgroup = 0; /* Initialize for pre-compile phase */++ if ((group_return =+ compile_regex(+ options, /* The options state */+ xoptions, /* The extra options state */+ &tempcode, /* Where to put code (updated) */+ &pptr, /* Input pointer (updated) */+ errorcodeptr, /* Where to put an error message */+ skipunits, /* Skip over bracket number */+ &subfirstcu, /* For possible first char */+ &subfirstcuflags,+ &subreqcu, /* For possible last char */+ &subreqcuflags,+ bcptr, /* Current branch chain */+ open_caps, /* Pointer to capture stack */+ cb, /* Compile data block */+ (lengthptr == NULL)? NULL : /* Actual compile phase */+ &length_prevgroup /* Pre-compile phase */+ )) == 0)+ return 0; /* Error */++ cb->parens_depth -= 1;++ /* If that was a non-conditional significant group (not an assertion, not a+ DEFINE) that matches at least one character, then the current item matches+ a character. Conditionals are handled below. */++ if (note_group_empty && bravalue != OP_COND && group_return > 0)+ matched_char = TRUE;++ /* If we've just compiled an assertion, pop the assert depth. */++ if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NA)+ cb->assert_depth -= 1;++ /* At the end of compiling, code is still pointing to the start of the+ group, while tempcode has been updated to point past the end of the group.+ The parsed pattern pointer (pptr) is on the closing META_KET.++ If this is a conditional bracket, check that there are no more than+ two branches in the group, or just one if it's a DEFINE group. We do this+ in the real compile phase, not in the pre-pass, where the whole group may+ not be available. */++ if (bravalue == OP_COND && lengthptr == NULL)+ {+ PCRE2_UCHAR *tc = code;+ int condcount = 0;++ do {+ condcount++;+ tc += GET(tc,1);+ }+ while (*tc != OP_KET);++ /* A DEFINE group is never obeyed inline (the "condition" is always+ false). It must have only one branch. Having checked this, change the+ opcode to OP_FALSE. */++ if (code[LINK_SIZE+1] == OP_DEFINE)+ {+ if (condcount > 1)+ {+ cb->erroroffset = offset;+ *errorcodeptr = ERR54;+ return 0;+ }+ code[LINK_SIZE+1] = OP_FALSE;+ bravalue = OP_DEFINE; /* A flag to suppress char handling below */+ }++ /* A "normal" conditional group. If there is just one branch, we must not+ make use of its firstcu or reqcu, because this is equivalent to an+ empty second branch. Also, it may match an empty string. If there are two+ branches, this item must match a character if the group must. */++ else+ {+ if (condcount > 2)+ {+ cb->erroroffset = offset;+ *errorcodeptr = ERR27;+ return 0;+ }+ if (condcount == 1) subfirstcuflags = subreqcuflags = REQ_NONE;+ else if (group_return > 0) matched_char = TRUE;+ }+ }++ /* In the pre-compile phase, update the length by the length of the group,+ less the brackets at either end. Then reduce the compiled code to just a+ set of non-capturing brackets so that it doesn't use much memory if it is+ duplicated by a quantifier.*/++ if (lengthptr != NULL)+ {+ if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE;+ code++; /* This already contains bravalue */+ PUTINC(code, 0, 1 + LINK_SIZE);+ *code++ = OP_KET;+ PUTINC(code, 0, 1 + LINK_SIZE);+ break; /* No need to waste time with special character handling */+ }++ /* Otherwise update the main code pointer to the end of the group. */++ code = tempcode;++ /* For a DEFINE group, required and first character settings are not+ relevant. */++ if (bravalue == OP_DEFINE) break;++ /* Handle updating of the required and first code units for other types of+ group. Update for normal brackets of all kinds, and conditions with two+ branches (see code above). If the bracket is followed by a quantifier with+ zero repeat, we have to back off. Hence the definition of zeroreqcu and+ zerofirstcu outside the main loop so that they can be accessed for the back+ off. */++ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ groupsetfirstcu = FALSE;++ if (bravalue >= OP_ONCE) /* Not an assertion */+ {+ /* If we have not yet set a firstcu in this branch, take it from the+ subpattern, remembering that it was set here so that a repeat of more+ than one can replicate it as reqcu if necessary. If the subpattern has+ no firstcu, set "none" for the whole branch. In both cases, a zero+ repeat forces firstcu to "none". */++ if (firstcuflags == REQ_UNSET && subfirstcuflags != REQ_UNSET)+ {+ if (subfirstcuflags < REQ_NONE)+ {+ firstcu = subfirstcu;+ firstcuflags = subfirstcuflags;+ groupsetfirstcu = TRUE;+ }+ else firstcuflags = REQ_NONE;+ zerofirstcuflags = REQ_NONE;+ }++ /* If firstcu was previously set, convert the subpattern's firstcu+ into reqcu if there wasn't one, using the vary flag that was in+ existence beforehand. */++ else if (subfirstcuflags < REQ_NONE && subreqcuflags >= REQ_NONE)+ {+ subreqcu = subfirstcu;+ subreqcuflags = subfirstcuflags | tempreqvary;+ }++ /* If the subpattern set a required code unit (or set a first code unit+ that isn't really the first code unit - see above), set it. */++ if (subreqcuflags < REQ_NONE)+ {+ reqcu = subreqcu;+ reqcuflags = subreqcuflags;+ }+ }++ /* For a forward assertion, we take the reqcu, if set, provided that the+ group has also set a firstcu. 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 firstcu for an assertion, however+ because it leads to incorrect effect for patterns such as /(?=a)a.+/ when+ the "real" "a" would then become a reqcu instead of a firstcu. This is+ overcome by a scan at the end if there's no firstcu, looking for an+ asserted first char. A similar effect for patterns like /(?=.*X)X$/ means+ we must only take the reqcu when the group also set a firstcu. Otherwise,+ in that example, 'X' ends up set for both. */++ else if ((bravalue == OP_ASSERT || bravalue == OP_ASSERT_NA) &&+ subreqcuflags < REQ_NONE && subfirstcuflags < REQ_NONE)+ {+ reqcu = subreqcu;+ reqcuflags = subreqcuflags;+ }++ break; /* End of nested group handling */+++ /* ===================================================================*/+ /* Handle named backreferences and recursions. */++ case META_BACKREF_BYNAME:+ case META_RECURSE_BYNAME:+ {+ int count, index;+ PCRE2_SPTR name;+ BOOL is_dupname = FALSE;+ named_group *ng = cb->named_groups;+ uint32_t length = *(++pptr);++ GETPLUSOFFSET(offset, pptr);+ name = cb->start_pattern + offset;++ /* In the first pass, the names generated in the pre-pass are available,+ but the main name table has not yet been created. Scan the list of names+ generated in the pre-pass in order to get a number and whether or not+ this name is duplicated. */++ groupnumber = 0;+ for (unsigned int i = 0; i < cb->names_found; i++, ng++)+ {+ if (length == ng->length &&+ PRIV(strncmp)(name, ng->name, length) == 0)+ {+ is_dupname = ng->isdup;+ groupnumber = ng->number;++ /* For a recursion, that's all that is needed. We can now go to+ the code that handles numerical recursion, applying it to the first+ group with the given name. */++ if (meta == META_RECURSE_BYNAME)+ {+ meta_arg = groupnumber;+ goto HANDLE_NUMERICAL_RECURSION;+ }++ /* For a back reference, update the back reference map and the+ maximum back reference. */++ cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;+ if (groupnumber > cb->top_backref)+ cb->top_backref = groupnumber;+ }+ }++ /* If the name was not found we have a bad reference. */++ if (groupnumber == 0)+ {+ *errorcodeptr = ERR15;+ cb->erroroffset = offset;+ return 0;+ }++ /* If a back reference name is not duplicated, we can handle it as+ a numerical reference. */++ if (!is_dupname)+ {+ meta_arg = groupnumber;+ goto HANDLE_SINGLE_REFERENCE;+ }++ /* If a back reference name is duplicated, we generate a different+ opcode to a numerical back reference. In the second pass we must+ search for the index and count in the final name table. */++ count = 0; /* Values for first pass (avoids compiler warning) */+ index = 0;+ if (lengthptr == NULL && !find_dupname_details(name, length, &index,+ &count, errorcodeptr, cb)) return 0;++ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_DNREFI : OP_DNREF;+ PUT2INC(code, 0, index);+ PUT2INC(code, 0, count);+ }+ break;+++ /* ===================================================================*/+ /* Handle a numerical callout. */++ case META_CALLOUT_NUMBER:+ code[0] = OP_CALLOUT;+ PUT(code, 1, pptr[1]); /* Offset to next pattern item */+ PUT(code, 1 + LINK_SIZE, pptr[2]); /* Length of next pattern item */+ code[1 + 2*LINK_SIZE] = pptr[3];+ pptr += 3;+ code += PRIV(OP_lengths)[OP_CALLOUT];+ break;+++ /* ===================================================================*/+ /* Handle a callout with a string argument. In the pre-pass we just compute+ the length without generating anything. The length in pptr[3] includes both+ delimiters; in the actual compile only the first one is copied, but a+ terminating zero is added. Any doubled delimiters within the string make+ this an overestimate, but it is not worth bothering about. */++ case META_CALLOUT_STRING:+ if (lengthptr != NULL)+ {+ *lengthptr += pptr[3] + (1 + 4*LINK_SIZE);+ pptr += 3;+ SKIPOFFSET(pptr);+ }++ /* In the real compile we can copy the string. The starting delimiter is+ included so that the client can discover it if they want. We also pass the+ start offset to help a script language give better error messages. */++ else+ {+ PCRE2_SPTR pp;+ uint32_t delimiter;+ uint32_t length = pptr[3];+ PCRE2_UCHAR *callout_string = code + (1 + 4*LINK_SIZE);++ code[0] = OP_CALLOUT_STR;+ PUT(code, 1, pptr[1]); /* Offset to next pattern item */+ PUT(code, 1 + LINK_SIZE, pptr[2]); /* Length of next pattern item */++ pptr += 3;+ GETPLUSOFFSET(offset, pptr); /* Offset to string in pattern */+ pp = cb->start_pattern + offset;+ delimiter = *callout_string++ = *pp++;+ if (delimiter == CHAR_LEFT_CURLY_BRACKET)+ delimiter = CHAR_RIGHT_CURLY_BRACKET;+ PUT(code, 1 + 3*LINK_SIZE, (int)(offset + 1)); /* One after delimiter */++ /* The syntax of the pattern was checked in the parsing scan. The length+ includes both delimiters, but we have passed the opening one just above,+ so we reduce length before testing it. The test is for > 1 because we do+ not want to copy the final delimiter. This also ensures that pp[1] is+ accessible. */++ while (--length > 1)+ {+ if (*pp == delimiter && pp[1] == delimiter)+ {+ *callout_string++ = delimiter;+ pp += 2;+ length--;+ }+ else *callout_string++ = *pp++;+ }+ *callout_string++ = CHAR_NUL;++ /* Set the length of the entire item, the advance to its end. */++ PUT(code, 1 + 2*LINK_SIZE, (int)(callout_string - code));+ code = callout_string;+ }+ break;+++ /* ===================================================================*/+ /* Handle repetition. The different types are all sorted out in the parsing+ pass. */++ case META_MINMAX_PLUS:+ case META_MINMAX_QUERY:+ case META_MINMAX:+ repeat_min = *(++pptr);+ repeat_max = *(++pptr);+ goto REPEAT;++ case META_ASTERISK:+ case META_ASTERISK_PLUS:+ case META_ASTERISK_QUERY:+ repeat_min = 0;+ repeat_max = REPEAT_UNLIMITED;+ goto REPEAT;++ case META_PLUS:+ case META_PLUS_PLUS:+ case META_PLUS_QUERY:+ repeat_min = 1;+ repeat_max = REPEAT_UNLIMITED;+ goto REPEAT;++ case META_QUERY:+ case META_QUERY_PLUS:+ case META_QUERY_QUERY:+ repeat_min = 0;+ repeat_max = 1;++ REPEAT:+ if (previous_matched_char && repeat_min > 0) matched_char = TRUE;++ /* Remember whether this is a variable length repeat, and default to+ single-char opcodes. */++ reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY;+ op_type = 0;++ /* Adjust first and required code units for a zero repeat. */++ if (repeat_min == 0)+ {+ firstcu = zerofirstcu;+ firstcuflags = zerofirstcuflags;+ reqcu = zeroreqcu;+ reqcuflags = zeroreqcuflags;+ }++ /* Note the greediness and possessiveness. */++ switch (meta)+ {+ case META_MINMAX_PLUS:+ case META_ASTERISK_PLUS:+ case META_PLUS_PLUS:+ case META_QUERY_PLUS:+ repeat_type = 0; /* Force greedy */+ possessive_quantifier = TRUE;+ break;++ case META_MINMAX_QUERY:+ case META_ASTERISK_QUERY:+ case META_PLUS_QUERY:+ case META_QUERY_QUERY:+ repeat_type = greedy_non_default;+ possessive_quantifier = FALSE;+ break;++ default:+ repeat_type = greedy_default;+ possessive_quantifier = FALSE;+ break;+ }++ /* Save start of previous item, in case we have to move it up in order to+ insert something before it, and remember what it was. */++ tempcode = previous;+ op_previous = *previous;++ /* Now handle repetition for the different types of item. If the repeat+ minimum and the repeat maximum are both 1, we can ignore the quantifier for+ non-parenthesized items, as they have only one alternative. For anything in+ parentheses, we must not ignore if {1} is possessive. */++ switch (op_previous)+ {+ /* If previous was a character or negated character match, abolish the+ item and generate a repeat item instead. If a char item has a minimum of+ more than one, ensure that it is set in reqcu - it might not be if a+ sequence such as x{3} is the first thing in a branch because the x will+ have gone into firstcu instead. */++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;+ op_type = chartypeoffset[op_previous - OP_CHAR];++ /* Deal with UTF characters that take up more than one code unit. */++#ifdef MAYBE_UTF_MULTI+ if (utf && NOT_FIRSTCU(code[-1]))+ {+ PCRE2_UCHAR *lastchar = code - 1;+ BACKCHAR(lastchar);+ mclength = (uint32_t)(code - lastchar); /* Length of UTF character */+ memcpy(mcbuffer, lastchar, CU2BYTES(mclength)); /* Save the char */+ }+ else+#endif /* MAYBE_UTF_MULTI */++ /* Handle the case of a single code unit - either with no UTF support, or+ with UTF disabled, or for a single-code-unit UTF character. In the latter+ case, for a repeated positive match, get the caseless flag for the+ required code unit from the previous character, because a class like [Aa]+ sets a caseless A but by now the req_caseopt flag has been reset. */++ {+ mcbuffer[0] = code[-1];+ mclength = 1;+ if (op_previous <= OP_CHARI && repeat_min > 1)+ {+ reqcu = mcbuffer[0];+ reqcuflags = cb->req_varyopt;+ if (op_previous == OP_CHARI) reqcuflags |= REQ_CASELESS;+ }+ }+ goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */++ /* If previous was a character class or a back reference, we put the+ repeat stuff after it, but just skip the item if the repeat was {0,0}. */++#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+#endif+ case OP_CLASS:+ case OP_NCLASS:+ case OP_REF:+ case OP_REFI:+ case OP_DNREF:+ case OP_DNREFI:++ if (repeat_max == 0)+ {+ code = previous;+ goto END_REPEAT;+ }+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;++ if (repeat_min == 0 && repeat_max == REPEAT_UNLIMITED)+ *code++ = OP_CRSTAR + repeat_type;+ else if (repeat_min == 1 && repeat_max == REPEAT_UNLIMITED)+ *code++ = OP_CRPLUS + repeat_type;+ else if (repeat_min == 0 && repeat_max == 1)+ *code++ = OP_CRQUERY + repeat_type;+ else+ {+ *code++ = OP_CRRANGE + repeat_type;+ PUT2INC(code, 0, repeat_min);+ if (repeat_max == REPEAT_UNLIMITED) repeat_max = 0; /* 2-byte encoding for max */+ PUT2INC(code, 0, repeat_max);+ }+ break;++ /* If previous is OP_FAIL, it was generated by an empty class []+ (PCRE2_ALLOW_EMPTY_CLASS is set). The other ways in which OP_FAIL can be+ generated, that is by (*FAIL) or (?!), disallow a quantifier at parse+ time. We can just ignore this repeat. */++ case OP_FAIL:+ goto END_REPEAT;++ /* Prior to 10.30, repeated recursions were wrapped in OP_ONCE brackets+ because pcre2_match() could not handle backtracking into recursively+ called groups. Now that this backtracking is available, we no longer need+ to do this. However, we still need to replicate recursions as we do for+ groups so as to have independent backtracking points. We can replicate+ for the minimum number of repeats directly. For optional repeats we now+ wrap the recursion in OP_BRA brackets and make use of the bracket+ repetition. */++ case OP_RECURSE:+ if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)+ goto END_REPEAT;++ /* Generate unwrapped repeats for a non-zero minimum, except when the+ minimum is 1 and the maximum unlimited, because that can be handled with+ OP_BRA terminated by OP_KETRMAX/MIN. When the maximum is equal to the+ minimum, we just need to generate the appropriate additional copies.+ Otherwise we need to generate one more, to simulate the situation when+ the minimum is zero. */++ if (repeat_min > 0 && (repeat_min != 1 || repeat_max != REPEAT_UNLIMITED))+ {+ int replicate = repeat_min;+ if (repeat_min == repeat_max) replicate--;++ /* In the pre-compile phase, we don't actually do the replication. We+ just adjust the length as if we had. Do some paranoid checks for+ potential integer overflow. */++ if (lengthptr != NULL)+ {+ PCRE2_SIZE delta;+ if (PRIV(ckd_smul)(&delta, replicate, 1 + LINK_SIZE) ||+ OFLOW_MAX - *lengthptr < delta)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += delta;+ }++ else for (int i = 0; i < replicate; i++)+ {+ memcpy(code, previous, CU2BYTES(1 + LINK_SIZE));+ previous = code;+ code += 1 + LINK_SIZE;+ }++ /* If the number of repeats is fixed, we are done. Otherwise, adjust+ the counts and fall through. */++ if (repeat_min == repeat_max) break;+ if (repeat_max != REPEAT_UNLIMITED) repeat_max -= repeat_min;+ repeat_min = 0;+ }++ /* Wrap the recursion call in OP_BRA brackets. */++ (void)memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(1 + LINK_SIZE));+ op_previous = *previous = OP_BRA;+ PUT(previous, 1, 2 + 2*LINK_SIZE);+ previous[2 + 2*LINK_SIZE] = OP_KET;+ PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE);+ code += 2 + 2 * LINK_SIZE;+ length_prevgroup = 3 + 3*LINK_SIZE;+ group_return = -1; /* Set "may match empty string" */++ /* Now treat as a repeated OP_BRA. */+ /* Fall through */++ /* If previous was a bracket group, we may have to replicate it in+ certain cases. Note that at this point we can encounter only the "basic"+ bracket opcodes such as BRA and CBRA, as this is the place where they get+ converted into the more special varieties such as BRAPOS and SBRA.+ Originally, PCRE did not allow repetition of assertions, but now it does,+ for Perl compatibility. */++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRA:+ case OP_CBRA:+ case OP_COND:+ {+ int len = (int)(code - previous);+ PCRE2_UCHAR *bralink = NULL;+ PCRE2_UCHAR *brazeroptr = NULL;++ if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)+ goto END_REPEAT;++ /* Repeating a DEFINE group (or any group where the condition is always+ FALSE and there is only one branch) is pointless, but Perl allows the+ syntax, so we just ignore the repeat. */++ if (op_previous == OP_COND && previous[LINK_SIZE+1] == OP_FALSE &&+ previous[GET(previous, 1)] != OP_ALT)+ goto END_REPEAT;++ /* Perl allows all assertions to be quantified, and when they contain+ capturing parentheses and/or are optional there are potential uses for+ this feature. PCRE2 used to force the maximum quantifier to 1 on the+ invalid grounds that further repetition was never useful. This was+ always a bit pointless, since an assertion could be wrapped with a+ repeated group to achieve the effect. General repetition is now+ permitted, but if the maximum is unlimited it is set to one more than+ the minimum. */++ if (op_previous < OP_ONCE) /* Assertion */+ {+ if (repeat_max == REPEAT_UNLIMITED) repeat_max = repeat_min + 1;+ }++ /* The case of a zero minimum is special because of the need to stick+ OP_BRAZERO in front of it, and because the group appears once in the+ data, whereas in other cases it appears the minimum number of times. For+ this reason, it is simplest to treat this case separately, as otherwise+ the code gets far too messy. There are several special subcases when the+ minimum is zero. */++ if (repeat_min == 0)+ {+ /* If the maximum is also zero, we used to just omit the group from+ the output altogether, like this:++ ** if (repeat_max == 0)+ ** {+ ** code = previous;+ ** goto END_REPEAT;+ ** }++ However, that fails when a group or a subgroup within it is+ referenced as a subroutine from elsewhere in the pattern, so now we+ stick in OP_SKIPZERO in front of it so that it is skipped on+ execution. As we don't have a list of which groups are referenced, we+ cannot do this selectively.++ If the maximum is 1 or unlimited, we just have to stick in the+ BRAZERO and do no more at this point. */++ if (repeat_max <= 1 || repeat_max == REPEAT_UNLIMITED)+ {+ (void)memmove(previous + 1, previous, CU2BYTES(len));+ code++;+ if (repeat_max == 0)+ {+ *previous++ = OP_SKIPZERO;+ goto END_REPEAT;+ }+ brazeroptr = previous; /* Save for possessive optimizing */+ *previous++ = OP_BRAZERO + repeat_type;+ }++ /* If the maximum is greater than 1 and limited, we have to replicate+ in a nested fashion, sticking OP_BRAZERO before each set of brackets.+ The first one has to be handled carefully because it's the original+ copy, which has to be moved up. The remainder can be handled by code+ that is common with the non-zero minimum case below. We have to+ adjust the value or repeat_max, since one less copy is required. */++ else+ {+ int linkoffset;+ (void)memmove(previous + 2 + LINK_SIZE, previous, CU2BYTES(len));+ code += 2 + LINK_SIZE;+ *previous++ = OP_BRAZERO + repeat_type;+ *previous++ = OP_BRA;++ /* We chain together the bracket link offset fields that have to be+ filled in later when the ends of the brackets are reached. */++ linkoffset = (bralink == NULL)? 0 : (int)(previous - bralink);+ bralink = previous;+ PUTINC(previous, 0, linkoffset);+ }++ if (repeat_max != REPEAT_UNLIMITED) repeat_max--;+ }++ /* If the minimum is greater than zero, replicate the group as many+ times as necessary, and adjust the maximum to the number of subsequent+ copies that we need. */++ else+ {+ if (repeat_min > 1)+ {+ /* In the pre-compile phase, we don't actually do the replication.+ We just adjust the length as if we had. Do some paranoid checks for+ potential integer overflow. */++ if (lengthptr != NULL)+ {+ PCRE2_SIZE delta;+ if (PRIV(ckd_smul)(&delta, repeat_min - 1,+ (int)length_prevgroup) ||+ OFLOW_MAX - *lengthptr < delta)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += delta;+ }++ /* This is compiling for real. If there is a set first code unit+ for the group, and we have not yet set a "required code unit", set+ it. */++ else+ {+ if (groupsetfirstcu && reqcuflags >= REQ_NONE)+ {+ reqcu = firstcu;+ reqcuflags = firstcuflags;+ }+ for (uint32_t i = 1; i < repeat_min; i++)+ {+ memcpy(code, previous, CU2BYTES(len));+ code += len;+ }+ }+ }++ if (repeat_max != REPEAT_UNLIMITED) repeat_max -= repeat_min;+ }++ /* This code is common to both the zero and non-zero minimum cases. If+ the maximum is limited, it replicates the group in a nested fashion,+ remembering the bracket starts on a stack. In the case of a zero+ minimum, the first one was set up above. In all cases the repeat_max+ now specifies the number of additional copies needed. Again, we must+ remember to replicate entries on the forward reference list. */++ if (repeat_max != REPEAT_UNLIMITED)+ {+ /* In the pre-compile phase, we don't actually do the replication. We+ just adjust the length as if we had. For each repetition we must add+ 1 to the length for BRAZERO and for all but the last repetition we+ must add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some+ paranoid checks to avoid integer overflow. */++ if (lengthptr != NULL && repeat_max > 0)+ {+ PCRE2_SIZE delta;+ if (PRIV(ckd_smul)(&delta, repeat_max,+ (int)length_prevgroup + 1 + 2 + 2*LINK_SIZE) ||+ OFLOW_MAX + (2 + 2*LINK_SIZE) - *lengthptr < delta)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ delta -= (2 + 2*LINK_SIZE); /* Last one doesn't nest */+ *lengthptr += delta;+ }++ /* This is compiling for real */++ else for (uint32_t i = repeat_max; i >= 1; i--)+ {+ *code++ = OP_BRAZERO + repeat_type;++ /* All but the final copy start a new nesting, maintaining the+ chain of brackets outstanding. */++ if (i != 1)+ {+ int linkoffset;+ *code++ = OP_BRA;+ linkoffset = (bralink == NULL)? 0 : (int)(code - bralink);+ bralink = code;+ PUTINC(code, 0, linkoffset);+ }++ memcpy(code, previous, CU2BYTES(len));+ code += len;+ }++ /* Now chain through the pending brackets, and fill in their length+ fields (which are holding the chain links pro tem). */++ while (bralink != NULL)+ {+ int oldlinkoffset;+ int linkoffset = (int)(code - bralink + 1);+ PCRE2_UCHAR *bra = code - linkoffset;+ oldlinkoffset = GET(bra, 1);+ bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;+ *code++ = OP_KET;+ PUTINC(code, 0, linkoffset);+ PUT(bra, 1, linkoffset);+ }+ }++ /* If the maximum is unlimited, set a repeater in the final copy. For+ SCRIPT_RUN and ONCE brackets, that's all we need to do. However,+ possessively repeated ONCE brackets can be converted into non-capturing+ brackets, as the behaviour of (?:xx)++ is the same as (?>xx)++ and this+ saves having to deal with possessive ONCEs specially.++ Otherwise, when we are doing the actual compile phase, check to see+ whether this group is one that could match an empty string. If so,+ convert the initial operator to the S form (e.g. OP_BRA -> OP_SBRA) so+ that runtime checking can be done. [This check is also applied to ONCE+ and SCRIPT_RUN groups at runtime, but in a different way.]++ Then, if the quantifier was possessive and the bracket is not a+ conditional, we convert the BRA code to the POS form, and the KET code+ to KETRPOS. (It turns out to be convenient at runtime to detect this+ kind of subpattern at both the start and at the end.) The use of+ special opcodes makes it possible to reduce greatly the stack usage in+ pcre2_match(). If the group is preceded by OP_BRAZERO, convert this to+ OP_BRAPOSZERO.++ Then, if the minimum number of matches is 1 or 0, cancel the possessive+ flag so that the default action below, of wrapping everything inside+ atomic brackets, does not happen. When the minimum is greater than 1,+ there will be earlier copies of the group, and so we still have to wrap+ the whole thing. */++ else+ {+ PCRE2_UCHAR *ketcode = code - 1 - LINK_SIZE;+ PCRE2_UCHAR *bracode = ketcode - GET(ketcode, 1);++ /* Convert possessive ONCE brackets to non-capturing */++ if (*bracode == OP_ONCE && possessive_quantifier) *bracode = OP_BRA;++ /* For non-possessive ONCE and for SCRIPT_RUN brackets, all we need+ to do is to set the KET. */++ if (*bracode == OP_ONCE || *bracode == OP_SCRIPT_RUN)+ *ketcode = OP_KETRMAX + repeat_type;++ /* Handle non-SCRIPT_RUN and non-ONCE brackets and possessive ONCEs+ (which have been converted to non-capturing above). */++ else+ {+ /* In the compile phase, adjust the opcode if the group can match+ an empty string. For a conditional group with only one branch, the+ value of group_return will not show "could be empty", so we must+ check that separately. */++ if (lengthptr == NULL)+ {+ if (group_return < 0) *bracode += OP_SBRA - OP_BRA;+ if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT)+ *bracode = OP_SCOND;+ }++ /* Handle possessive quantifiers. */++ if (possessive_quantifier)+ {+ /* For COND brackets, we wrap the whole thing in a possessively+ repeated non-capturing bracket, because we have not invented POS+ versions of the COND opcodes. */++ if (*bracode == OP_COND || *bracode == OP_SCOND)+ {+ int nlen = (int)(code - bracode);+ (void)memmove(bracode + 1 + LINK_SIZE, bracode, CU2BYTES(nlen));+ code += 1 + LINK_SIZE;+ nlen += 1 + LINK_SIZE;+ *bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS;+ *code++ = OP_KETRPOS;+ PUTINC(code, 0, nlen);+ PUT(bracode, 1, nlen);+ }++ /* For non-COND brackets, we modify the BRA code and use KETRPOS. */++ else+ {+ *bracode += 1; /* Switch to xxxPOS opcodes */+ *ketcode = OP_KETRPOS;+ }++ /* If the minimum is zero, mark it as possessive, then unset the+ possessive flag when the minimum is 0 or 1. */++ if (brazeroptr != NULL) *brazeroptr = OP_BRAPOSZERO;+ if (repeat_min < 2) possessive_quantifier = FALSE;+ }++ /* Non-possessive quantifier */++ else *ketcode = OP_KETRMAX + repeat_type;+ }+ }+ }+ break;++ /* 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 the the Unicode property types will be present only when+ SUPPORT_UNICODE is defined, but we don't wrap the little bits of code+ here because it just makes it horribly messy. */++ default:+ if (op_previous >= OP_EODN) /* Not a character type - internal error */+ {+ *errorcodeptr = ERR10;+ return 0;+ }+ else+ {+ int prop_type, prop_value;+ PCRE2_UCHAR *oldcode;++ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;++ op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */+ mclength = 0; /* Not a character */++ if (op_previous == OP_PROP || op_previous == OP_NOTPROP)+ {+ prop_type = previous[1];+ prop_value = previous[2];+ }+ else+ {+ /* Come here from just above with a character in mcbuffer/mclength. */+ OUTPUT_SINGLE_REPEAT:+ prop_type = prop_value = -1;+ }++ /* At this point, if prop_type == prop_value == -1 we either have a+ character in mcbuffer when mclength is greater than zero, or we have+ mclength zero, in which case there is a non-property character type in+ op_previous. If prop_type/value are not negative, we have a property+ character type in op_previous. */++ oldcode = code; /* Save where we were */+ code = previous; /* Usually overwrite previous item */++ /* If the maximum is zero then the minimum must also be zero; Perl allows+ this case, so we do too - by simply omitting the item altogether. */++ if (repeat_max == 0) goto END_REPEAT;++ /* Combine the op_type with the repeat_type */++ repeat_type += op_type;++ /* A minimum of zero is handled either as the special case * or ?, or as+ an UPTO, with the maximum given. */++ if (repeat_min == 0)+ {+ if (repeat_max == REPEAT_UNLIMITED) *code++ = OP_STAR + repeat_type;+ else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;+ else+ {+ *code++ = OP_UPTO + repeat_type;+ PUT2INC(code, 0, repeat_max);+ }+ }++ /* A repeat minimum of 1 is optimized into some special cases. If the+ maximum is unlimited, we use OP_PLUS. Otherwise, the original item is+ left in place and, if the maximum is greater than 1, we use OP_UPTO with+ one less than the maximum. */++ else if (repeat_min == 1)+ {+ if (repeat_max == REPEAT_UNLIMITED)+ *code++ = OP_PLUS + repeat_type;+ else+ {+ code = oldcode; /* Leave previous item in place */+ if (repeat_max == 1) goto END_REPEAT;+ *code++ = OP_UPTO + repeat_type;+ PUT2INC(code, 0, repeat_max - 1);+ }+ }++ /* The case {n,n} is just an EXACT, while the general case {n,m} is+ handled as an EXACT followed by an UPTO or STAR or QUERY. */++ else+ {+ *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */+ PUT2INC(code, 0, repeat_min);++ /* Unless repeat_max equals repeat_min, fill in the data for EXACT,+ and then generate the second opcode. For a repeated Unicode property+ match, there are two extra values that define the required property,+ and mclength is set zero to indicate this. */++ if (repeat_max != repeat_min)+ {+ if (mclength > 0)+ {+ memcpy(code, mcbuffer, CU2BYTES(mclength));+ code += mclength;+ }+ else+ {+ *code++ = op_previous;+ if (prop_type >= 0)+ {+ *code++ = prop_type;+ *code++ = prop_value;+ }+ }++ /* Now set up the following opcode */++ if (repeat_max == REPEAT_UNLIMITED)+ *code++ = OP_STAR + repeat_type;+ else+ {+ repeat_max -= repeat_min;+ if (repeat_max == 1)+ {+ *code++ = OP_QUERY + repeat_type;+ }+ else+ {+ *code++ = OP_UPTO + repeat_type;+ PUT2INC(code, 0, repeat_max);+ }+ }+ }+ }++ /* Fill in the character or character type for the final opcode. */++ if (mclength > 0)+ {+ memcpy(code, mcbuffer, CU2BYTES(mclength));+ code += mclength;+ }+ else+ {+ *code++ = op_previous;+ if (prop_type >= 0)+ {+ *code++ = prop_type;+ *code++ = prop_value;+ }+ }+ }+ break;+ } /* End of switch on different op_previous values */+++ /* If the character following a repeat is '+', possessive_quantifier is+ TRUE. For some opcodes, there are special alternative opcodes for this+ case. For anything else, we wrap the entire repeated item inside OP_ONCE+ brackets. Logically, the '+' notation is just syntactic sugar, taken from+ Sun's Java package, but the special opcodes can optimize it.++ Some (but not all) possessively repeated subpatterns have already been+ completely handled in the code just above. For them, possessive_quantifier+ is always FALSE at this stage. Note that the repeated item starts at+ tempcode, not at previous, which might be the first part of a string whose+ (former) last char we repeated. */++ if (possessive_quantifier)+ {+ int len;++ /* Possessifying an EXACT quantifier has no effect, so we can ignore it.+ However, QUERY, STAR, or UPTO may follow (for quantifiers such as {5,6},+ {5,}, or {5,10}). We skip over an EXACT item; if the length of what+ remains is greater than zero, there's a further opcode that can be+ handled. If not, do nothing, leaving the EXACT alone. */++ switch(*tempcode)+ {+ case OP_TYPEEXACT:+ tempcode += PRIV(OP_lengths)[*tempcode] ++ ((tempcode[1 + IMM2_SIZE] == OP_PROP+ || tempcode[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);+ break;++ /* CHAR opcodes are used for exacts whose count is 1. */++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_EXACT:+ case OP_EXACTI:+ case OP_NOTEXACT:+ case OP_NOTEXACTI:+ tempcode += PRIV(OP_lengths)[*tempcode];+#ifdef SUPPORT_UNICODE+ if (utf && HAS_EXTRALEN(tempcode[-1]))+ tempcode += GET_EXTRALEN(tempcode[-1]);+#endif+ break;++ /* For the class opcodes, the repeat operator appears at the end;+ adjust tempcode to point to it. */++ case OP_CLASS:+ case OP_NCLASS:+ tempcode += 1 + 32/sizeof(PCRE2_UCHAR);+ break;++#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+ tempcode += GET(tempcode, 1);+ break;+#endif+ }++ /* If tempcode is equal to code (which points to the end of the repeated+ item), it means we have skipped an EXACT item but there is no following+ QUERY, STAR, or UPTO; the value of len will be 0, and we do nothing. In+ all other cases, tempcode will be pointing to the repeat opcode, and will+ be less than code, so the value of len will be greater than 0. */++ len = (int)(code - tempcode);+ if (len > 0)+ {+ unsigned int repcode = *tempcode;++ /* There is a table for possessifying opcodes, all of which are less+ than OP_CALLOUT. A zero entry means there is no possessified version.+ */++ if (repcode < OP_CALLOUT && opcode_possessify[repcode] > 0)+ *tempcode = opcode_possessify[repcode];++ /* For opcode without a special possessified version, wrap the item in+ ONCE brackets. */++ else+ {+ (void)memmove(tempcode + 1 + LINK_SIZE, tempcode, CU2BYTES(len));+ code += 1 + LINK_SIZE;+ len += 1 + LINK_SIZE;+ tempcode[0] = OP_ONCE;+ *code++ = OP_KET;+ PUTINC(code, 0, len);+ PUT(tempcode, 1, len);+ }+ }+ }++ /* We set the "follows varying string" flag for subsequently encountered+ reqcus if it isn't already set and we have just passed a varying length+ item. */++ END_REPEAT:+ cb->req_varyopt |= reqvary;+ break;+++ /* ===================================================================*/+ /* Handle a 32-bit data character with a value greater than META_END. */++ case META_BIGVALUE:+ pptr++;+ goto NORMAL_CHAR;+++ /* ===============================================================*/+ /* Handle a back reference by number, which is the meta argument. The+ pattern offsets for back references to group numbers less than 10 are held+ in a special vector, to avoid using more than two parsed pattern elements+ in 64-bit environments. We only need the offset to the first occurrence,+ because if that doesn't fail, subsequent ones will also be OK. */++ case META_BACKREF:+ if (meta_arg < 10) offset = cb->small_ref_offset[meta_arg];+ else GETPLUSOFFSET(offset, pptr);++ if (meta_arg > cb->bracount)+ {+ cb->erroroffset = offset;+ *errorcodeptr = ERR15; /* Non-existent subpattern */+ return 0;+ }++ /* Come here from named backref handling when the reference is to a+ single group (that is, not to a duplicated name). The back reference+ data will have already been updated. We must disable firstcu if not+ set, to cope with cases like (?=(\w+))\1: which would otherwise set ':'+ later. */++ HANDLE_SINGLE_REFERENCE:+ if (firstcuflags == REQ_UNSET) zerofirstcuflags = firstcuflags = REQ_NONE;+ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_REFI : OP_REF;+ PUT2INC(code, 0, meta_arg);++ /* Update the map of back references, and keep the highest one. We+ could do this in parse_regex() for numerical back references, but not+ for named back references, because we don't know the numbers to which+ named back references refer. So we do it all in this function. */++ cb->backref_map |= (meta_arg < 32)? (1u << meta_arg) : 1;+ if (meta_arg > cb->top_backref) cb->top_backref = meta_arg;+ break;+++ /* ===============================================================*/+ /* Handle recursion by inserting the number of the called group (which is+ the meta argument) after OP_RECURSE. At the end of compiling the pattern is+ scanned and these numbers are replaced by offsets within the pattern. It is+ done like this to avoid problems with forward references and adjusting+ offsets when groups are duplicated and moved (as discovered in previous+ implementations). Note that a recursion does not have a set first+ character. */++ case META_RECURSE:+ GETPLUSOFFSET(offset, pptr);+ if (meta_arg > cb->bracount)+ {+ cb->erroroffset = offset;+ *errorcodeptr = ERR15; /* Non-existent subpattern */+ return 0;+ }+ HANDLE_NUMERICAL_RECURSION:+ *code = OP_RECURSE;+ PUT(code, 1, meta_arg);+ code += 1 + LINK_SIZE;+ groupsetfirstcu = FALSE;+ cb->had_recurse = TRUE;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ break;+++ /* ===============================================================*/+ /* Handle capturing parentheses; the number is the meta argument. */++ case META_CAPTURE:+ bravalue = OP_CBRA;+ skipunits = IMM2_SIZE;+ PUT2(code, 1+LINK_SIZE, meta_arg);+ cb->lastcapture = meta_arg;+ goto GROUP_PROCESS_NOTE_EMPTY;+++ /* ===============================================================*/+ /* Handle escape sequence items. For ones like \d, the ESC_values are+ arranged to be the same as the corresponding OP_values in the default case+ when PCRE2_UCP is not set (which is the only case in which they will appear+ here).++ Note: \Q and \E are never seen here, as they were dealt with in+ parse_pattern(). Neither are numerical back references or recursions, which+ were turned into META_BACKREF or META_RECURSE items, respectively. \k and+ \g, when followed by names, are turned into META_BACKREF_BYNAME or+ META_RECURSE_BYNAME. */++ case META_ESCAPE:++ /* We can test for escape sequences that consume a character because their+ values lie between ESC_b and ESC_Z; this may have to change if any new ones+ are ever created. For these sequences, we disable the setting of a first+ character if it hasn't already been set. */++ if (meta_arg > ESC_b && meta_arg < ESC_Z)+ {+ matched_char = TRUE;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ }++ /* Set values to reset to if this is followed by a zero repeat. */++ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;++ /* If Unicode is not supported, \P and \p are not allowed and are+ faulted at parse time, so will never appear here. */++#ifdef SUPPORT_UNICODE+ if (meta_arg == ESC_P || meta_arg == ESC_p)+ {+ uint32_t ptype = *(++pptr) >> 16;+ uint32_t pdata = *pptr & 0xffff;++ /* The special case of \p{Any} is compiled to OP_ALLANY so as to benefit+ from the auto-anchoring code. */++ if (meta_arg == ESC_p && ptype == PT_ANY)+ {+ *code++ = OP_ALLANY;+ }+ else+ {+ *code++ = (meta_arg == ESC_p)? OP_PROP : OP_NOTPROP;+ *code++ = ptype;+ *code++ = pdata;+ }+ break; /* End META_ESCAPE */+ }+#endif++ /* \K is forbidden in lookarounds since 10.38 because that's what Perl has+ done. However, there's an option, in case anyone was relying on it. */++ if (cb->assert_depth > 0 && meta_arg == ESC_K &&+ (xoptions & PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) == 0)+ {+ *errorcodeptr = ERR99;+ return 0;+ }++ /* For the rest (including \X when Unicode is supported - if not it's+ faulted at parse time), the OP value is the escape value when PCRE2_UCP is+ not set; if it is set, most of them do not show up here because they are+ converted into Unicode property tests in parse_regex().++ In non-UTF mode, and for both 32-bit modes, we turn \C into OP_ALLANY+ instead of OP_ANYBYTE so that it works in DFA mode and in lookbehinds.+ There are special UCP codes for \B and \b which are used in UCP mode unless+ "word" matching is being forced to ASCII.++ Note that \b and \B do a one-character lookbehind, and \A also behaves as+ if it does. */++ switch(meta_arg)+ {+ case ESC_C:+ cb->external_flags |= PCRE2_HASBKC; /* Record */+#if PCRE2_CODE_UNIT_WIDTH == 32+ meta_arg = OP_ALLANY;+#else+ if (!utf) meta_arg = OP_ALLANY;+#endif+ break;++ case ESC_B:+ case ESC_b:+ if ((options & PCRE2_UCP) != 0 && (xoptions & PCRE2_EXTRA_ASCII_BSW) == 0)+ meta_arg = (meta_arg == ESC_B)? OP_NOT_UCP_WORD_BOUNDARY :+ OP_UCP_WORD_BOUNDARY;+ /* Fall through */++ case ESC_A:+ if (cb->max_lookbehind == 0) cb->max_lookbehind = 1;+ break;+ }++ *code++ = meta_arg;+ break; /* End META_ESCAPE */+++ /* ===================================================================*/+ /* Handle an unrecognized meta value. A parsed pattern value less than+ META_END is a literal. Otherwise we have a problem. */++ default:+ if (meta >= META_END)+ {+#ifdef DEBUG_SHOW_PARSED+ fprintf(stderr, "** Unrecognized parsed pattern item 0x%.8x\n", *pptr);+#endif+ *errorcodeptr = ERR89; /* Internal error - unrecognized. */+ return 0;+ }++ /* Handle a literal character. We come here by goto in the case of a+ 32-bit, non-UTF character whose value is greater than META_END. */++ NORMAL_CHAR:+ meta = *pptr; /* Get the full 32 bits */+ NORMAL_CHAR_SET: /* Character is already in meta */+ matched_char = TRUE;++ /* For caseless UTF or UCP mode, check whether this character has more than+ one other case. If so, generate a special OP_PROP item instead of OP_CHARI.+ When casing restrictions apply, ignore caseless sets that start with an+ ASCII character. */++#ifdef SUPPORT_UNICODE+ if ((utf||ucp) && (options & PCRE2_CASELESS) != 0)+ {+ uint32_t caseset = UCD_CASESET(meta);+ if (caseset != 0 &&+ ((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) == 0 ||+ PRIV(ucd_caseless_sets)[caseset] > 127))+ {+ *code++ = OP_PROP;+ *code++ = PT_CLIST;+ *code++ = caseset;+ if (firstcuflags == REQ_UNSET)+ firstcuflags = zerofirstcuflags = REQ_NONE;+ break; /* End handling this meta item */+ }+ }+#endif++ /* Caseful matches, or caseless and not one of the multicase characters. We+ come here by goto in the case of a positive class that contains only+ case-partners of a character with just two cases; matched_char has already+ been set TRUE and options fudged if necessary. */++ CLASS_CASELESS_CHAR:++ /* Get the character's code units into mcbuffer, with the length in+ mclength. When not in UTF mode, the length is always 1. */++#ifdef SUPPORT_UNICODE+ if (utf) mclength = PRIV(ord2utf)(meta, mcbuffer); else+#endif+ {+ mclength = 1;+ mcbuffer[0] = meta;+ }++ /* Generate the appropriate code */++ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_CHARI : OP_CHAR;+ memcpy(code, mcbuffer, CU2BYTES(mclength));+ code += mclength;++ /* Remember if \r or \n were seen */++ if (mcbuffer[0] == CHAR_CR || mcbuffer[0] == CHAR_NL)+ cb->external_flags |= PCRE2_HASCRORLF;++ /* Set the first and required code units appropriately. If no previous+ first code unit, set it from this character, but revert to none on a zero+ repeat. Otherwise, leave the firstcu value alone, and don't change it on+ a zero repeat. */++ if (firstcuflags == REQ_UNSET)+ {+ zerofirstcuflags = REQ_NONE;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;++ /* If the character is more than one code unit long, we can set a single+ firstcu only if it is not to be matched caselessly. Multiple possible+ starting code units may be picked up later in the studying code. */++ if (mclength == 1 || req_caseopt == 0)+ {+ firstcu = mcbuffer[0];+ firstcuflags = req_caseopt;+ if (mclength != 1)+ {+ reqcu = code[-1];+ reqcuflags = cb->req_varyopt;+ }+ }+ else firstcuflags = reqcuflags = REQ_NONE;+ }++ /* firstcu was previously set; we can set reqcu only if the length is+ 1 or the matching is caseful. */++ else+ {+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;+ if (mclength == 1 || req_caseopt == 0)+ {+ reqcu = code[-1];+ reqcuflags = req_caseopt | cb->req_varyopt;+ }+ }++ /* If caselessness was temporarily instated, reset it. */++ if (reset_caseful)+ {+ options &= ~PCRE2_CASELESS;+ req_caseopt = 0;+ reset_caseful = FALSE;+ }++ break; /* End literal character handling */+ } /* End of big switch */+ } /* End of big loop */++/* Control never reaches here. */+}++++/*************************************************+* Compile regex: a sequence of alternatives *+*************************************************/++/* On entry, pptr is pointing past the bracket meta, but on return it points to+the closing bracket or META_END. The code variable is pointing at the code unit+into which the BRA operator has been stored. This function is used during the+pre-compile phase when we are trying to find out the amount of memory needed,+as well as during the real compile phase. The value of lengthptr distinguishes+the two phases.++Arguments:+ options option bits, including any changes for this subpattern+ xoptions extra option bits, ditto+ codeptr -> the address of the current code pointer+ pptrptr -> the address of the current parsed pattern pointer+ errorcodeptr -> pointer to error code variable+ skipunits skip this many code units at start (for brackets and OP_COND)+ firstcuptr place to put the first required code unit+ firstcuflagsptr place to put the first code unit flags+ reqcuptr place to put the last required code unit+ reqcuflagsptr place to put the last required code unit flags+ bcptr pointer to the chain of currently open branches+ cb points to the data block with tables pointers etc.+ lengthptr NULL during the real compile phase+ points to length accumulator during pre-compile phase++Returns: 0 There has been an error+ +1 Success, this group must match at least one character+ -1 Success, this group may match an empty string+*/++static int+compile_regex(uint32_t options, uint32_t xoptions, PCRE2_UCHAR **codeptr,+ uint32_t **pptrptr, int *errorcodeptr, uint32_t skipunits,+ uint32_t *firstcuptr, uint32_t *firstcuflagsptr, uint32_t *reqcuptr,+ uint32_t *reqcuflagsptr, branch_chain *bcptr, open_capitem *open_caps,+ compile_block *cb, PCRE2_SIZE *lengthptr)+{+PCRE2_UCHAR *code = *codeptr;+PCRE2_UCHAR *last_branch = code;+PCRE2_UCHAR *start_bracket = code;+BOOL lookbehind;+open_capitem capitem;+int capnumber = 0;+int okreturn = 1;+uint32_t *pptr = *pptrptr;+uint32_t firstcu, reqcu;+uint32_t lookbehindlength;+uint32_t lookbehindminlength;+uint32_t firstcuflags, reqcuflags;+uint32_t branchfirstcu, branchreqcu;+uint32_t branchfirstcuflags, branchreqcuflags;+PCRE2_SIZE length;+branch_chain bc;++/* If set, call the external function that checks for stack availability. */++if (cb->cx->stack_guard != NULL &&+ cb->cx->stack_guard(cb->parens_depth, cb->cx->stack_guard_data))+ {+ *errorcodeptr= ERR33;+ return 0;+ }++/* Miscellaneous initialization */++bc.outer = bcptr;+bc.current_branch = code;++firstcu = reqcu = 0;+firstcuflags = reqcuflags = REQ_UNSET;++/* Accumulate the length for use in the pre-compile phase. Start with the+length of the BRA and KET and any extra code units that are required at the+beginning. We accumulate in a local variable to save frequent testing of+lengthptr for NULL. We cannot do this by looking at the value of 'code' at the+start and end of each alternative, because compiled items are discarded during+the pre-compile phase so that the workspace is not exceeded. */++length = 2 + 2*LINK_SIZE + skipunits;++/* Remember if this is a lookbehind assertion, and if it is, save its length+and skip over the pattern offset. */++lookbehind = *code == OP_ASSERTBACK ||+ *code == OP_ASSERTBACK_NOT ||+ *code == OP_ASSERTBACK_NA;++if (lookbehind)+ {+ lookbehindlength = META_DATA(pptr[-1]);+ lookbehindminlength = *pptr;+ pptr += SIZEOFFSET;+ }+else lookbehindlength = lookbehindminlength = 0;++/* If this is a capturing subpattern, add to the chain of open capturing items+so that we can detect them if (*ACCEPT) is encountered. Note that only OP_CBRA+need be tested here; changing this opcode to one of its variants, e.g.+OP_SCBRAPOS, happens later, after the group has been compiled. */++if (*code == OP_CBRA)+ {+ capnumber = GET2(code, 1 + LINK_SIZE);+ capitem.number = capnumber;+ capitem.next = open_caps;+ capitem.assert_depth = cb->assert_depth;+ open_caps = &capitem;+ }++/* Offset is set zero to mark that this bracket is still open */++PUT(code, 1, 0);+code += 1 + LINK_SIZE + skipunits;++/* Loop for each alternative branch */++for (;;)+ {+ int branch_return;++ /* Insert OP_REVERSE or OP_VREVERSE if this is a lookbehind assertion. There+ is only a single mimimum length for the whole assertion. When the mimimum+ length is LOOKBEHIND_MAX it means that all branches are of fixed length,+ though not necessarily the same length. In this case, the original OP_REVERSE+ can be used. It can also be used if a branch in a variable length lookbehind+ has the same maximum and minimum. Otherwise, use OP_VREVERSE, which has both+ maximum and minimum values. */++ if (lookbehind && lookbehindlength > 0)+ {+ if (lookbehindminlength == LOOKBEHIND_MAX ||+ lookbehindminlength == lookbehindlength)+ {+ *code++ = OP_REVERSE;+ PUT2INC(code, 0, lookbehindlength);+ length += 1 + IMM2_SIZE;+ }+ else+ {+ *code++ = OP_VREVERSE;+ PUT2INC(code, 0, lookbehindminlength);+ PUT2INC(code, 0, lookbehindlength);+ length += 1 + 2*IMM2_SIZE;+ }+ }++ /* Now compile the branch; in the pre-compile phase its length gets added+ into the length. */++ if ((branch_return =+ compile_branch(&options, &xoptions, &code, &pptr, errorcodeptr,+ &branchfirstcu, &branchfirstcuflags, &branchreqcu, &branchreqcuflags,+ &bc, open_caps, cb, (lengthptr == NULL)? NULL : &length)) == 0)+ return 0;++ /* If a branch can match an empty string, so can the whole group. */++ if (branch_return < 0) okreturn = -1;++ /* In the real compile phase, there is some post-processing to be done. */++ if (lengthptr == NULL)+ {+ /* If this is the first branch, the firstcu and reqcu values for the+ branch become the values for the regex. */++ if (*last_branch != OP_ALT)+ {+ firstcu = branchfirstcu;+ firstcuflags = branchfirstcuflags;+ reqcu = branchreqcu;+ reqcuflags = branchreqcuflags;+ }++ /* If this is not the first branch, the first char and reqcu have to+ match the values from all the previous branches, except that if the+ previous value for reqcu didn't have REQ_VARY set, it can still match,+ and we set REQ_VARY for the group from this branch's value. */++ else+ {+ /* If we previously had a firstcu, but it doesn't match the new branch,+ we have to abandon the firstcu for the regex, but if there was+ previously no reqcu, it takes on the value of the old firstcu. */++ if (firstcuflags != branchfirstcuflags || firstcu != branchfirstcu)+ {+ if (firstcuflags < REQ_NONE)+ {+ if (reqcuflags >= REQ_NONE)+ {+ reqcu = firstcu;+ reqcuflags = firstcuflags;+ }+ }+ firstcuflags = REQ_NONE;+ }++ /* If we (now or from before) have no firstcu, a firstcu from the+ branch becomes a reqcu if there isn't a branch reqcu. */++ if (firstcuflags >= REQ_NONE && branchfirstcuflags < REQ_NONE &&+ branchreqcuflags >= REQ_NONE)+ {+ branchreqcu = branchfirstcu;+ branchreqcuflags = branchfirstcuflags;+ }++ /* Now ensure that the reqcus match */++ if (((reqcuflags & ~REQ_VARY) != (branchreqcuflags & ~REQ_VARY)) ||+ reqcu != branchreqcu)+ reqcuflags = REQ_NONE;+ else+ {+ reqcu = branchreqcu;+ reqcuflags |= branchreqcuflags; /* To "or" REQ_VARY if present */+ }+ }+ }++ /* Handle reaching the end of the expression, either ')' or end of pattern.+ In the real compile phase, go back through the alternative branches and+ reverse the chain of offsets, with the field in the BRA item now becoming an+ offset to the first alternative. If there are no alternatives, it points to+ the end of the group. The length in the terminating ket is always the length+ of the whole bracketed item. Return leaving the pointer at the terminating+ char. */++ if (META_CODE(*pptr) != META_ALT)+ {+ if (lengthptr == NULL)+ {+ PCRE2_SIZE branch_length = code - last_branch;+ do+ {+ PCRE2_SIZE prev_length = GET(last_branch, 1);+ PUT(last_branch, 1, branch_length);+ branch_length = prev_length;+ last_branch -= branch_length;+ }+ while (branch_length > 0);+ }++ /* Fill in the ket */++ *code = OP_KET;+ PUT(code, 1, (int)(code - start_bracket));+ code += 1 + LINK_SIZE;++ /* Set values to pass back */++ *codeptr = code;+ *pptrptr = pptr;+ *firstcuptr = firstcu;+ *firstcuflagsptr = firstcuflags;+ *reqcuptr = reqcu;+ *reqcuflagsptr = reqcuflags;+ if (lengthptr != NULL)+ {+ if (OFLOW_MAX - *lengthptr < length)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += length;+ }+ return okreturn;+ }++ /* Another branch follows. In the pre-compile phase, we can move the code+ pointer back to where it was for the start of the first branch. (That is,+ pretend that each branch is the only one.)++ In the real compile phase, insert an ALT node. Its length field points back+ to the previous branch while the bracket remains open. At the end the chain+ is reversed. It's done like this so that the start of the bracket has a+ zero offset until it is closed, making it possible to detect recursion. */++ if (lengthptr != NULL)+ {+ code = *codeptr + 1 + LINK_SIZE + skipunits;+ length += 1 + LINK_SIZE;+ }+ else+ {+ *code = OP_ALT;+ PUT(code, 1, (int)(code - last_branch));+ bc.current_branch = last_branch = code;+ code += 1 + LINK_SIZE;+ }++ /* Set the maximum lookbehind length for the next branch (if not in a+ lookbehind the value will be zero) and then advance past the vertical bar. */++ lookbehindlength = META_DATA(*pptr);+ pptr++;+ }+/* Control never reaches here */+}++++/*************************************************+* Check for anchored pattern *+*************************************************/++/* Try to find out if this is an anchored regular expression. Consider each+alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket+all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then+it's anchored. However, if this is a multiline pattern, then only OP_SOD will+be found, because ^ generates OP_CIRCM in that mode.++We can also consider a regex to be anchored if OP_SOM starts all its branches.+This is the code for \G, which means "match at start of match position, taking+into account the match offset".++A branch is also implicitly anchored if it starts with .* and DOTALL is set,+because that will try the rest of the pattern at all possible matching points,+so there is no point trying again.... er ....++.... except when the .* appears inside capturing parentheses, and there is a+subsequent back reference to those parentheses. We haven't enough information+to catch that case precisely.++At first, the best we could do was to detect when .* was in capturing brackets+and the highest back reference was greater than or equal to that level.+However, by keeping a bitmap of the first 31 back references, we can catch some+of the more common cases more precisely.++... A second exception is when the .* appears inside an atomic group, because+this prevents the number of characters it matches from being adjusted.++Arguments:+ code points to start of the compiled pattern+ bracket_map a bitmap of which brackets we are inside while testing; this+ handles up to substring 31; after that we just have to take+ the less precise approach+ cb points to the compile data block+ atomcount atomic group level+ inassert TRUE if in an assertion++Returns: TRUE or FALSE+*/++static BOOL+is_anchored(PCRE2_SPTR code, uint32_t bracket_map, compile_block *cb,+ int atomcount, BOOL inassert)+{+do {+ PCRE2_SPTR scode = first_significant_code(+ code + PRIV(OP_lengths)[*code], FALSE);+ int op = *scode;++ /* Non-capturing brackets */++ if (op == OP_BRA || op == OP_BRAPOS ||+ op == OP_SBRA || op == OP_SBRAPOS)+ {+ if (!is_anchored(scode, bracket_map, cb, atomcount, inassert))+ return FALSE;+ }++ /* Capturing brackets */++ else if (op == OP_CBRA || op == OP_CBRAPOS ||+ op == OP_SCBRA || op == OP_SCBRAPOS)+ {+ int n = GET2(scode, 1+LINK_SIZE);+ uint32_t new_map = bracket_map | ((n < 32)? (1u << n) : 1);+ if (!is_anchored(scode, new_map, cb, atomcount, inassert)) return FALSE;+ }++ /* Positive forward assertion */++ else if (op == OP_ASSERT || op == OP_ASSERT_NA)+ {+ if (!is_anchored(scode, bracket_map, cb, atomcount, TRUE)) return FALSE;+ }++ /* Condition. If there is no second branch, it can't be anchored. */++ else if (op == OP_COND || op == OP_SCOND)+ {+ if (scode[GET(scode,1)] != OP_ALT) return FALSE;+ if (!is_anchored(scode, bracket_map, cb, atomcount, inassert))+ return FALSE;+ }++ /* Atomic groups */++ else if (op == OP_ONCE)+ {+ if (!is_anchored(scode, bracket_map, cb, atomcount + 1, inassert))+ return FALSE;+ }++ /* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and+ it isn't in brackets that are or may be referenced or inside an atomic+ group or an assertion. Also the pattern must not contain *PRUNE or *SKIP,+ because these break the feature. Consider, for example, /(?s).*?(*PRUNE)b/+ with the subject "aab", which matches "b", i.e. not at the start of a line.+ There is also an option that disables auto-anchoring. */++ else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR ||+ op == OP_TYPEPOSSTAR))+ {+ if (scode[1] != OP_ALLANY || (bracket_map & cb->backref_map) != 0 ||+ atomcount > 0 || cb->had_pruneorskip || inassert ||+ (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)+ return FALSE;+ }++ /* Check for explicit anchoring */++ else if (op != OP_SOD && op != OP_SOM && op != OP_CIRC) return FALSE;++ code += GET(code, 1);+ }+while (*code == OP_ALT); /* Loop for each alternative */+return TRUE;+}++++/*************************************************+* Check for starting with ^ or .* *+*************************************************/++/* This is called to find out if every branch starts with ^ or .* so that+"first char" processing can be done to speed things up in multiline+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 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 the compiled pattern or a group+ bracket_map a bitmap of which brackets we are inside while testing; this+ handles up to substring 31; after that we just have to take+ the less precise approach+ cb points to the compile data+ atomcount atomic group level+ inassert TRUE if in an assertion++Returns: TRUE or FALSE+*/++static BOOL+is_startline(PCRE2_SPTR code, unsigned int bracket_map, compile_block *cb,+ int atomcount, BOOL inassert)+{+do {+ PCRE2_SPTR scode = first_significant_code(+ code + PRIV(OP_lengths)[*code], FALSE);+ int op = *scode;++ /* If we are at the start of a conditional assertion group, *both* the+ conditional assertion *and* what follows the condition must satisfy the test+ for start of line. Other kinds of condition fail. Note that there may be an+ auto-callout at the start of a condition. */++ if (op == OP_COND)+ {+ scode += 1 + LINK_SIZE;++ if (*scode == OP_CALLOUT) scode += PRIV(OP_lengths)[OP_CALLOUT];+ else if (*scode == OP_CALLOUT_STR) scode += GET(scode, 1 + 2*LINK_SIZE);++ switch (*scode)+ {+ case OP_CREF:+ case OP_DNCREF:+ case OP_RREF:+ case OP_DNRREF:+ case OP_FAIL:+ case OP_FALSE:+ case OP_TRUE:+ return FALSE;++ default: /* Assertion */+ if (!is_startline(scode, bracket_map, cb, atomcount, TRUE)) return FALSE;+ do scode += GET(scode, 1); while (*scode == OP_ALT);+ scode += 1 + LINK_SIZE;+ break;+ }+ scode = first_significant_code(scode, FALSE);+ op = *scode;+ }++ /* Non-capturing brackets */++ if (op == OP_BRA || op == OP_BRAPOS ||+ op == OP_SBRA || op == OP_SBRAPOS)+ {+ if (!is_startline(scode, bracket_map, cb, atomcount, inassert))+ return FALSE;+ }++ /* Capturing brackets */++ else if (op == OP_CBRA || op == OP_CBRAPOS ||+ op == OP_SCBRA || op == OP_SCBRAPOS)+ {+ int n = GET2(scode, 1+LINK_SIZE);+ unsigned int new_map = bracket_map | ((n < 32)? (1u << n) : 1);+ if (!is_startline(scode, new_map, cb, atomcount, inassert)) return FALSE;+ }++ /* Positive forward assertions */++ else if (op == OP_ASSERT || op == OP_ASSERT_NA)+ {+ if (!is_startline(scode, bracket_map, cb, atomcount, TRUE))+ return FALSE;+ }++ /* Atomic brackets */++ else if (op == OP_ONCE)+ {+ if (!is_startline(scode, bracket_map, cb, 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 or an assertion, and 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. There is also an option that disables this+ optimization. */++ else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)+ {+ if (scode[1] != OP_ANY || (bracket_map & cb->backref_map) != 0 ||+ atomcount > 0 || cb->had_pruneorskip || inassert ||+ (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)+ return FALSE;+ }++ /* Check for explicit circumflex; anything else gives a FALSE result. Note+ in particular that this includes atomic brackets OP_ONCE because the number+ of characters matched by .* cannot be adjusted inside them. */++ else if (op != OP_CIRC && op != OP_CIRCM) return FALSE;++ /* Move on to the next alternative */++ code += GET(code, 1);+ }+while (*code == OP_ALT); /* Loop for each alternative */+return TRUE;+}++++/*************************************************+* Scan compiled regex for recursion reference *+*************************************************/++/* This function scans through a compiled pattern until it finds an instance of+OP_RECURSE.++Arguments:+ code points to start of expression+ utf TRUE in UTF mode++Returns: pointer to the opcode for OP_RECURSE, or NULL if not found+*/++static PCRE2_SPTR+find_recurse(PCRE2_SPTR code, BOOL utf)+{+for (;;)+ {+ PCRE2_UCHAR c = *code;+ if (c == OP_END) return NULL;+ if (c == OP_RECURSE) return code;++ /* XCLASS is used for classes that cannot be represented just by a bit map.+ This includes negated single high-valued characters. CALLOUT_STR is used for+ callouts with string arguments. In both cases the length in the table is+ zero; the actual length is stored in the compiled code. */++ if (c == OP_XCLASS) code += GET(code, 1);+ else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE);++ /* Otherwise, we can get the item's length from the table, except that for+ repeated character types, we have to test for \p and \P, which have an extra+ two code units of parameters, and for MARK/PRUNE/SKIP/THEN with an argument,+ we must add in its length. */++ else+ {+ switch(c)+ {+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;+ break;++ case OP_TYPEPOSUPTO:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)+ code += 2;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ code += code[1];+ break;+ }++ /* Add in the fixed length from the table */++ code += PRIV(OP_lengths)[c];++ /* In UTF-8 and UTF-16 modes, opcodes that are followed by a character may+ be followed by a multi-unit character. The length in the table is a+ minimum, so we have to arrange to skip the extra units. */++#ifdef MAYBE_UTF_MULTI+ if (utf) switch(c)+ {+ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_EXACT:+ case OP_EXACTI:+ case OP_NOTEXACT:+ case OP_NOTEXACTI:+ case OP_UPTO:+ case OP_UPTOI:+ case OP_NOTUPTO:+ case OP_NOTUPTOI:+ case OP_MINUPTO:+ case OP_MINUPTOI:+ case OP_NOTMINUPTO:+ case OP_NOTMINUPTOI:+ case OP_POSUPTO:+ case OP_POSUPTOI:+ case OP_NOTPOSUPTO:+ case OP_NOTPOSUPTOI:+ case OP_STAR:+ case OP_STARI:+ case OP_NOTSTAR:+ case OP_NOTSTARI:+ case OP_MINSTAR:+ case OP_MINSTARI:+ case OP_NOTMINSTAR:+ case OP_NOTMINSTARI:+ case OP_POSSTAR:+ case OP_POSSTARI:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSSTARI:+ case OP_PLUS:+ case OP_PLUSI:+ case OP_NOTPLUS:+ case OP_NOTPLUSI:+ case OP_MINPLUS:+ case OP_MINPLUSI:+ case OP_NOTMINPLUS:+ case OP_NOTMINPLUSI:+ case OP_POSPLUS:+ case OP_POSPLUSI:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSPLUSI:+ case OP_QUERY:+ case OP_QUERYI:+ case OP_NOTQUERY:+ case OP_NOTQUERYI:+ case OP_MINQUERY:+ case OP_MINQUERYI:+ case OP_NOTMINQUERY:+ case OP_NOTMINQUERYI:+ case OP_POSQUERY:+ case OP_POSQUERYI:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSQUERYI:+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);+ break;+ }+#else+ (void)(utf); /* Keep compiler happy by referencing function argument */+#endif /* MAYBE_UTF_MULTI */+ }+ }+}++++/*************************************************+* Check for asserted fixed first code unit *+*************************************************/++/* During compilation, the "first code unit" settings from forward assertions+are discarded, because they can cause conflicts with actual literals that+follow. However, if we end up without a first code unit setting for an+unanchored pattern, it is worth scanning the regex to see if there is an+initial asserted first code unit. If all branches start with the same asserted+code unit, or with a non-conditional bracket all of whose alternatives start+with the same asserted code unit (recurse ad lib), then we return that code+unit, with the flags set to zero or REQ_CASELESS; otherwise return zero with+REQ_NONE in the flags.++Arguments:+ code points to start of compiled pattern+ flags points to the first code unit flags+ inassert non-zero if in an assertion++Returns: the fixed first code unit, or 0 with REQ_NONE in flags+*/++static uint32_t+find_firstassertedcu(PCRE2_SPTR code, uint32_t *flags, uint32_t inassert)+{+uint32_t c = 0;+uint32_t cflags = REQ_NONE;++*flags = REQ_NONE;+do {+ uint32_t d;+ uint32_t dflags;+ int xl = (*code == OP_CBRA || *code == OP_SCBRA ||+ *code == OP_CBRAPOS || *code == OP_SCBRAPOS)? IMM2_SIZE:0;+ PCRE2_SPTR scode = first_significant_code(code + 1+LINK_SIZE + xl, TRUE);+ PCRE2_UCHAR op = *scode;++ switch(op)+ {+ default:+ return 0;++ case OP_BRA:+ case OP_BRAPOS:+ case OP_CBRA:+ case OP_SCBRA:+ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ case OP_ASSERT:+ case OP_ASSERT_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ d = find_firstassertedcu(scode, &dflags, inassert ++ ((op == OP_ASSERT || op == OP_ASSERT_NA)?1:0));+ if (dflags >= REQ_NONE) return 0;+ if (cflags >= REQ_NONE) { c = d; cflags = dflags; }+ else if (c != d || cflags != dflags) return 0;+ break;++ case OP_EXACT:+ scode += IMM2_SIZE;+ /* Fall through */++ case OP_CHAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSPLUS:+ if (inassert == 0) return 0;+ if (cflags >= REQ_NONE) { c = scode[1]; cflags = 0; }+ else if (c != scode[1]) return 0;+ break;++ case OP_EXACTI:+ scode += IMM2_SIZE;+ /* Fall through */++ case OP_CHARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSPLUSI:+ if (inassert == 0) return 0;++ /* If the character is more than one code unit long, we cannot set its+ first code unit when matching caselessly. Later scanning may pick up+ multiple code units. */++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (scode[1] >= 0x80) return 0;+#elif PCRE2_CODE_UNIT_WIDTH == 16+ if (scode[1] >= 0xd800 && scode[1] <= 0xdfff) return 0;+#endif+#endif++ if (cflags >= REQ_NONE) { c = scode[1]; cflags = REQ_CASELESS; }+ else if (c != scode[1]) return 0;+ break;+ }++ code += GET(code, 1);+ }+while (*code == OP_ALT);++*flags = cflags;+return c;+}++++/*************************************************+* Add an entry to the name/number table *+*************************************************/++/* This function is called between compiling passes to add an entry to the+name/number table, maintaining alphabetical order. Checking for permitted+and forbidden duplicates has already been done.++Arguments:+ cb the compile data block+ name the name to add+ length the length of the name+ groupno the group number+ tablecount the count of names in the table so far++Returns: nothing+*/++static void+add_name_to_table(compile_block *cb, PCRE2_SPTR name, int length,+ unsigned int groupno, uint32_t tablecount)+{+uint32_t i;+PCRE2_UCHAR *slot = cb->name_table;++for (i = 0; i < tablecount; i++)+ {+ int crc = memcmp(name, slot+IMM2_SIZE, CU2BYTES(length));+ if (crc == 0 && slot[IMM2_SIZE+length] != 0)+ crc = -1; /* Current name is a substring */++ /* Make space in the table and break the loop for an earlier name. For a+ duplicate or later name, carry on. We do this for duplicates so that in the+ simple case (when ?(| is not used) they are in order of their numbers. In all+ cases they are in the order in which they appear in the pattern. */++ if (crc < 0)+ {+ (void)memmove(slot + cb->name_entry_size, slot,+ CU2BYTES((tablecount - i) * cb->name_entry_size));+ break;+ }++ /* Continue the loop for a later or duplicate name */++ slot += cb->name_entry_size;+ }++PUT2(slot, 0, groupno);+memcpy(slot + IMM2_SIZE, name, CU2BYTES(length));++/* Add a terminating zero and fill the rest of the slot with zeroes so that+the memory is all initialized. Otherwise valgrind moans about uninitialized+memory when saving serialized compiled patterns. */++memset(slot + IMM2_SIZE + length, 0,+ CU2BYTES(cb->name_entry_size - length - IMM2_SIZE));+}++++/*************************************************+* Skip in parsed pattern *+*************************************************/++/* This function is called to skip parts of the parsed pattern when finding the+length of a lookbehind branch. It is called after (*ACCEPT) and (*FAIL) to find+the end of the branch, it is called to skip over an internal lookaround or+(DEFINE) group, and it is also called to skip to the end of a class, during+which it will never encounter nested groups (but there's no need to have+special code for that).++When called to find the end of a branch or group, pptr must point to the first+meta code inside the branch, not the branch-starting code. In other cases it+can point to the item that causes the function to be called.++Arguments:+ pptr current pointer to skip from+ skiptype PSKIP_CLASS when skipping to end of class+ PSKIP_ALT when META_ALT ends the skip+ PSKIP_KET when only META_KET ends the skip++Returns: new value of pptr+ NULL if META_END is reached - should never occur+ or for an unknown meta value - likewise+*/++static uint32_t *+parsed_skip(uint32_t *pptr, uint32_t skiptype)+{+uint32_t nestlevel = 0;++for (;; pptr++)+ {+ uint32_t meta = META_CODE(*pptr);++ switch(meta)+ {+ default: /* Just skip over most items */+ if (meta < META_END) continue; /* Literal */+ break;++ /* This should never occur. */++ case META_END:+ return NULL;++ /* The data for these items is variable in length. */++ case META_BACKREF: /* Offset is present only if group >= 10 */+ if (META_DATA(*pptr) >= 10) pptr += SIZEOFFSET;+ break;++ case META_ESCAPE: /* A few escapes are followed by data items. */+ switch (META_DATA(*pptr))+ {+ case ESC_P:+ case ESC_p:+ pptr += 1;+ break;++ case ESC_g:+ case ESC_k:+ pptr += 1 + SIZEOFFSET;+ break;+ }+ break;++ case META_MARK: /* Add the length of the name. */+ case META_COMMIT_ARG:+ case META_PRUNE_ARG:+ case META_SKIP_ARG:+ case META_THEN_ARG:+ pptr += pptr[1];+ break;++ /* These are the "active" items in this loop. */++ case META_CLASS_END:+ if (skiptype == PSKIP_CLASS) return pptr;+ break;++ case META_ATOMIC:+ case META_CAPTURE:+ case META_COND_ASSERT:+ case META_COND_DEFINE:+ case META_COND_NAME:+ case META_COND_NUMBER:+ case META_COND_RNAME:+ case META_COND_RNUMBER:+ case META_COND_VERSION:+ case META_LOOKAHEAD:+ case META_LOOKAHEADNOT:+ case META_LOOKAHEAD_NA:+ case META_LOOKBEHIND:+ case META_LOOKBEHINDNOT:+ case META_LOOKBEHIND_NA:+ case META_NOCAPTURE:+ case META_SCRIPT_RUN:+ nestlevel++;+ break;++ case META_ALT:+ if (nestlevel == 0 && skiptype == PSKIP_ALT) return pptr;+ break;++ case META_KET:+ if (nestlevel == 0) return pptr;+ nestlevel--;+ break;+ }++ /* The extra data item length for each meta is in a table. */++ meta = (meta >> 16) & 0x7fff;+ if (meta >= sizeof(meta_extra_lengths)) return NULL;+ pptr += meta_extra_lengths[meta];+ }+/* Control never reaches here */+return pptr;+}++++/*************************************************+* Find length of a parsed group *+*************************************************/++/* This is called for nested groups within a branch of a lookbehind whose+length is being computed. On entry, the pointer must be at the first element+after the group initializing code. On exit it points to OP_KET. Caching is used+to improve processing speed when the same capturing group occurs many times.++Arguments:+ pptrptr pointer to pointer in the parsed pattern+ minptr where to return the minimum length+ isinline FALSE if a reference or recursion; TRUE for inline group+ errcodeptr pointer to the errorcode+ lcptr pointer to the loop counter+ group number of captured group or -1 for a non-capturing group+ recurses chain of recurse_check to catch mutual recursion+ cb pointer to the compile data++Returns: the maximum group length or a negative number+*/++static int+get_grouplength(uint32_t **pptrptr, int *minptr, BOOL isinline, int *errcodeptr,+ int *lcptr, int group, parsed_recurse_check *recurses, compile_block *cb)+{+uint32_t *gi = cb->groupinfo + 2 * group;+int branchlength, branchminlength;+int grouplength = -1;+int groupminlength = INT_MAX;++/* The cache can be used only if there is no possibility of there being two+groups with the same number. We do not need to set the end pointer for a group+that is being processed as a back reference or recursion, but we must do so for+an inline group. */++if (group > 0 && (cb->external_flags & PCRE2_DUPCAPUSED) == 0)+ {+ uint32_t groupinfo = gi[0];+ if ((groupinfo & GI_NOT_FIXED_LENGTH) != 0) return -1;+ if ((groupinfo & GI_SET_FIXED_LENGTH) != 0)+ {+ if (isinline) *pptrptr = parsed_skip(*pptrptr, PSKIP_KET);+ *minptr = gi[1];+ return groupinfo & GI_FIXED_LENGTH_MASK;+ }+ }++/* Scan the group. In this case we find the end pointer of necessity. */++for(;;)+ {+ branchlength = get_branchlength(pptrptr, &branchminlength, errcodeptr, lcptr,+ recurses, cb);+ if (branchlength < 0) goto ISNOTFIXED;+ if (branchlength > grouplength) grouplength = branchlength;+ if (branchminlength < groupminlength) groupminlength = branchminlength;+ if (**pptrptr == META_KET) break;+ *pptrptr += 1; /* Skip META_ALT */+ }++if (group > 0)+ {+ gi[0] |= (uint32_t)(GI_SET_FIXED_LENGTH | grouplength);+ gi[1] = groupminlength;+ }++*minptr = groupminlength;+return grouplength;++ISNOTFIXED:+if (group > 0) gi[0] |= GI_NOT_FIXED_LENGTH;+return -1;+}++++/*************************************************+* Find length of a parsed branch *+*************************************************/++/* Return fixed maximum and minimum lengths for a branch in a lookbehind,+giving an error if the length is not limited. On entry, *pptrptr points to the+first element inside the branch. On exit it is set to point to the ALT or KET.++Arguments:+ pptrptr pointer to pointer in the parsed pattern+ minptr where to return the minimum length+ errcodeptr pointer to error code+ lcptr pointer to loop counter+ recurses chain of recurse_check to catch mutual recursion+ cb pointer to compile block++Returns: the maximum length, or a negative value on error+*/++static int+get_branchlength(uint32_t **pptrptr, int *minptr, int *errcodeptr, int *lcptr,+ parsed_recurse_check *recurses, compile_block *cb)+{+int branchlength = 0;+int branchminlength = 0;+int grouplength, groupminlength;+uint32_t lastitemlength = 0;+uint32_t lastitemminlength = 0;+uint32_t *pptr = *pptrptr;+PCRE2_SIZE offset;+parsed_recurse_check this_recurse;++/* A large and/or complex regex can take too long to process. This can happen+more often when (?| groups are present in the pattern because their length+cannot be cached. */++if ((*lcptr)++ > 2000)+ {+ *errcodeptr = ERR35; /* Lookbehind is too complicated */+ return -1;+ }++/* Scan the branch, accumulating the length. */++for (;; pptr++)+ {+ parsed_recurse_check *r;+ uint32_t *gptr, *gptrend;+ uint32_t escape;+ uint32_t group = 0;+ uint32_t itemlength = 0;+ uint32_t itemminlength = 0;+ uint32_t min, max;++ if (*pptr < META_END)+ {+ itemlength = itemminlength = 1;+ }++ else switch (META_CODE(*pptr))+ {+ case META_KET:+ case META_ALT:+ goto EXIT;++ /* (*ACCEPT) and (*FAIL) terminate the branch, but we must skip to the+ actual termination. */++ case META_ACCEPT:+ case META_FAIL:+ pptr = parsed_skip(pptr, PSKIP_ALT);+ if (pptr == NULL) goto PARSED_SKIP_FAILED;+ goto EXIT;++ case META_MARK:+ case META_COMMIT_ARG:+ case META_PRUNE_ARG:+ case META_SKIP_ARG:+ case META_THEN_ARG:+ pptr += pptr[1] + 1;+ break;++ case META_CIRCUMFLEX:+ case META_COMMIT:+ case META_DOLLAR:+ case META_PRUNE:+ case META_SKIP:+ case META_THEN:+ break;++ case META_OPTIONS:+ pptr += 2;+ break;++ case META_BIGVALUE:+ itemlength = itemminlength = 1;+ pptr += 1;+ break;++ case META_CLASS:+ case META_CLASS_NOT:+ itemlength = itemminlength = 1;+ pptr = parsed_skip(pptr, PSKIP_CLASS);+ if (pptr == NULL) goto PARSED_SKIP_FAILED;+ break;++ case META_CLASS_EMPTY_NOT:+ case META_DOT:+ itemlength = itemminlength = 1;+ break;++ case META_CALLOUT_NUMBER:+ pptr += 3;+ break;++ case META_CALLOUT_STRING:+ pptr += 3 + SIZEOFFSET;+ break;++ /* Only some escapes consume a character. Of those, \R can match one or two+ characters, but \X is never allowed because it matches an unknown number of+ characters. \C is allowed only in 32-bit and non-UTF 8/16-bit modes. */++ case META_ESCAPE:+ escape = META_DATA(*pptr);+ if (escape == ESC_X) return -1;+ if (escape == ESC_R)+ {+ itemminlength = 1;+ itemlength = 2;+ }+ else if (escape > ESC_b && escape < ESC_Z)+ {+#if PCRE2_CODE_UNIT_WIDTH != 32+ if ((cb->external_options & PCRE2_UTF) != 0 && escape == ESC_C)+ {+ *errcodeptr = ERR36;+ return -1;+ }+#endif+ itemlength = itemminlength = 1;+ if (escape == ESC_p || escape == ESC_P) pptr++; /* Skip prop data */+ }+ break;++ /* Lookaheads do not contribute to the length of this branch, but they may+ contain lookbehinds within them whose lengths need to be set. */++ case META_LOOKAHEAD:+ case META_LOOKAHEADNOT:+ case META_LOOKAHEAD_NA:+ *errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb, lcptr);+ if (*errcodeptr != 0) return -1;++ /* Ignore any qualifiers that follow a lookahead assertion. */++ switch (pptr[1])+ {+ case META_ASTERISK:+ case META_ASTERISK_PLUS:+ case META_ASTERISK_QUERY:+ case META_PLUS:+ case META_PLUS_PLUS:+ case META_PLUS_QUERY:+ case META_QUERY:+ case META_QUERY_PLUS:+ case META_QUERY_QUERY:+ pptr++;+ break;++ case META_MINMAX:+ case META_MINMAX_PLUS:+ case META_MINMAX_QUERY:+ pptr += 3;+ break;++ default:+ break;+ }+ break;++ /* A nested lookbehind does not contribute any length to this lookbehind,+ but must itself be checked and have its lengths set. */++ case META_LOOKBEHIND:+ case META_LOOKBEHINDNOT:+ case META_LOOKBEHIND_NA:+ if (!set_lookbehind_lengths(&pptr, errcodeptr, lcptr, recurses, cb))+ return -1;+ break;++ /* Back references and recursions are handled by very similar code. At this+ stage, the names generated in the parsing pass are available, but the main+ name table has not yet been created. So for the named varieties, scan the+ list of names in order to get the number of the first one in the pattern,+ and whether or not this name is duplicated. */++ case META_BACKREF_BYNAME:+ if ((cb->external_options & PCRE2_MATCH_UNSET_BACKREF) != 0)+ goto ISNOTFIXED;+ /* Fall through */++ case META_RECURSE_BYNAME:+ {+ int i;+ PCRE2_SPTR name;+ BOOL is_dupname = FALSE;+ named_group *ng = cb->named_groups;+ uint32_t meta_code = META_CODE(*pptr);+ uint32_t length = *(++pptr);++ GETPLUSOFFSET(offset, pptr);+ name = cb->start_pattern + offset;+ for (i = 0; i < cb->names_found; i++, ng++)+ {+ if (length == ng->length && PRIV(strncmp)(name, ng->name, length) == 0)+ {+ group = ng->number;+ is_dupname = ng->isdup;+ break;+ }+ }++ if (group == 0)+ {+ *errcodeptr = ERR15; /* Non-existent subpattern */+ cb->erroroffset = offset;+ return -1;+ }++ /* A numerical back reference can be fixed length if duplicate capturing+ groups are not being used. A non-duplicate named back reference can also+ be handled. */++ if (meta_code == META_RECURSE_BYNAME ||+ (!is_dupname && (cb->external_flags & PCRE2_DUPCAPUSED) == 0))+ goto RECURSE_OR_BACKREF_LENGTH; /* Handle as a numbered version. */+ }+ goto ISNOTFIXED; /* Duplicate name or number */++ /* The offset values for back references < 10 are in a separate vector+ because otherwise they would use more than two parsed pattern elements on+ 64-bit systems. */++ case META_BACKREF:+ if ((cb->external_options & PCRE2_MATCH_UNSET_BACKREF) != 0 ||+ (cb->external_flags & PCRE2_DUPCAPUSED) != 0)+ goto ISNOTFIXED;+ group = META_DATA(*pptr);+ if (group < 10)+ {+ offset = cb->small_ref_offset[group];+ goto RECURSE_OR_BACKREF_LENGTH;+ }++ /* Fall through */+ /* For groups >= 10 - picking up group twice does no harm. */++ /* A true recursion implies not fixed length, but a subroutine call may+ be OK. Back reference "recursions" are also failed. */++ case META_RECURSE:+ group = META_DATA(*pptr);+ GETPLUSOFFSET(offset, pptr);++ RECURSE_OR_BACKREF_LENGTH:+ if (group > cb->bracount)+ {+ cb->erroroffset = offset;+ *errcodeptr = ERR15; /* Non-existent subpattern */+ return -1;+ }+ if (group == 0) goto ISNOTFIXED; /* Local recursion */+ for (gptr = cb->parsed_pattern; *gptr != META_END; gptr++)+ {+ if (META_CODE(*gptr) == META_BIGVALUE) gptr++;+ else if (*gptr == (META_CAPTURE | group)) break;+ }++ /* We must start the search for the end of the group at the first meta code+ inside the group. Otherwise it will be treated as an enclosed group. */++ gptrend = parsed_skip(gptr + 1, PSKIP_KET);+ if (gptrend == NULL) goto PARSED_SKIP_FAILED;+ if (pptr > gptr && pptr < gptrend) goto ISNOTFIXED; /* Local recursion */+ for (r = recurses; r != NULL; r = r->prev) if (r->groupptr == gptr) break;+ if (r != NULL) goto ISNOTFIXED; /* Mutual recursion */+ this_recurse.prev = recurses;+ this_recurse.groupptr = gptr;++ /* We do not need to know the position of the end of the group, that is,+ gptr is not used after the call to get_grouplength(). Setting the second+ argument FALSE stops it scanning for the end when the length can be found+ in the cache. */++ gptr++;+ grouplength = get_grouplength(&gptr, &groupminlength, FALSE, errcodeptr,+ lcptr, group, &this_recurse, cb);+ if (grouplength < 0)+ {+ if (*errcodeptr == 0) goto ISNOTFIXED;+ return -1; /* Error already set */+ }+ itemlength = grouplength;+ itemminlength = groupminlength;+ break;++ /* A (DEFINE) group is never obeyed inline and so it does not contribute to+ the length of this branch. Skip from the following item to the next+ unpaired ket. */++ case META_COND_DEFINE:+ pptr = parsed_skip(pptr + 1, PSKIP_KET);+ break;++ /* Check other nested groups - advance past the initial data for each type+ and then seek a fixed length with get_grouplength(). */++ case META_COND_NAME:+ case META_COND_NUMBER:+ case META_COND_RNAME:+ case META_COND_RNUMBER:+ pptr += 2 + SIZEOFFSET;+ goto CHECK_GROUP;++ case META_COND_ASSERT:+ pptr += 1;+ goto CHECK_GROUP;++ case META_COND_VERSION:+ pptr += 4;+ goto CHECK_GROUP;++ case META_CAPTURE:+ group = META_DATA(*pptr);+ /* Fall through */++ case META_ATOMIC:+ case META_NOCAPTURE:+ case META_SCRIPT_RUN:+ pptr++;+ CHECK_GROUP:+ grouplength = get_grouplength(&pptr, &groupminlength, TRUE, errcodeptr,+ lcptr, group, recurses, cb);+ if (grouplength < 0) return -1;+ itemlength = grouplength;+ itemminlength = groupminlength;+ break;++ case META_QUERY:+ case META_QUERY_PLUS:+ case META_QUERY_QUERY:+ min = 0;+ max = 1;+ goto REPETITION;++ /* Exact repetition is OK; variable repetition is not. A repetition of zero+ must subtract the length that has already been added. */++ case META_MINMAX:+ case META_MINMAX_PLUS:+ case META_MINMAX_QUERY:+ min = pptr[1];+ max = pptr[2];+ pptr += 2;++ REPETITION:+ if (max != REPEAT_UNLIMITED)+ {+ if (lastitemlength != 0 && /* Should not occur, but just in case */+ max != 0 &&+ (INT_MAX - branchlength)/lastitemlength < max - 1)+ {+ *errcodeptr = ERR87; /* Integer overflow; lookbehind too big */+ return -1;+ }+ if (min == 0) branchminlength -= lastitemminlength;+ else itemminlength = (min - 1) * lastitemminlength;+ if (max == 0) branchlength -= lastitemlength;+ else itemlength = (max - 1) * lastitemlength;+ break;+ }+ /* Fall through */++ /* Any other item means this branch does not have a fixed length. */++ default:+ ISNOTFIXED:+ *errcodeptr = ERR25; /* Not fixed length */+ return -1;+ }++ /* Add the item length to the branchlength, checking for integer overflow and+ for the branch length exceeding the overall limit. Later, if there is at+ least one variable-length branch in the group, there is a test for the+ (smaller) variable-length branch length limit. */++ if (INT_MAX - branchlength < (int)itemlength ||+ (branchlength += itemlength) > LOOKBEHIND_MAX)+ {+ *errcodeptr = ERR87;+ return -1;+ }++ branchminlength += itemminlength;++ /* Save this item length for use if the next item is a quantifier. */++ lastitemlength = itemlength;+ lastitemminlength = itemminlength;+ }++EXIT:+*pptrptr = pptr;+*minptr = branchminlength;+return branchlength;++PARSED_SKIP_FAILED:+*errcodeptr = ERR90;+return -1;+}++++/*************************************************+* Set lengths in a lookbehind *+*************************************************/++/* This function is called for each lookbehind, to set the lengths in its+branches. An error occurs if any branch does not have a limited maximum length+that is less than the limit (65535). On exit, the pointer must be left on the+final ket.++The function also maintains the max_lookbehind value. Any lookbehind branch+that contains a nested lookbehind may actually look further back than the+length of the branch. The additional amount is passed back from+get_branchlength() as an "extra" value.++Arguments:+ pptrptr pointer to pointer in the parsed pattern+ errcodeptr pointer to error code+ lcptr pointer to loop counter+ recurses chain of recurse_check to catch mutual recursion+ cb pointer to compile block++Returns: TRUE if all is well+ FALSE otherwise, with error code and offset set+*/++static BOOL+set_lookbehind_lengths(uint32_t **pptrptr, int *errcodeptr, int *lcptr,+ parsed_recurse_check *recurses, compile_block *cb)+{+PCRE2_SIZE offset;+uint32_t *bptr = *pptrptr;+uint32_t *gbptr = bptr;+int maxlength = 0;+int minlength = INT_MAX;+BOOL variable = FALSE;++READPLUSOFFSET(offset, bptr); /* Offset for error messages */+*pptrptr += SIZEOFFSET;++/* Each branch can have a different maximum length, but we can keep only a+single minimum for the whole group, because there's nowhere to save individual+values in the META_ALT item. */++do+ {+ int branchlength, branchminlength;++ *pptrptr += 1;+ branchlength = get_branchlength(pptrptr, &branchminlength, errcodeptr, lcptr,+ recurses, cb);++ if (branchlength < 0)+ {+ /* The errorcode and offset may already be set from a nested lookbehind. */+ if (*errcodeptr == 0) *errcodeptr = ERR25;+ if (cb->erroroffset == PCRE2_UNSET) cb->erroroffset = offset;+ return FALSE;+ }++ if (branchlength != branchminlength) variable = TRUE;+ if (branchminlength < minlength) minlength = branchminlength;+ if (branchlength > maxlength) maxlength = branchlength;+ if (branchlength > cb->max_lookbehind) cb->max_lookbehind = branchlength;+ *bptr |= branchlength; /* branchlength never more than 65535 */+ bptr = *pptrptr;+ }+while (META_CODE(*bptr) == META_ALT);++/* If any branch is of variable length, the whole lookbehind is of variable+length. If the maximum length of any branch exceeds the maximum for variable+lookbehinds, give an error. Otherwise, the minimum length is set in the word+that follows the original group META value. For a fixed-length lookbehind, this+is set to LOOKBEHIND_MAX, to indicate that each branch is of a fixed (but+possibly different) length. */++if (variable)+ {+ gbptr[1] = minlength;+ if ((uint32_t)maxlength > cb->max_varlookbehind)+ {+ *errcodeptr = ERR100;+ cb->erroroffset = offset;+ return FALSE;+ }+ }+else gbptr[1] = LOOKBEHIND_MAX;+++gbptr[1] = variable? minlength : LOOKBEHIND_MAX;+return TRUE;+}++++/*************************************************+* Check parsed pattern lookbehinds *+*************************************************/++/* This function is called at the end of parsing a pattern if any lookbehinds+were encountered. It scans the parsed pattern for them, calling+set_lookbehind_lengths() for each one. At the start, the errorcode is zero and+the error offset is marked unset. The enables the functions above not to+override settings from deeper nestings.++This function is called recursively from get_branchlength() for lookaheads in+order to process any lookbehinds that they may contain. It stops when it hits a+non-nested closing parenthesis in this case, returning a pointer to it.++Arguments+ pptr points to where to start (start of pattern or start of lookahead)+ retptr if not NULL, return the ket pointer here+ recurses chain of recurse_check to catch mutual recursion+ cb points to the compile block+ lcptr points to loop counter++Returns: 0 on success, or an errorcode (cb->erroroffset will be set)+*/++static int+check_lookbehinds(uint32_t *pptr, uint32_t **retptr,+ parsed_recurse_check *recurses, compile_block *cb, int *lcptr)+{+int errorcode = 0;+int nestlevel = 0;++cb->erroroffset = PCRE2_UNSET;++for (; *pptr != META_END; pptr++)+ {+ if (*pptr < META_END) continue; /* Literal */++ switch (META_CODE(*pptr))+ {+ default:+ return ERR70; /* Unrecognized meta code */++ case META_ESCAPE:+ if (*pptr - META_ESCAPE == ESC_P || *pptr - META_ESCAPE == ESC_p)+ pptr += 1;+ break;++ case META_KET:+ if (--nestlevel < 0)+ {+ if (retptr != NULL) *retptr = pptr;+ return 0;+ }+ break;++ case META_ATOMIC:+ case META_CAPTURE:+ case META_COND_ASSERT:+ case META_LOOKAHEAD:+ case META_LOOKAHEADNOT:+ case META_LOOKAHEAD_NA:+ case META_NOCAPTURE:+ case META_SCRIPT_RUN:+ nestlevel++;+ break;++ case META_ACCEPT:+ case META_ALT:+ case META_ASTERISK:+ case META_ASTERISK_PLUS:+ case META_ASTERISK_QUERY:+ case META_BACKREF:+ case META_CIRCUMFLEX:+ case META_CLASS:+ case META_CLASS_EMPTY:+ case META_CLASS_EMPTY_NOT:+ case META_CLASS_END:+ case META_CLASS_NOT:+ case META_COMMIT:+ case META_DOLLAR:+ case META_DOT:+ case META_FAIL:+ case META_PLUS:+ case META_PLUS_PLUS:+ case META_PLUS_QUERY:+ case META_PRUNE:+ case META_QUERY:+ case META_QUERY_PLUS:+ case META_QUERY_QUERY:+ case META_RANGE_ESCAPED:+ case META_RANGE_LITERAL:+ case META_SKIP:+ case META_THEN:+ break;++ case META_RECURSE:+ pptr += SIZEOFFSET;+ break;++ case META_BACKREF_BYNAME:+ case META_RECURSE_BYNAME:+ pptr += 1 + SIZEOFFSET;+ break;++ case META_COND_DEFINE:+ pptr += SIZEOFFSET;+ nestlevel++;+ break;++ case META_COND_NAME:+ case META_COND_NUMBER:+ case META_COND_RNAME:+ case META_COND_RNUMBER:+ pptr += 1 + SIZEOFFSET;+ nestlevel++;+ break;++ case META_COND_VERSION:+ pptr += 3;+ nestlevel++;+ break;++ case META_CALLOUT_STRING:+ pptr += 3 + SIZEOFFSET;+ break;++ case META_BIGVALUE:+ case META_POSIX:+ case META_POSIX_NEG:+ pptr += 1;+ break;++ case META_MINMAX:+ case META_MINMAX_QUERY:+ case META_MINMAX_PLUS:+ case META_OPTIONS:+ pptr += 2;+ break;++ case META_CALLOUT_NUMBER:+ pptr += 3;+ break;++ case META_MARK:+ case META_COMMIT_ARG:+ case META_PRUNE_ARG:+ case META_SKIP_ARG:+ case META_THEN_ARG:+ pptr += 1 + pptr[1];+ break;++ case META_LOOKBEHIND:+ case META_LOOKBEHINDNOT:+ case META_LOOKBEHIND_NA:+ if (!set_lookbehind_lengths(&pptr, &errorcode, lcptr, recurses, cb))+ return errorcode;+ break;+ }+ }++return 0;+}++++/*************************************************+* External function to compile a pattern *+*************************************************/++/* This function reads a regular expression in the form of a string and returns+a pointer to a block of store holding a compiled version of the expression.++Arguments:+ pattern the regular expression+ patlen the length of the pattern, or PCRE2_ZERO_TERMINATED+ options option bits+ errorptr pointer to errorcode+ erroroffset pointer to error offset+ ccontext points to a compile context or is NULL++Returns: pointer to compiled data block, or NULL on error,+ with errorcode and erroroffset set+*/++PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION+pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE patlen, uint32_t options,+ int *errorptr, PCRE2_SIZE *erroroffset, pcre2_compile_context *ccontext)+{+BOOL utf; /* Set TRUE for UTF mode */+BOOL ucp; /* Set TRUE for UCP mode */+BOOL has_lookbehind = FALSE; /* Set TRUE if a lookbehind is found */+BOOL zero_terminated; /* Set TRUE for zero-terminated pattern */+pcre2_real_code *re = NULL; /* What we will return */+compile_block cb; /* "Static" compile-time data */+const uint8_t *tables; /* Char tables base pointer */++PCRE2_UCHAR *code; /* Current pointer in compiled code */+PCRE2_SPTR codestart; /* Start of compiled code */+PCRE2_SPTR ptr; /* Current pointer in pattern */+uint32_t *pptr; /* Current pointer in parsed pattern */++PCRE2_SIZE length = 1; /* Allow for final END opcode */+PCRE2_SIZE usedlength; /* Actual length used */+PCRE2_SIZE re_blocksize; /* Size of memory block */+PCRE2_SIZE big32count = 0; /* 32-bit literals >= 0x80000000 */+PCRE2_SIZE parsed_size_needed; /* Needed for parsed pattern */++uint32_t firstcuflags, reqcuflags; /* Type of first/req code unit */+uint32_t firstcu, reqcu; /* Value of first/req code unit */+uint32_t setflags = 0; /* NL and BSR set flags */++uint32_t skipatstart; /* When checking (*UTF) etc */+uint32_t limit_heap = UINT32_MAX;+uint32_t limit_match = UINT32_MAX; /* Unset match limits */+uint32_t limit_depth = UINT32_MAX;++int newline = 0; /* Unset; can be set by the pattern */+int bsr = 0; /* Unset; can be set by the pattern */+int errorcode = 0; /* Initialize to avoid compiler warn */+int regexrc; /* Return from compile */++uint32_t i; /* Local loop counter */++/* Comments at the head of this file explain about these variables. */++uint32_t stack_groupinfo[GROUPINFO_DEFAULT_SIZE];+uint32_t stack_parsed_pattern[PARSED_PATTERN_DEFAULT_SIZE];+named_group named_groups[NAMED_GROUP_LIST_SIZE];++/* The workspace is used in different ways in the different compiling phases.+It needs to be 16-bit aligned for the preliminary parsing scan. */++uint32_t c16workspace[C16_WORK_SIZE];+PCRE2_UCHAR *cworkspace = (PCRE2_UCHAR *)c16workspace;+++/* -------------- Check arguments and set up the pattern ----------------- */++/* There must be error code and offset pointers. */++if (errorptr == NULL || erroroffset == NULL) return NULL;+*errorptr = ERR0;+*erroroffset = 0;++/* There must be a pattern, but NULL is allowed with zero length. */++if (pattern == NULL)+ {+ if (patlen == 0) pattern = (PCRE2_SPTR)""; else+ {+ *errorptr = ERR16;+ return NULL;+ }+ }++/* A NULL compile context means "use a default context" */++if (ccontext == NULL)+ ccontext = (pcre2_compile_context *)(&PRIV(default_compile_context));++/* PCRE2_MATCH_INVALID_UTF implies UTF */++if ((options & PCRE2_MATCH_INVALID_UTF) != 0) options |= PCRE2_UTF;++/* Check that all undefined public option bits are zero. */++if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0 ||+ (ccontext->extra_options & ~PUBLIC_COMPILE_EXTRA_OPTIONS) != 0)+ {+ *errorptr = ERR17;+ return NULL;+ }++if ((options & PCRE2_LITERAL) != 0 &&+ ((options & ~PUBLIC_LITERAL_COMPILE_OPTIONS) != 0 ||+ (ccontext->extra_options & ~PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS) != 0))+ {+ *errorptr = ERR92;+ return NULL;+ }++/* A zero-terminated pattern is indicated by the special length value+PCRE2_ZERO_TERMINATED. Check for an overlong pattern. */++if ((zero_terminated = (patlen == PCRE2_ZERO_TERMINATED)))+ patlen = PRIV(strlen)(pattern);++if (patlen > ccontext->max_pattern_length)+ {+ *errorptr = ERR88;+ return NULL;+ }++/* From here on, all returns from this function should end up going via the+EXIT label. */+++/* ------------ Initialize the "static" compile data -------------- */++tables = (ccontext->tables != NULL)? ccontext->tables : PRIV(default_tables);++cb.lcc = tables + lcc_offset; /* Individual */+cb.fcc = tables + fcc_offset; /* character */+cb.cbits = tables + cbits_offset; /* tables */+cb.ctypes = tables + ctypes_offset;++cb.assert_depth = 0;+cb.bracount = 0;+cb.cx = ccontext;+cb.dupnames = FALSE;+cb.end_pattern = pattern + patlen;+cb.erroroffset = 0;+cb.external_flags = 0;+cb.external_options = options;+cb.groupinfo = stack_groupinfo;+cb.had_recurse = FALSE;+cb.lastcapture = 0;+cb.max_lookbehind = 0; /* Max encountered */+cb.max_varlookbehind = ccontext->max_varlookbehind; /* Limit */+cb.name_entry_size = 0;+cb.name_table = NULL;+cb.named_groups = named_groups;+cb.named_group_list_size = NAMED_GROUP_LIST_SIZE;+cb.names_found = 0;+cb.parens_depth = 0;+cb.parsed_pattern = stack_parsed_pattern;+cb.req_varyopt = 0;+cb.start_code = cworkspace;+cb.start_pattern = pattern;+cb.start_workspace = cworkspace;+cb.workspace_size = COMPILE_WORK_SIZE;++/* Maximum back reference and backref bitmap. The bitmap records up to 31 back+references to help in deciding whether (.*) can be treated as anchored or not.+*/++cb.top_backref = 0;+cb.backref_map = 0;++/* Escape sequences \1 to \9 are always back references, but as they are only+two characters long, only two elements can be used in the parsed_pattern+vector. The first contains the reference, and we'd like to use the second to+record the offset in the pattern, so that forward references to non-existent+groups can be diagnosed later with an offset. However, on 64-bit systems,+PCRE2_SIZE won't fit. Instead, we have a vector of offsets for the first+occurrence of \1 to \9, indexed by the second parsed_pattern value. All other+references have enough space for the offset to be put into the parsed pattern.+*/++for (i = 0; i < 10; i++) cb.small_ref_offset[i] = PCRE2_UNSET;+++/* --------------- Start looking at the pattern --------------- */++/* Unless PCRE2_LITERAL is set, check for global one-time option settings at+the start of the pattern, and remember the offset to the actual regex. With+valgrind support, make the terminator of a zero-terminated pattern+inaccessible. This catches bugs that would otherwise only show up for+non-zero-terminated patterns. */++#ifdef SUPPORT_VALGRIND+if (zero_terminated) VALGRIND_MAKE_MEM_NOACCESS(pattern + patlen, CU2BYTES(1));+#endif++ptr = pattern;+skipatstart = 0;++if ((options & PCRE2_LITERAL) == 0)+ {+ while (patlen - skipatstart >= 2 &&+ ptr[skipatstart] == CHAR_LEFT_PARENTHESIS &&+ ptr[skipatstart+1] == CHAR_ASTERISK)+ {+ for (i = 0; i < sizeof(pso_list)/sizeof(pso); i++)+ {+ uint32_t c, pp;+ const pso *p = pso_list + i;++ if (patlen - skipatstart - 2 >= p->length &&+ PRIV(strncmp_c8)(ptr + skipatstart + 2, (char *)(p->name),+ p->length) == 0)+ {+ skipatstart += p->length + 2;+ switch(p->type)+ {+ case PSO_OPT:+ cb.external_options |= p->value;+ break;++ case PSO_FLG:+ setflags |= p->value;+ break;++ case PSO_NL:+ newline = p->value;+ setflags |= PCRE2_NL_SET;+ break;++ case PSO_BSR:+ bsr = p->value;+ setflags |= PCRE2_BSR_SET;+ break;++ case PSO_LIMM:+ case PSO_LIMD:+ case PSO_LIMH:+ c = 0;+ pp = skipatstart;+ if (!IS_DIGIT(ptr[pp]))+ {+ errorcode = ERR60;+ ptr += pp;+ goto HAD_EARLY_ERROR;+ }+ while (IS_DIGIT(ptr[pp]))+ {+ if (c > UINT32_MAX / 10 - 1) break; /* Integer overflow */+ c = c*10 + (ptr[pp++] - CHAR_0);+ }+ if (ptr[pp++] != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR60;+ ptr += pp;+ goto HAD_EARLY_ERROR;+ }+ if (p->type == PSO_LIMH) limit_heap = c;+ else if (p->type == PSO_LIMM) limit_match = c;+ else limit_depth = c;+ skipatstart += pp - skipatstart;+ break;+ }+ break; /* Out of the table scan loop */+ }+ }+ if (i >= sizeof(pso_list)/sizeof(pso)) break; /* Out of pso loop */+ }+ }++/* End of pattern-start options; advance to start of real regex. */++ptr += skipatstart;++/* Can't support UTF or UCP if PCRE2 was built without Unicode support. */++#ifndef SUPPORT_UNICODE+if ((cb.external_options & (PCRE2_UTF|PCRE2_UCP)) != 0)+ {+ errorcode = ERR32;+ goto HAD_EARLY_ERROR;+ }+#endif++/* Check UTF. We have the original options in 'options', with that value as+modified by (*UTF) etc in cb->external_options. The extra option+PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not permitted in UTF-16 mode because the+surrogate code points cannot be represented in UTF-16. */++utf = (cb.external_options & PCRE2_UTF) != 0;+if (utf)+ {+ if ((options & PCRE2_NEVER_UTF) != 0)+ {+ errorcode = ERR74;+ goto HAD_EARLY_ERROR;+ }+ if ((options & PCRE2_NO_UTF_CHECK) == 0 &&+ (errorcode = PRIV(valid_utf)(pattern, patlen, erroroffset)) != 0)+ goto HAD_ERROR; /* Offset was set by valid_utf() */++#if PCRE2_CODE_UNIT_WIDTH == 16+ if ((ccontext->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) != 0)+ {+ errorcode = ERR91;+ goto HAD_EARLY_ERROR;+ }+#endif+ }++/* Check UCP lockout. */++ucp = (cb.external_options & PCRE2_UCP) != 0;+if (ucp && (cb.external_options & PCRE2_NEVER_UCP) != 0)+ {+ errorcode = ERR75;+ goto HAD_EARLY_ERROR;+ }++/* Process the BSR setting. */++if (bsr == 0) bsr = ccontext->bsr_convention;++/* Process the newline setting. */++if (newline == 0) newline = ccontext->newline_convention;+cb.nltype = NLTYPE_FIXED;+switch(newline)+ {+ case PCRE2_NEWLINE_CR:+ cb.nllen = 1;+ cb.nl[0] = CHAR_CR;+ break;++ case PCRE2_NEWLINE_LF:+ cb.nllen = 1;+ cb.nl[0] = CHAR_NL;+ break;++ case PCRE2_NEWLINE_NUL:+ cb.nllen = 1;+ cb.nl[0] = CHAR_NUL;+ break;++ case PCRE2_NEWLINE_CRLF:+ cb.nllen = 2;+ cb.nl[0] = CHAR_CR;+ cb.nl[1] = CHAR_NL;+ break;++ case PCRE2_NEWLINE_ANY:+ cb.nltype = NLTYPE_ANY;+ break;++ case PCRE2_NEWLINE_ANYCRLF:+ cb.nltype = NLTYPE_ANYCRLF;+ break;++ default:+ errorcode = ERR56;+ goto HAD_EARLY_ERROR;+ }++/* Pre-scan the pattern to do two things: (1) Discover the named groups and+their numerical equivalents, so that this information is always available for+the remaining processing. (2) At the same time, parse the pattern and put a+processed version into the parsed_pattern vector. This has escapes interpreted+and comments removed (amongst other things).++In all but one case, when PCRE2_AUTO_CALLOUT is not set, the number of unsigned+32-bit ints in the parsed pattern is bounded by the length of the pattern plus+one (for the terminator) plus four if PCRE2_EXTRA_WORD or PCRE2_EXTRA_LINE is+set. The exceptional case is when running in 32-bit, non-UTF mode, when literal+characters greater than META_END (0x80000000) have to be coded as two units. In+this case, therefore, we scan the pattern to check for such values. */++#if PCRE2_CODE_UNIT_WIDTH == 32+if (!utf)+ {+ PCRE2_SPTR p;+ for (p = ptr; p < cb.end_pattern; p++) if (*p >= META_END) big32count++;+ }+#endif++/* Ensure that the parsed pattern buffer is big enough. When PCRE2_AUTO_CALLOUT+is set we have to assume a numerical callout (4 elements) for each character+plus one at the end. This is overkill, but memory is plentiful these days. For+many smaller patterns the vector on the stack (which was set up above) can be+used. */++parsed_size_needed = patlen - skipatstart + big32count;++if ((ccontext->extra_options &+ (PCRE2_EXTRA_MATCH_WORD|PCRE2_EXTRA_MATCH_LINE)) != 0)+ parsed_size_needed += 4;++if ((options & PCRE2_AUTO_CALLOUT) != 0)+ parsed_size_needed = (parsed_size_needed + 1) * 5;++if (parsed_size_needed >= PARSED_PATTERN_DEFAULT_SIZE)+ {+ uint32_t *heap_parsed_pattern = ccontext->memctl.malloc(+ (parsed_size_needed + 1) * sizeof(uint32_t), ccontext->memctl.memory_data);+ if (heap_parsed_pattern == NULL)+ {+ *errorptr = ERR21;+ goto EXIT;+ }+ cb.parsed_pattern = heap_parsed_pattern;+ }+cb.parsed_pattern_end = cb.parsed_pattern + parsed_size_needed + 1;++/* Do the parsing scan. */++errorcode = parse_regex(ptr, cb.external_options, &has_lookbehind, &cb);+if (errorcode != 0) goto HAD_CB_ERROR;++/* If there are any lookbehinds, scan the parsed pattern to figure out their+lengths. Workspace is needed to remember whether numbered groups are or are not+of limited length, and if limited, what the minimum and maximum lengths are.+This caching saves re-computing the length of any group that is referenced more+than once, which is particularly relevant when recursion is involved.+Unnumbered groups do not have this exposure because they cannot be referenced.+If there are sufficiently few groups, the default index vector on the stack, as+set up above, can be used. Otherwise we have to get/free some heap memory. The+vector must be initialized to zero. */++if (has_lookbehind)+ {+ int loopcount = 0;+ if (cb.bracount >= GROUPINFO_DEFAULT_SIZE/2)+ {+ cb.groupinfo = ccontext->memctl.malloc(+ (2 * (cb.bracount + 1))*sizeof(uint32_t), ccontext->memctl.memory_data);+ if (cb.groupinfo == NULL)+ {+ errorcode = ERR21;+ cb.erroroffset = 0;+ goto HAD_CB_ERROR;+ }+ }+ memset(cb.groupinfo, 0, (2 * cb.bracount + 1) * sizeof(uint32_t));+ errorcode = check_lookbehinds(cb.parsed_pattern, NULL, NULL, &cb, &loopcount);+ if (errorcode != 0) goto HAD_CB_ERROR;+ }++/* For debugging, there is a function that shows the parsed pattern vector. */++#ifdef DEBUG_SHOW_PARSED+fprintf(stderr, "+++ Pre-scan complete:\n");+show_parsed(&cb);+#endif++/* For debugging capturing information this code can be enabled. */++#ifdef DEBUG_SHOW_CAPTURES+ {+ named_group *ng = cb.named_groups;+ fprintf(stderr, "+++Captures: %d\n", cb.bracount);+ for (i = 0; i < cb.names_found; i++, ng++)+ {+ fprintf(stderr, "+++%3d %.*s\n", ng->number, ng->length, ng->name);+ }+ }+#endif++/* Pretend to compile the pattern while actually just accumulating the amount+of memory required in the 'length' variable. This behaviour is triggered by+passing a non-NULL final argument to compile_regex(). We pass a block of+workspace (cworkspace) for it to compile parts of the pattern into; the+compiled code is discarded when it is no longer needed, so hopefully this+workspace will never overflow, though there is a test for its doing so.++On error, errorcode will be set non-zero, so we don't need to look at the+result of the function. The initial options have been put into the cb block,+but we still have to pass a separate options variable (the first argument)+because the options may change as the pattern is processed. */++cb.erroroffset = patlen; /* For any subsequent errors that do not set it */+pptr = cb.parsed_pattern;+code = cworkspace;+*code = OP_BRA;++(void)compile_regex(cb.external_options, ccontext->extra_options, &code, &pptr,+ &errorcode, 0, &firstcu, &firstcuflags, &reqcu, &reqcuflags, NULL, NULL,+ &cb, &length);++if (errorcode != 0) goto HAD_CB_ERROR; /* Offset is in cb.erroroffset */++/* This should be caught in compile_regex(), but just in case... */++if (length > MAX_PATTERN_SIZE)+ {+ errorcode = ERR20;+ goto HAD_CB_ERROR;+ }++/* Compute the size of, then, if not too large, get and initialize the data+block for storing the compiled pattern and names table. Integer overflow should+no longer be possible because nowadays we limit the maximum value of+cb.names_found and cb.name_entry_size. */++re_blocksize = sizeof(pcre2_real_code) ++ CU2BYTES(length ++ (PCRE2_SIZE)cb.names_found * (PCRE2_SIZE)cb.name_entry_size);++if (re_blocksize > ccontext->max_pattern_compiled_length)+ {+ errorcode = ERR101;+ goto HAD_CB_ERROR;+ }++re = (pcre2_real_code *)+ ccontext->memctl.malloc(re_blocksize, ccontext->memctl.memory_data);+if (re == NULL)+ {+ errorcode = ERR21;+ goto HAD_CB_ERROR;+ }++/* The compiler may put padding at the end of the pcre2_real_code structure in+order to round it up to a multiple of 4 or 8 bytes. This means that when a+compiled pattern is copied (for example, when serialized) undefined bytes are+read, and this annoys debuggers such as valgrind. To avoid this, we explicitly+write to the last 8 bytes of the structure before setting the fields. */++memset((char *)re + sizeof(pcre2_real_code) - 8, 0, 8);+re->memctl = ccontext->memctl;+re->tables = tables;+re->executable_jit = NULL;+memset(re->start_bitmap, 0, 32 * sizeof(uint8_t));+re->blocksize = re_blocksize;+re->magic_number = MAGIC_NUMBER;+re->compile_options = options;+re->overall_options = cb.external_options;+re->extra_options = ccontext->extra_options;+re->flags = PCRE2_CODE_UNIT_WIDTH/8 | cb.external_flags | setflags;+re->limit_heap = limit_heap;+re->limit_match = limit_match;+re->limit_depth = limit_depth;+re->first_codeunit = 0;+re->last_codeunit = 0;+re->bsr_convention = bsr;+re->newline_convention = newline;+re->max_lookbehind = 0;+re->minlength = 0;+re->top_bracket = 0;+re->top_backref = 0;+re->name_entry_size = cb.name_entry_size;+re->name_count = cb.names_found;++/* The basic block is immediately followed by the name table, and the compiled+code follows after that. */++codestart = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)) ++ re->name_entry_size * re->name_count;++/* Update the compile data block for the actual compile. The starting points of+the name/number translation table and of the code are passed around in the+compile data block. The start/end pattern and initial options are already set+from the pre-compile phase, as is the name_entry_size field. */++cb.parens_depth = 0;+cb.assert_depth = 0;+cb.lastcapture = 0;+cb.name_table = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code));+cb.start_code = codestart;+cb.req_varyopt = 0;+cb.had_accept = FALSE;+cb.had_pruneorskip = FALSE;++/* If any named groups were found, create the name/number table from the list+created in the pre-pass. */++if (cb.names_found > 0)+ {+ named_group *ng = cb.named_groups;+ for (i = 0; i < cb.names_found; i++, ng++)+ add_name_to_table(&cb, ng->name, ng->length, ng->number, i);+ }++/* Set up a starting, non-extracting bracket, then compile the expression. On+error, errorcode will be set non-zero, so we don't need to look at the result+of the function here. */++pptr = cb.parsed_pattern;+code = (PCRE2_UCHAR *)codestart;+*code = OP_BRA;+regexrc = compile_regex(re->overall_options, ccontext->extra_options, &code,+ &pptr, &errorcode, 0, &firstcu, &firstcuflags, &reqcu, &reqcuflags, NULL,+ NULL, &cb, NULL);+if (regexrc < 0) re->flags |= PCRE2_MATCH_EMPTY;+re->top_bracket = cb.bracount;+re->top_backref = cb.top_backref;+re->max_lookbehind = cb.max_lookbehind;++if (cb.had_accept)+ {+ reqcu = 0; /* Must disable after (*ACCEPT) */+ reqcuflags = REQ_NONE;+ re->flags |= PCRE2_HASACCEPT; /* Disables minimum length */+ }++/* Fill in the final opcode and check for disastrous overflow. If no overflow,+but the estimated length exceeds the really used length, adjust the value of+re->blocksize, and if valgrind support is configured, mark the extra allocated+memory as unaddressable, so that any out-of-bound reads can be detected. */++*code++ = OP_END;+usedlength = code - codestart;+if (usedlength > length) errorcode = ERR23; else+ {+ re->blocksize -= CU2BYTES(length - usedlength);+#ifdef SUPPORT_VALGRIND+ VALGRIND_MAKE_MEM_NOACCESS(code, CU2BYTES(length - usedlength));+#endif+ }++/* Scan the pattern for recursion/subroutine calls and convert the group+numbers into offsets. Maintain a small cache so that repeated groups containing+recursions are efficiently handled. */++#define RSCAN_CACHE_SIZE 8++if (errorcode == 0 && cb.had_recurse)+ {+ PCRE2_UCHAR *rcode;+ PCRE2_SPTR rgroup;+ unsigned int ccount = 0;+ int start = RSCAN_CACHE_SIZE;+ recurse_cache rc[RSCAN_CACHE_SIZE];++ for (rcode = (PCRE2_UCHAR *)find_recurse(codestart, utf);+ rcode != NULL;+ rcode = (PCRE2_UCHAR *)find_recurse(rcode + 1 + LINK_SIZE, utf))+ {+ int p, groupnumber;++ groupnumber = (int)GET(rcode, 1);+ if (groupnumber == 0) rgroup = codestart; else+ {+ PCRE2_SPTR search_from = codestart;+ rgroup = NULL;+ for (i = 0, p = start; i < ccount; i++, p = (p + 1) & 7)+ {+ if (groupnumber == rc[p].groupnumber)+ {+ rgroup = rc[p].group;+ break;+ }++ /* Group n+1 must always start to the right of group n, so we can save+ search time below when the new group number is greater than any of the+ previously found groups. */++ if (groupnumber > rc[p].groupnumber) search_from = rc[p].group;+ }++ if (rgroup == NULL)+ {+ rgroup = PRIV(find_bracket)(search_from, utf, groupnumber);+ if (rgroup == NULL)+ {+ errorcode = ERR53;+ break;+ }+ if (--start < 0) start = RSCAN_CACHE_SIZE - 1;+ rc[start].groupnumber = groupnumber;+ rc[start].group = rgroup;+ if (ccount < RSCAN_CACHE_SIZE) ccount++;+ }+ }++ PUT(rcode, 1, rgroup - codestart);+ }+ }++/* In rare debugging situations we sometimes need to look at the compiled code+at this stage. */++#ifdef DEBUG_CALL_PRINTINT+pcre2_printint(re, stderr, TRUE);+fprintf(stderr, "Length=%lu Used=%lu\n", length, usedlength);+#endif++/* Unless disabled, check whether any single character iterators can be+auto-possessified. The function overwrites the appropriate opcode values, so+the type of the pointer must be cast. NOTE: the intermediate variable "temp" is+used in this code because at least one compiler gives a warning about loss of+"const" attribute if the cast (PCRE2_UCHAR *)codestart is used directly in the+function call. */++if (errorcode == 0 && (re->overall_options & PCRE2_NO_AUTO_POSSESS) == 0)+ {+ PCRE2_UCHAR *temp = (PCRE2_UCHAR *)codestart;+ if (PRIV(auto_possessify)(temp, &cb) != 0) errorcode = ERR80;+ }++/* Failed to compile, or error while post-processing. */++if (errorcode != 0) goto HAD_CB_ERROR;++/* Successful compile. If the anchored option was not passed, set it if+we can determine that the pattern is anchored by virtue of ^ characters or \A+or anything else, such as starting with non-atomic .* when DOTALL is set and+there are no occurrences of *PRUNE or *SKIP (though there is an option to+disable this case). */++if ((re->overall_options & PCRE2_ANCHORED) == 0 &&+ is_anchored(codestart, 0, &cb, 0, FALSE))+ re->overall_options |= PCRE2_ANCHORED;++/* Set up the first code unit or startline flag, the required code unit, and+then study the pattern. This code need not be obeyed if PCRE2_NO_START_OPTIMIZE+is set, as the data it would create will not be used. Note that a first code+unit (but not the startline flag) is useful for anchored patterns because it+can still give a quick "no match" and also avoid searching for a last code+unit. */++if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)+ {+ int minminlength = 0; /* For minimal minlength from first/required CU */++ /* If we do not have a first code unit, see if there is one that is asserted+ (these are not saved during the compile because they can cause conflicts with+ actual literals that follow). */++ if (firstcuflags >= REQ_NONE)+ firstcu = find_firstassertedcu(codestart, &firstcuflags, 0);++ /* Save the data for a first code unit. The existence of one means the+ minimum length must be at least 1. */++ if (firstcuflags < REQ_NONE)+ {+ re->first_codeunit = firstcu;+ re->flags |= PCRE2_FIRSTSET;+ minminlength++;++ /* Handle caseless first code units. */++ if ((firstcuflags & REQ_CASELESS) != 0)+ {+ if (firstcu < 128 || (!utf && !ucp && firstcu < 255))+ {+ if (cb.fcc[firstcu] != firstcu) re->flags |= PCRE2_FIRSTCASELESS;+ }++ /* The first code unit is > 128 in UTF or UCP mode, or > 255 otherwise.+ In 8-bit UTF mode, codepoints in the range 128-255 are introductory code+ points and cannot have another case, but if UCP is set they may do. */++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+ else if (ucp && !utf && UCD_OTHERCASE(firstcu) != firstcu)+ re->flags |= PCRE2_FIRSTCASELESS;+#else+ else if ((utf || ucp) && firstcu <= MAX_UTF_CODE_POINT &&+ UCD_OTHERCASE(firstcu) != firstcu)+ re->flags |= PCRE2_FIRSTCASELESS;+#endif+#endif /* SUPPORT_UNICODE */+ }+ }++ /* When there is no first code unit, for non-anchored patterns, see if we can+ set the PCRE2_STARTLINE flag. This is helpful for multiline matches when all+ branches start with ^ and also when all branches start with non-atomic .* for+ non-DOTALL matches when *PRUNE and SKIP are not present. (There is an option+ that disables this case.) */++ else if ((re->overall_options & PCRE2_ANCHORED) == 0 &&+ is_startline(codestart, 0, &cb, 0, FALSE))+ re->flags |= PCRE2_STARTLINE;++ /* Handle the "required code unit", if one is set. In the UTF case we can+ increment the minimum minimum length only if we are sure this really is a+ different character and not a non-starting code unit of the first character,+ because the minimum length count is in characters, not code units. */++ if (reqcuflags < REQ_NONE)+ {+#if PCRE2_CODE_UNIT_WIDTH == 16+ if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */+ firstcuflags >= REQ_NONE || /* First not set */+ (firstcu & 0xf800) != 0xd800 || /* First not surrogate */+ (reqcu & 0xfc00) != 0xdc00) /* Req not low surrogate */+#elif PCRE2_CODE_UNIT_WIDTH == 8+ if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */+ firstcuflags >= REQ_NONE || /* First not set */+ (firstcu & 0x80) == 0 || /* First is ASCII */+ (reqcu & 0x80) == 0) /* Req is ASCII */+#endif+ {+ minminlength++;+ }++ /* In the case of an anchored pattern, set up the value only if it follows+ a variable length item in the pattern. */++ if ((re->overall_options & PCRE2_ANCHORED) == 0 ||+ (reqcuflags & REQ_VARY) != 0)+ {+ re->last_codeunit = reqcu;+ re->flags |= PCRE2_LASTSET;++ /* Handle caseless required code units as for first code units (above). */++ if ((reqcuflags & REQ_CASELESS) != 0)+ {+ if (reqcu < 128 || (!utf && !ucp && reqcu < 255))+ {+ if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS;+ }+#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+ else if (ucp && !utf && UCD_OTHERCASE(reqcu) != reqcu)+ re->flags |= PCRE2_LASTCASELESS;+#else+ else if ((utf || ucp) && reqcu <= MAX_UTF_CODE_POINT &&+ UCD_OTHERCASE(reqcu) != reqcu)+ re->flags |= PCRE2_LASTCASELESS;+#endif+#endif /* SUPPORT_UNICODE */+ }+ }+ }++ /* Study the compiled pattern to set up information such as a bitmap of+ starting code units and a minimum matching length. */++ if (PRIV(study)(re) != 0)+ {+ errorcode = ERR31;+ goto HAD_CB_ERROR;+ }++ /* If study() set a bitmap of starting code units, it implies a minimum+ length of at least one. */++ if ((re->flags & PCRE2_FIRSTMAPSET) != 0 && minminlength == 0)+ minminlength = 1;++ /* If the minimum length set (or not set) by study() is less than the minimum+ implied by required code units, override it. */++ if (re->minlength < minminlength) re->minlength = minminlength;+ } /* End of start-of-match optimizations. */++/* Control ends up here in all cases. When running under valgrind, make a+pattern's terminating zero defined again. If memory was obtained for the parsed+version of the pattern, free it before returning. Also free the list of named+groups if a larger one had to be obtained, and likewise the group information+vector. */++EXIT:+#ifdef SUPPORT_VALGRIND+if (zero_terminated) VALGRIND_MAKE_MEM_DEFINED(pattern + patlen, CU2BYTES(1));+#endif+if (cb.parsed_pattern != stack_parsed_pattern)+ ccontext->memctl.free(cb.parsed_pattern, ccontext->memctl.memory_data);+if (cb.named_group_list_size > NAMED_GROUP_LIST_SIZE)+ ccontext->memctl.free((void *)cb.named_groups, ccontext->memctl.memory_data);+if (cb.groupinfo != stack_groupinfo)+ ccontext->memctl.free((void *)cb.groupinfo, ccontext->memctl.memory_data);+return re; /* Will be NULL after an error */++/* Errors discovered in parse_regex() set the offset value in the compile+block. Errors discovered before it is called must compute it from the ptr+value. After parse_regex() is called, the offset in the compile block is set to+the end of the pattern, but certain errors in compile_regex() may reset it if+an offset is available in the parsed pattern. */++HAD_CB_ERROR:+ptr = pattern + cb.erroroffset;++HAD_EARLY_ERROR:+*erroroffset = ptr - pattern;++HAD_ERROR:+*errorptr = errorcode;+pcre2_code_free(re);+re = NULL;+goto EXIT;+}++/* These #undefs are here to enable unity builds with CMake. */++#undef NLBLOCK /* Block containing newline information */+#undef PSSTART /* Field containing processed string start */+#undef PSEND /* Field containing processed string end */ /* End of pcre2_compile.c */
src/c/pcre2/src/pcre2_context.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2018 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -136,10 +136,13 @@ NULL, /* Stack guard data */ PRIV(default_tables), /* Character tables */ PCRE2_UNSET, /* Max pattern length */+ PCRE2_UNSET, /* Max pattern compiled length */ BSR_DEFAULT, /* Backslash R default */ NEWLINE_DEFAULT, /* Newline convention */ PARENS_NEST_LIMIT, /* As it says */- 0 }; /* Extra options */+ 0, /* Extra options */+ MAX_VARLOOKBEHIND /* As it says */+ }; /* The create function copies the default into the new memory, but must override the default memory handling functions if a gcontext was provided. */@@ -228,49 +231,48 @@ PCRE2_EXP_DEFN pcre2_general_context * PCRE2_CALL_CONVENTION pcre2_general_context_copy(pcre2_general_context *gcontext) {-pcre2_general_context *new =+pcre2_general_context *newcontext = gcontext->memctl.malloc(sizeof(pcre2_real_general_context), gcontext->memctl.memory_data);-if (new == NULL) return NULL;-memcpy(new, gcontext, sizeof(pcre2_real_general_context));-return new;+if (newcontext == NULL) return NULL;+memcpy(newcontext, gcontext, sizeof(pcre2_real_general_context));+return newcontext; } PCRE2_EXP_DEFN pcre2_compile_context * PCRE2_CALL_CONVENTION pcre2_compile_context_copy(pcre2_compile_context *ccontext) {-pcre2_compile_context *new =+pcre2_compile_context *newcontext = ccontext->memctl.malloc(sizeof(pcre2_real_compile_context), ccontext->memctl.memory_data);-if (new == NULL) return NULL;-memcpy(new, ccontext, sizeof(pcre2_real_compile_context));-return new;+if (newcontext == NULL) return NULL;+memcpy(newcontext, ccontext, sizeof(pcre2_real_compile_context));+return newcontext; } PCRE2_EXP_DEFN pcre2_match_context * PCRE2_CALL_CONVENTION pcre2_match_context_copy(pcre2_match_context *mcontext) {-pcre2_match_context *new =+pcre2_match_context *newcontext = mcontext->memctl.malloc(sizeof(pcre2_real_match_context), mcontext->memctl.memory_data);-if (new == NULL) return NULL;-memcpy(new, mcontext, sizeof(pcre2_real_match_context));-return new;+if (newcontext == NULL) return NULL;+memcpy(newcontext, mcontext, sizeof(pcre2_real_match_context));+return newcontext; } - PCRE2_EXP_DEFN pcre2_convert_context * PCRE2_CALL_CONVENTION pcre2_convert_context_copy(pcre2_convert_context *ccontext) {-pcre2_convert_context *new =+pcre2_convert_context *newcontext = ccontext->memctl.malloc(sizeof(pcre2_real_convert_context), ccontext->memctl.memory_data);-if (new == NULL) return NULL;-memcpy(new, ccontext, sizeof(pcre2_real_convert_context));-return new;+if (newcontext == NULL) return NULL;+memcpy(newcontext, ccontext, sizeof(pcre2_real_convert_context));+return newcontext; } @@ -352,6 +354,13 @@ } PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_max_pattern_compiled_length(pcre2_compile_context *ccontext, PCRE2_SIZE length)+{+ccontext->max_pattern_compiled_length = length;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_newline(pcre2_compile_context *ccontext, uint32_t newline) { switch(newline)@@ -371,6 +380,13 @@ } PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_max_varlookbehind(pcre2_compile_context *ccontext, uint32_t limit)+{+ccontext->max_varlookbehind = limit;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext, uint32_t limit) { ccontext->parens_nest_limit = limit;@@ -443,9 +459,12 @@ return 0; } -/* This function became obsolete at release 10.30. It is kept as a synonym for-backwards compatibility. */+/* These functions became obsolete at release 10.30. The first is kept as a+synonym for backwards compatibility. The second now does nothing. Exclude both+from coverage reports. */ +/* LCOV_EXCL_START */+ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_recursion_limit(pcre2_match_context *mcontext, uint32_t limit) {@@ -463,6 +482,9 @@ (void)mydata; return 0; }++/* LCOV_EXCL_STOP */+ /* ------------ Convert context ------------ */
src/c/pcre2/src/pcre2_convert.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2018 University of Cambridge+ New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -65,9 +65,8 @@ #define STR_QUERY_s STR_LEFT_PARENTHESIS STR_QUESTION_MARK STR_s STR_RIGHT_PARENTHESIS #define STR_STAR_NUL STR_LEFT_PARENTHESIS STR_ASTERISK STR_N STR_U STR_L STR_RIGHT_PARENTHESIS -/* States for range and POSIX processing */+/* States for POSIX processing */ -enum { RANGE_NOT_STARTED, RANGE_STARTING, RANGE_STARTED }; enum { POSIX_START_REGEX, POSIX_ANCHORED, POSIX_NOT_BRACKET, POSIX_CLASS_NOT_STARTED, POSIX_CLASS_STARTING, POSIX_CLASS_STARTED }; @@ -541,6 +540,14 @@ static BOOL convert_glob_char_in_class(int class_index, PCRE2_UCHAR c) {+#if PCRE2_CODE_UNIT_WIDTH != 8+if (c > 0xff)+ {+ /* ctype functions are not sane for c > 0xff */+ return 0;+ }+#endif+ switch (class_index) { case 1: return isalnum(c);
src/c/pcre2/src/pcre2_dfa_match.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2022 University of Cambridge+ New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -168,7 +168,7 @@ 0, /* KetRmax */ 0, /* KetRmin */ 0, /* KetRpos */- 0, /* Reverse */+ 0, 0, /* Reverse, Vreverse */ 0, /* Assert */ 0, /* Assert not */ 0, /* Assert behind */@@ -187,7 +187,8 @@ 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */ 0, 0, /* COMMIT, COMMIT_ARG */ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */- 0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */+ 0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */+ 0, 0 /* \B and \b in UCP mode */ }; /* This table identifies those opcodes that inspect a character. It is used to@@ -245,7 +246,7 @@ 0, /* KetRmax */ 0, /* KetRmin */ 0, /* KetRpos */- 0, /* Reverse */+ 0, 0, /* Reverse, Vreverse */ 0, /* Assert */ 0, /* Assert not */ 0, /* Assert behind */@@ -264,7 +265,8 @@ 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */ 0, 0, /* COMMIT, COMMIT_ARG */ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */- 0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */+ 0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */+ 1, 1 /* \B and \b in UCP mode */ }; /* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,@@ -350,7 +352,7 @@ */ static int-do_callout(PCRE2_SPTR code, PCRE2_SIZE *offsets, PCRE2_SPTR current_subject,+do_callout_dfa(PCRE2_SPTR code, PCRE2_SIZE *offsets, PCRE2_SPTR current_subject, PCRE2_SPTR ptr, dfa_match_block *mb, PCRE2_SIZE extracode, PCRE2_SIZE *lengthptr) {@@ -426,7 +428,7 @@ else {- uint32_t newsize = (rws->size >= UINT32_MAX/2)? UINT32_MAX/2 : rws->size * 2;+ uint32_t newsize = (rws->size >= UINT32_MAX/(sizeof(int)*2))? UINT32_MAX/sizeof(int) : rws->size * 2; uint32_t newsizeK = newsize/(1024/sizeof(int)); if (newsizeK + mb->heap_used > mb->heap_limit)@@ -589,7 +591,7 @@ end_code = this_start_code; do {- size_t back = (size_t)GET(end_code, 2+LINK_SIZE);+ size_t back = (size_t)GET2(end_code, 2+LINK_SIZE); if (back > max_back) max_back = back; end_code += GET(end_code, 1); }@@ -633,8 +635,8 @@ end_code = this_start_code; do {- uint32_t revlen = (end_code[1+LINK_SIZE] == OP_REVERSE)? 1 + LINK_SIZE : 0;- size_t back = (revlen == 0)? 0 : (size_t)GET(end_code, 2+LINK_SIZE);+ uint32_t revlen = (end_code[1+LINK_SIZE] == OP_REVERSE)? 1 + IMM2_SIZE : 0;+ size_t back = (revlen == 0)? 0 : (size_t)GET2(end_code, 2+LINK_SIZE); if (back <= gone_back) { int bstate = (int)(end_code - start_code + 1 + LINK_SIZE + revlen);@@ -1100,6 +1102,8 @@ /*-----------------------------------------------------------------*/ case OP_WORD_BOUNDARY: case OP_NOT_WORD_BOUNDARY:+ case OP_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY: { int left_word, right_word; @@ -1112,13 +1116,13 @@ #endif GETCHARTEST(d, temp); #ifdef SUPPORT_UNICODE- if ((mb->poptions & PCRE2_UCP) != 0)+ if (codevalue == OP_UCP_WORD_BOUNDARY ||+ codevalue == OP_NOT_UCP_WORD_BOUNDARY) {- if (d == '_') left_word = TRUE; else- {- uint32_t cat = UCD_CATEGORY(d);- left_word = (cat == ucp_L || cat == ucp_N);- }+ int chartype = UCD_CHARTYPE(d);+ int category = PRIV(ucp_gentype)[chartype];+ left_word = (category == ucp_L || category == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc); } else #endif@@ -1137,13 +1141,13 @@ mb->last_used_ptr = temp; } #ifdef SUPPORT_UNICODE- if ((mb->poptions & PCRE2_UCP) != 0)+ if (codevalue == OP_UCP_WORD_BOUNDARY ||+ codevalue == OP_NOT_UCP_WORD_BOUNDARY) {- if (c == '_') right_word = TRUE; else- {- uint32_t cat = UCD_CATEGORY(c);- right_word = (cat == ucp_L || cat == ucp_N);- }+ int chartype = UCD_CHARTYPE(c);+ int category = PRIV(ucp_gentype)[chartype];+ right_word = (category == ucp_L || category == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc); } else #endif@@ -1151,7 +1155,9 @@ } else right_word = FALSE; - if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))+ if ((left_word == right_word) ==+ (codevalue == OP_NOT_WORD_BOUNDARY ||+ codevalue == OP_NOT_UCP_WORD_BOUNDARY)) { ADD_ACTIVE(state_offset + 1, 0); } } break;@@ -1168,6 +1174,7 @@ if (clen > 0) { BOOL OK;+ int chartype; const uint32_t *cp; const ucd_record * prop = GET_UCD(c); switch(code[1])@@ -1177,8 +1184,9 @@ break; case PT_LAMP:- OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||- prop->chartype == ucp_Lt;+ chartype = prop->chartype;+ OK = chartype == ucp_Lu || chartype == ucp_Ll ||+ chartype == ucp_Lt; break; case PT_GC:@@ -1201,8 +1209,9 @@ /* These are specials for combination cases. */ case PT_ALNUM:- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N;+ chartype = prop->chartype;+ OK = PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included,@@ -1225,12 +1234,20 @@ break; case PT_WORD:- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N ||- c == CHAR_UNDERSCORE;+ chartype = prop->chartype;+ OK = PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc; break; case PT_CLIST:+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c > MAX_UTF_CODE_POINT)+ {+ OK = FALSE;+ break;+ }+#endif cp = PRIV(ucd_caseless_sets) + code[2]; for (;;) {@@ -1440,6 +1457,7 @@ if (clen > 0) { BOOL OK;+ int chartype; const uint32_t *cp; const ucd_record * prop = GET_UCD(c); switch(code[2])@@ -1449,8 +1467,8 @@ break; case PT_LAMP:- OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||- prop->chartype == ucp_Lt;+ chartype = prop->chartype;+ OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt; break; case PT_GC:@@ -1473,8 +1491,9 @@ /* These are specials for combination cases. */ case PT_ALNUM:- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N;+ chartype = prop->chartype;+ OK = PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included,@@ -1497,12 +1516,20 @@ break; case PT_WORD:- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N ||- c == CHAR_UNDERSCORE;+ chartype = prop->chartype;+ OK = PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc; break; case PT_CLIST:+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c > MAX_UTF_CODE_POINT)+ {+ OK = FALSE;+ break;+ }+#endif cp = PRIV(ucd_caseless_sets) + code[3]; for (;;) {@@ -1695,6 +1722,7 @@ if (clen > 0) { BOOL OK;+ int chartype; const uint32_t *cp; const ucd_record * prop = GET_UCD(c); switch(code[2])@@ -1704,8 +1732,8 @@ break; case PT_LAMP:- OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||- prop->chartype == ucp_Lt;+ chartype = prop->chartype;+ OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt; break; case PT_GC:@@ -1728,8 +1756,9 @@ /* These are specials for combination cases. */ case PT_ALNUM:- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N;+ chartype = prop->chartype;+ OK = PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included,@@ -1752,12 +1781,20 @@ break; case PT_WORD:- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N ||- c == CHAR_UNDERSCORE;+ chartype = prop->chartype;+ OK = PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc; break; case PT_CLIST:+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c > MAX_UTF_CODE_POINT)+ {+ OK = FALSE;+ break;+ }+#endif cp = PRIV(ucd_caseless_sets) + code[3]; for (;;) {@@ -1975,6 +2012,7 @@ if (clen > 0) { BOOL OK;+ int chartype; const uint32_t *cp; const ucd_record * prop = GET_UCD(c); switch(code[1 + IMM2_SIZE + 1])@@ -1984,8 +2022,8 @@ break; case PT_LAMP:- OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||- prop->chartype == ucp_Lt;+ chartype = prop->chartype;+ OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt; break; case PT_GC:@@ -2009,8 +2047,9 @@ /* These are specials for combination cases. */ case PT_ALNUM:- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N;+ chartype = prop->chartype;+ OK = PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included,@@ -2033,12 +2072,20 @@ break; case PT_WORD:- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N ||- c == CHAR_UNDERSCORE;+ chartype = prop->chartype;+ OK = PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc; break; case PT_CLIST:+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c > MAX_UTF_CODE_POINT)+ {+ OK = FALSE;+ break;+ }+#endif cp = PRIV(ucd_caseless_sets) + code[1 + IMM2_SIZE + 2]; for (;;) {@@ -2799,7 +2846,7 @@ || code[LINK_SIZE + 1] == OP_CALLOUT_STR) { PCRE2_SIZE callout_length;- rrc = do_callout(code, offsets, current_subject, ptr, mb,+ rrc = do_callout_dfa(code, offsets, current_subject, ptr, mb, 1 + LINK_SIZE, &callout_length); if (rrc < 0) return rrc; /* Abandon */ if (rrc > 0) break; /* Fail this thread */@@ -2894,7 +2941,6 @@ int *local_workspace; PCRE2_SIZE *local_offsets; RWS_anchor *rws = (RWS_anchor *)RWS;- dfa_recursion_info *ri; PCRE2_SPTR callpat = start_code + GET(code, 1); uint32_t recno = (callpat == mb->start_code)? 0 : GET2(callpat, 1 + LINK_SIZE);@@ -2911,18 +2957,24 @@ rws->free -= RWS_RSIZE + RWS_OVEC_RSIZE; /* Check for repeating a recursion without advancing the subject- pointer. This should catch convoluted mutual recursions. (Some simple- cases are caught at compile time.) */+ pointer or last used character. This should catch convoluted mutual+ recursions. (Some simple cases are caught at compile time.) */ - for (ri = mb->recursive; ri != NULL; ri = ri->prevrec)- if (recno == ri->group_num && ptr == ri->subject_position)+ for (dfa_recursion_info *ri = mb->recursive;+ ri != NULL;+ ri = ri->prevrec)+ {+ if (recno == ri->group_num && ptr == ri->subject_position &&+ mb->last_used_ptr == ri->last_used_ptr) return PCRE2_ERROR_RECURSELOOP;+ } /* Remember this recursion and where we started it so as to catch infinite loops. */ new_recursive.group_num = recno; new_recursive.subject_position = ptr;+ new_recursive.last_used_ptr = mb->last_used_ptr; new_recursive.prevrec = mb->recursive; mb->recursive = &new_recursive; @@ -3196,7 +3248,7 @@ case OP_CALLOUT_STR: { PCRE2_SIZE callout_length;- rrc = do_callout(code, offsets, current_subject, ptr, mb, 0,+ rrc = do_callout_dfa(code, offsets, current_subject, ptr, mb, 0, &callout_length); if (rrc < 0) return rrc; /* Abandon */ if (rrc == 0)@@ -3424,7 +3476,7 @@ where to start. */ startline = (re->flags & PCRE2_STARTLINE) != 0;-firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;+firstline = !anchored && (re->overall_options & PCRE2_FIRSTLINE) != 0; bumpalong_limit = end_subject; /* Initialize and set up the fixed fields in the callout block, with a pointer@@ -3994,8 +4046,9 @@ match_data->ovector[0] = (PCRE2_SIZE)(start_match - subject); match_data->ovector[1] = (PCRE2_SIZE)(end_subject - subject); }+ match_data->subject_length = length; match_data->leftchar = (PCRE2_SIZE)(mb->start_used_ptr - subject);- match_data->rightchar = (PCRE2_SIZE)( mb->last_used_ptr - subject);+ match_data->rightchar = (PCRE2_SIZE)(mb->last_used_ptr - subject); match_data->startchar = (PCRE2_SIZE)(start_match - subject); match_data->rc = rc; @@ -4056,5 +4109,11 @@ return rc; }++/* These #undefs are here to enable unity builds with CMake. */++#undef NLBLOCK /* Block containing newline information */+#undef PSSTART /* Field containing processed string start */+#undef PSEND /* Field containing processed string end */ /* End of pcre2_dfa_match.c */
src/c/pcre2/src/pcre2_dftables.c view
@@ -56,10 +56,11 @@ #include <string.h> #include <locale.h> +#define PCRE2_DFTABLES /* for pcre2_internal.h, pcre2_maketables.c */+ #define PCRE2_CODE_UNIT_WIDTH 0 /* Must be set, but not relevant here */ #include "pcre2_internal.h" -#define PCRE2_DFTABLES /* pcre2_maketables.c notices this */ #include "pcre2_maketables.c" @@ -98,8 +99,8 @@ int nclass = 0; BOOL binary = FALSE; char *env = (char *)"C";-const unsigned char *tables;-const unsigned char *base_of_tables;+const uint8_t *tables;+const uint8_t *base_of_tables; /* Process options */ @@ -180,7 +181,8 @@ "/* This file was automatically written by the pcre2_dftables auxiliary\n" "program. It contains character tables that are used when no external\n" "tables are passed to PCRE2 by the application that calls it. The tables\n"- "are used only for characters whose code values are less than 256. */\n\n");+ "are used only for characters whose code values are less than 256, and\n"+ "only relevant if not in UCP mode. */\n\n"); (void)fprintf(f, "/* This set of tables was written in the %s locale. */\n\n", env);@@ -206,14 +208,6 @@ #endif (void)fprintf(f,- "/* The following #include is present because without it gcc 4.x may remove\n"- "the array definition from the final binary if PCRE2 is built into a static\n"- "library and dead code stripping is activated. This leads to link errors.\n"- "Pulling in the header ensures that the array gets flagged as \"someone\n"- "outside this compilation unit might reference this\" and so it will always\n"- "be supplied to the linker. */\n\n");--(void)fprintf(f, "#ifdef HAVE_CONFIG_H\n" "#include \"config.h\"\n" "#endif\n\n"@@ -269,7 +263,7 @@ " 0x%02x letter\n" " 0x%02x lower case letter\n" " 0x%02x decimal digit\n"- " 0x%02x alphanumeric or '_'\n*/\n\n",+ " 0x%02x word (alphanumeric or '_')\n*/\n\n", ctype_space, ctype_letter, ctype_lcletter, ctype_digit, ctype_word); (void)fprintf(f, " ");
src/c/pcre2/src/pcre2_error.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2021 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -82,7 +82,7 @@ "missing closing parenthesis\0" /* 15 */ "reference to non-existent subpattern\0"- "pattern passed as NULL\0"+ "pattern passed as NULL with non-zero length\0" "unrecognised compile-time option bit(s)\0" "missing ) after (?# comment\0" "parentheses are too deeply nested\0"@@ -93,7 +93,7 @@ "internal error: code overflow\0" "missing closing parenthesis for condition\0" /* 25 */- "lookbehind assertion is not fixed length\0"+ "length of lookbehind assertion is not limited\0" "a relative value of zero is not allowed\0" "conditional subpattern contains more than two branches\0" "assertion expected after (?( or (?(?C)\0"@@ -187,6 +187,9 @@ "too many capturing groups (maximum 65535)\0" "atomic assertion expected after (?( or (?(?C)\0" "\\K is not allowed in lookarounds (but see PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK)\0"+ /* 100 */+ "branch too long in variable-length lookbehind assertion\0"+ "compiled pattern would be longer than the limit set by the application\0" ; /* Match-time and UTF error texts are in the same format. */@@ -272,6 +275,7 @@ /* 65 */ "internal error - duplicate substitution match\0" "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0"+ "INTERNAL ERROR: invalid substring offset\0" ;
src/c/pcre2/src/pcre2_extuni.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2021 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -75,7 +75,11 @@ * Match an extended grapheme sequence * *************************************************/ -/*+/* NOTE: The logic contained in this function is replicated in three special-+purpose functions in the pcre2_jit_compile.c module. If the logic below is+changed, they must be kept in step so that the interpreter and the JIT have the+same behaviour.+ Arguments: c the first character eptr pointer to next character@@ -92,6 +96,7 @@ PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject, PCRE2_SPTR end_subject, BOOL utf, int *xcount) {+BOOL was_ep_ZWJ = FALSE; int lgb = UCD_GRAPHBREAK(c); while (eptr < end_subject)@@ -102,6 +107,12 @@ rgb = UCD_GRAPHBREAK(c); if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break; + /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was+ preceded by Extended Pictographic. */++ if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ)+ break;+ /* Not breaking between Regional Indicators is allowed only if there are an even number of preceding RIs. */ @@ -129,12 +140,15 @@ if ((ricount & 1) != 0) break; /* Grapheme break required */ } - /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this- allows any number of them before a following Extended_Pictographic. */+ /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in+ between; see next statement). */ - if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||- lgb != ucp_gbExtended_Pictographic)- lgb = rgb;+ was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ);++ /* If Extend follows Extended_Pictographic, do not update lgb; this allows+ any number of them before a following ZWJ. */++ if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic) lgb = rgb; eptr += len; if (xcount != NULL) *xcount += 1;
src/c/pcre2/src/pcre2_find_bracket.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2018 University of Cambridge+ New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -41,9 +41,9 @@ /* This module contains a single function that scans through a compiled pattern until it finds a capturing bracket with the given number, or, if the number is-negative, an instance of OP_REVERSE for a lookbehind. The function is called-from pcre2_compile.c and also from pcre2_study.c when finding the minimum-matching length. */+negative, an instance of OP_REVERSE or OP_VREVERSE for a lookbehind. The+function is called from pcre2_compile.c and also from pcre2_study.c when+finding the minimum matching length. */ #ifdef HAVE_CONFIG_H@@ -85,7 +85,7 @@ /* Handle lookbehind */ - else if (c == OP_REVERSE)+ else if (c == OP_REVERSE || c == OP_VREVERSE) { if (number < 0) return (PCRE2_UCHAR *)code; code += PRIV(OP_lengths)[c];
src/c/pcre2/src/pcre2_fuzzsupport.c view
@@ -7,24 +7,44 @@ rather than a file name. This allows easy testing of short strings. Written by Philip Hazel, October 2016+Updated February 2024 (Addison Crump added 16-bit/32-bit and JIT support)+Further updates March/April/May 2024 by PH ***************************************************************************/ #include <errno.h>+#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h>+#include <unistd.h> +/* stack size adjustment */+#include <sys/time.h>+#include <sys/resource.h>++#define STACK_SIZE_MB 256+#define JIT_SIZE_LIMIT (200 * 1024)++#ifndef PCRE2_CODE_UNIT_WIDTH #define PCRE2_CODE_UNIT_WIDTH 8+#endif++#include "config.h" #include "pcre2.h"+#include "pcre2_internal.h" #define MAX_MATCH_SIZE 1000 #define DFA_WORKSPACE_COUNT 100 +/* When adding new compile or match options, remember to update the functions+below that output them. */+ #define ALLOWED_COMPILE_OPTIONS \ (PCRE2_ANCHORED|PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \ PCRE2_ALT_VERBNAMES|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_DOLLAR_ENDONLY| \- PCRE2_DOTALL|PCRE2_DUPNAMES|PCRE2_ENDANCHORED|PCRE2_EXTENDED|PCRE2_FIRSTLINE| \+ PCRE2_DOTALL|PCRE2_DUPNAMES|PCRE2_ENDANCHORED|PCRE2_EXTENDED| \+ PCRE2_EXTENDED_MORE|PCRE2_FIRSTLINE| \ PCRE2_MATCH_UNSET_BACKREF|PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C| \ PCRE2_NO_AUTO_CAPTURE| \ PCRE2_NO_AUTO_POSSESS|PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_NO_START_OPTIMIZE| \@@ -34,8 +54,183 @@ #define ALLOWED_MATCH_OPTIONS \ (PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \ PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_HARD| \- PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT)+ PCRE2_PARTIAL_SOFT) +#define BASE_MATCH_OPTIONS \+ (PCRE2_NO_JIT|PCRE2_DISABLE_RECURSELOOP_CHECK)+++#if defined(SUPPORT_DIFF_FUZZ) || defined(STANDALONE)+static void print_compile_options(FILE *stream, uint32_t compile_options)+{+fprintf(stream, "Compile options %s%.8x =",+ (compile_options == PCRE2_NEVER_BACKSLASH_C)? "(base) " : "",+ compile_options);++fprintf(stream, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",+ ((compile_options & PCRE2_ALT_BSUX) != 0)? " alt_bsux" : "",+ ((compile_options & PCRE2_ALT_CIRCUMFLEX) != 0)? " alt_circumflex" : "",+ ((compile_options & PCRE2_ALT_VERBNAMES) != 0)? " alt_verbnames" : "",+ ((compile_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)? " allow_empty_class" : "",+ ((compile_options & PCRE2_ANCHORED) != 0)? " anchored" : "",+ ((compile_options & PCRE2_AUTO_CALLOUT) != 0)? " auto_callout" : "",+ ((compile_options & PCRE2_CASELESS) != 0)? " caseless" : "",+ ((compile_options & PCRE2_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",+ ((compile_options & PCRE2_DOTALL) != 0)? " dotall" : "",+ ((compile_options & PCRE2_DUPNAMES) != 0)? " dupnames" : "",+ ((compile_options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",+ ((compile_options & PCRE2_EXTENDED) != 0)? " extended" : "",+ ((compile_options & PCRE2_EXTENDED_MORE) != 0)? " extended_more" : "",+ ((compile_options & PCRE2_FIRSTLINE) != 0)? " firstline" : "",+ ((compile_options & PCRE2_MATCH_UNSET_BACKREF) != 0)? " match_unset_backref" : "",+ ((compile_options & PCRE2_MULTILINE) != 0)? " multiline" : "",+ ((compile_options & PCRE2_NEVER_BACKSLASH_C) != 0)? " never_backslash_c" : "",+ ((compile_options & PCRE2_NEVER_UCP) != 0)? " never_ucp" : "",+ ((compile_options & PCRE2_NEVER_UTF) != 0)? " never_utf" : "",+ ((compile_options & PCRE2_NO_AUTO_CAPTURE) != 0)? " no_auto_capture" : "",+ ((compile_options & PCRE2_NO_AUTO_POSSESS) != 0)? " no_auto_possess" : "",+ ((compile_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)? " no_dotstar_anchor" : "",+ ((compile_options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",+ ((compile_options & PCRE2_NO_START_OPTIMIZE) != 0)? " no_start_optimize" : "",+ ((compile_options & PCRE2_UCP) != 0)? " ucp" : "",+ ((compile_options & PCRE2_UNGREEDY) != 0)? " ungreedy" : "",+ ((compile_options & PCRE2_USE_OFFSET_LIMIT) != 0)? " use_offset_limit" : "",+ ((compile_options & PCRE2_UTF) != 0)? " utf" : "");+}++static void print_match_options(FILE *stream, uint32_t match_options)+{+fprintf(stream, "Match options %s%.8x =",+ (match_options == BASE_MATCH_OPTIONS)? "(base) " : "", match_options);++fprintf(stream, "%s%s%s%s%s%s%s%s%s%s%s\n",+ ((match_options & PCRE2_ANCHORED) != 0)? " anchored" : "",+ ((match_options & PCRE2_DISABLE_RECURSELOOP_CHECK) != 0)? " disable_recurseloop_check" : "",+ ((match_options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",+ ((match_options & PCRE2_NO_JIT) != 0)? " no_jit" : "",+ ((match_options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",+ ((match_options & PCRE2_NOTBOL) != 0)? " notbol" : "",+ ((match_options & PCRE2_NOTEMPTY) != 0)? " notempty" : "",+ ((match_options & PCRE2_NOTEMPTY_ATSTART) != 0)? " notempty_atstart" : "",+ ((match_options & PCRE2_NOTEOL) != 0)? " noteol" : "",+ ((match_options & PCRE2_PARTIAL_HARD) != 0)? " partial_hard" : "",+ ((match_options & PCRE2_PARTIAL_SOFT) != 0)? " partial_soft" : "");+}+++/* This function can print an error message at all code unit widths. */++static void print_error(FILE *f, int errorcode, const char *text, ...)+{+PCRE2_UCHAR buffer[256];+PCRE2_UCHAR *p = buffer;+va_list ap;+va_start(ap, text);+vfprintf(f, text, ap);+va_end(ap);+pcre2_get_error_message(errorcode, buffer, 256);+while (*p != 0) fprintf(f, "%c", *p++);+printf("\n");+}+#endif /* defined(SUPPORT_DIFF_FUZZ || defined(STANDALONE) */+++#ifdef SUPPORT_JIT+#ifdef SUPPORT_DIFF_FUZZ+static void dump_matches(FILE *stream, int count, pcre2_match_data *match_data)+{+int errorcode;++for (int index = 0; index < count; index++)+ {+ PCRE2_UCHAR *bufferptr = NULL;+ PCRE2_SIZE bufflen = 0;++ errorcode = pcre2_substring_get_bynumber(match_data, index, &bufferptr,+ &bufflen);++ if (errorcode >= 0)+ {+ fprintf(stream, "Match %d (hex encoded): ", index);+ for (PCRE2_SIZE i = 0; i < bufflen; i++)+ {+ fprintf(stream, "%02x", bufferptr[i]);+ }+ fprintf(stream, "\n");+ }+ else+ {+ print_error(stream, errorcode, "Match %d failed: ", index);+ }+ }+}++/* This function describes the current test case being evaluated, then aborts */++static void describe_failure(+ const char *task,+ const unsigned char *data,+ size_t size,+ uint32_t compile_options,+ uint32_t match_options,+ int errorcode,+ int errorcode_jit,+ int matches,+ int matches_jit,+ pcre2_match_data *match_data,+ pcre2_match_data *match_data_jit+) {++fprintf(stderr, "Encountered failure while performing %s; context:\n", task);++fprintf(stderr, "Pattern/sample string (hex encoded): ");+for (size_t i = 0; i < size; i++)+ {+ fprintf(stderr, "%02x", data[i]);+ }+fprintf(stderr, "\n");++print_compile_options(stderr, compile_options);+print_match_options(stderr, match_options);++if (errorcode < 0)+ {+ print_error(stderr, errorcode, "Non-JIT'd operation emitted an error: ");+ }++if (matches >= 0)+ {+ fprintf(stderr, "Non-JIT'd operation did not emit an error.\n");+ if (match_data != NULL)+ {+ fprintf(stderr, "%d matches discovered by non-JIT'd regex:\n", matches);+ dump_matches(stderr, matches, match_data);+ fprintf(stderr, "\n");+ }+ }++if (errorcode_jit < 0)+ {+ print_error(stderr, errorcode_jit, "JIT'd operation emitted error %d:",+ errorcode_jit);+ }++if (matches_jit >= 0)+ {+ fprintf(stderr, "JIT'd operation did not emit an error.\n");+ if (match_data_jit != NULL)+ {+ fprintf(stderr, "%d matches discovered by JIT'd regex:\n", matches_jit);+ dump_matches(stderr, matches_jit, match_data_jit);+ fprintf(stderr, "\n");+ }+ }++abort();+}+#endif /* SUPPORT_DIFF_FUZZ */+#endif /* SUPPORT_JIT */+ /* This is the callout function. Its only purpose is to halt matching if there are more than 100 callouts, as one way of stopping too much time being spent on fruitless matches. The callout data is a pointer to the counter. */@@ -50,99 +245,220 @@ /* Putting in this apparently unnecessary prototype prevents gcc from giving a "no previous prototype" warning when compiling at high warning level. */ -int LLVMFuzzerTestOneInput(const unsigned char *, size_t);+int LLVMFuzzerInitialize(int *, char ***); +int LLVMFuzzerTestOneInput(unsigned char *, size_t);++int LLVMFuzzerInitialize(int *argc, char ***argv)+{+int rc;+struct rlimit rlim;+getrlimit(RLIMIT_STACK, &rlim);+rlim.rlim_cur = STACK_SIZE_MB * 1024 * 1024;+if (rlim.rlim_cur > rlim.rlim_max)+ {+ fprintf(stderr, "Hard stack size limit is too small (needed 8MiB)!\n");+ _exit(1);+ }+rc = setrlimit(RLIMIT_STACK, &rlim);+if (rc != 0)+ {+ fprintf(stderr, "Failed to expand stack size\n");+ _exit(1);+ }++(void)argc; /* Avoid "unused parameter" warnings */+(void)argv;+return 0;+}+ /* Here's the driving function. */ -int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size)+int LLVMFuzzerTestOneInput(unsigned char *data, size_t size) {+PCRE2_UCHAR *wdata;+PCRE2_UCHAR *newwdata = NULL; uint32_t compile_options; uint32_t match_options;+uint64_t random_options; pcre2_match_data *match_data = NULL;+#ifdef SUPPORT_JIT+pcre2_match_data *match_data_jit = NULL;+#endif+pcre2_compile_context *compile_context = NULL; pcre2_match_context *match_context = NULL; size_t match_size; int dfa_workspace[DFA_WORKSPACE_COUNT];-int r1, r2;-int i; -if (size < 1) return 0;+if (size < sizeof(random_options)) return -1; +random_options = *(uint64_t *)(data);+data += sizeof(random_options);+wdata = (PCRE2_UCHAR *)data;+size -= sizeof(random_options);+size /= PCRE2_CODE_UNIT_WIDTH / 8;++/* PCRE2 compiles quantified groups by replicating them. In certain cases of+very large quantifiers this can lead to unacceptably long JIT compile times. To+get around this, we scan the data string for large quantifiers that follow a+closing parenthesis, and reduce the value of the quantifier to 10, assuming+that this will make minimal difference to the detection of bugs.++Do the same for quantifiers that follow a closing square bracket, because+classes that contain a number of non-ascii characters can take a lot of time+when matching.++We have to make a copy of the input because oss-fuzz complains if we overwrite+the original. Start the scan at the second character so there can be a+lookbehind for a backslash, and end it before the end so that the next+character can be checked for an opening brace. */++if (size > 3)+ {+ newwdata = malloc(size * sizeof(PCRE2_UCHAR));+ memcpy(newwdata, wdata, size * sizeof(PCRE2_UCHAR));+ wdata = newwdata;++ for (size_t i = 1; i < size - 2; i++)+ {+ size_t j;++ if ((wdata[i] != ')' && wdata[i] != ']') || wdata[i-1] == '\\' ||+ wdata[i+1] != '{')+ continue;+ i++; /* Points to '{' */++ /* Loop for two values a quantifier. Offset i points to brace or comma at the+ start of the loop.*/++ for (int ii = 0; ii < 2; ii++)+ {+ int q = 0;++ if (i >= size - 1) goto END_QSCAN; /* Can happen for , */++ /* Ignore leading spaces */++ while (wdata[i+1] == ' ' || wdata[i+1] == '\t')+ {+ i++;+ if (i >= size - 1) goto END_QSCAN;+ }++ /* Scan for a number ending in brace or comma in the first iteration,+ optionally preceded by space. */++ for (j = i + 1; j < size && j < i + 7; j++)+ {+ if (wdata[j] == ' ' || wdata[j] == '\t')+ {+ j++;+ while (j < size && (wdata[j] == ' ' || wdata[j] == '\t')) j++;+ if (j >= size) goto OUTERLOOP;+ if (wdata[j] != '}' && wdata[j] != ',') goto OUTERLOOP;+ }+ if (wdata[j] == '}' || (ii == 0 && wdata[j] == ',')) break;+ if (wdata[j] < '0' || wdata[j] > '9')+ {+ j--; /* Ensure this character is checked next. The */+ goto OUTERLOOP; /* string might be (e.g.) "){9){234}" */+ }+ q = q * 10 + wdata[j] - '0';+ }++ if (j >= size) goto END_QSCAN; /* End of data */++ /* Hit ',' or '}' or read 6 digits. Six digits is a number > 65536 which is+ the maximum quantifier. Leave such numbers alone. */++ if (j >= i + 7 || q > 65535) goto OUTERLOOP;++ /* Limit the quantifier size to 10 */++ if (q > 10)+ {+#ifdef STANDALONE+ printf("Reduced quantifier value %d to 10.\n", q);+#endif+ for (size_t k = i + 1; k < j; k++) wdata[k] = '0';+ wdata[j - 2] = '1';+ }++ /* Advance to end of number and break if reached closing brace (continue+ after comma, which is only valid in the first time round this loop). */++ i = j;+ if (wdata[i] == '}') break;+ }++ /* Continue along the data string */++ OUTERLOOP:+ i = j;+ continue;+ }+ }+END_QSCAN:+ /* Limiting the length of the subject for matching stops fruitless searches in large trees taking too much time. */ match_size = (size > MAX_MATCH_SIZE)? MAX_MATCH_SIZE : size; -/* Figure out some options to use. Initialize the random number to ensure-repeatability. Ensure that we get a 32-bit unsigned random number for testing-options. (RAND_MAX is required to be at least 32767, but is commonly-2147483647, which excludes the top bit.) */+/* Create a compile context, and set a limit on the size of the compiled+pattern. This stops the fuzzer using vast amounts of memory. */ -srand((unsigned int)(data[size/2]));-r1 = rand();-r2 = rand();+compile_context = pcre2_compile_context_create(NULL);+if (compile_context == NULL)+ {+#ifdef STANDALONE+ fprintf(stderr, "** Failed to create compile context block\n");+#endif+ abort();+ }+pcre2_set_max_pattern_compiled_length(compile_context, 10*1024*1024); /* Ensure that all undefined option bits are zero (waste of time trying them) and also that PCRE2_NO_UTF_CHECK is unset, as there is no guarantee that the-input is UTF-8. Also unset PCRE2_NEVER_UTF and PCRE2_NEVER_UCP as there is no-reason to disallow UTF and UCP. Force PCRE2_NEVER_BACKSLASH_C to be set because-\C in random patterns is highly likely to cause a crash. */+input is valid UTF. Also unset PCRE2_NEVER_UTF and PCRE2_NEVER_UCP as there is+no reason to disallow UTF and UCP. Force PCRE2_NEVER_BACKSLASH_C to be set+because \C in random patterns is highly likely to cause a crash. */ -compile_options =- ((((uint32_t)r1 << 16) | ((uint32_t)r2 & 0xffff)) & ALLOWED_COMPILE_OPTIONS) |+compile_options = ((random_options >> 32) & ALLOWED_COMPILE_OPTIONS) | PCRE2_NEVER_BACKSLASH_C;- -match_options =- ((((uint32_t)r1 << 16) | ((uint32_t)r2 & 0xffff)) & ALLOWED_MATCH_OPTIONS);- +match_options = (((uint32_t)random_options) & ALLOWED_MATCH_OPTIONS) |+ BASE_MATCH_OPTIONS;+ /* Discard partial matching if PCRE2_ENDANCHORED is set, because they are not allowed together and just give an immediate error return. */ if (((compile_options|match_options) & PCRE2_ENDANCHORED) != 0)- match_options &= ~(PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT); + match_options &= ~(PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT); /* Do the compile with and without the options, and after a successful compile, likewise do the match with and without the options. */ -for (i = 0; i < 2; i++)+for (int i = 0; i < 2; i++) { uint32_t callout_count; int errorcode;+#ifdef SUPPORT_JIT+ int errorcode_jit;+#ifdef SUPPORT_DIFF_FUZZ+ int matches = 0;+ int matches_jit = 0;+#endif+#endif PCRE2_SIZE erroroffset; pcre2_code *code; #ifdef STANDALONE- printf("Compile options %.8x never_backslash_c", compile_options);- printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",- ((compile_options & PCRE2_ALT_BSUX) != 0)? ",alt_bsux" : "",- ((compile_options & PCRE2_ALT_CIRCUMFLEX) != 0)? ",alt_circumflex" : "",- ((compile_options & PCRE2_ALT_VERBNAMES) != 0)? ",alt_verbnames" : "",- ((compile_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)? ",allow_empty_class" : "",- ((compile_options & PCRE2_ANCHORED) != 0)? ",anchored" : "",- ((compile_options & PCRE2_AUTO_CALLOUT) != 0)? ",auto_callout" : "",- ((compile_options & PCRE2_CASELESS) != 0)? ",caseless" : "",- ((compile_options & PCRE2_DOLLAR_ENDONLY) != 0)? ",dollar_endonly" : "",- ((compile_options & PCRE2_DOTALL) != 0)? ",dotall" : "",- ((compile_options & PCRE2_DUPNAMES) != 0)? ",dupnames" : "",- ((compile_options & PCRE2_ENDANCHORED) != 0)? ",endanchored" : "",- ((compile_options & PCRE2_EXTENDED) != 0)? ",extended" : "",- ((compile_options & PCRE2_FIRSTLINE) != 0)? ",firstline" : "",- ((compile_options & PCRE2_MATCH_UNSET_BACKREF) != 0)? ",match_unset_backref" : "",- ((compile_options & PCRE2_MULTILINE) != 0)? ",multiline" : "",- ((compile_options & PCRE2_NEVER_UCP) != 0)? ",never_ucp" : "",- ((compile_options & PCRE2_NEVER_UTF) != 0)? ",never_utf" : "",- ((compile_options & PCRE2_NO_AUTO_CAPTURE) != 0)? ",no_auto_capture" : "",- ((compile_options & PCRE2_NO_AUTO_POSSESS) != 0)? ",no_auto_possess" : "",- ((compile_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)? ",no_dotstar_anchor" : "",- ((compile_options & PCRE2_NO_UTF_CHECK) != 0)? ",no_utf_check" : "",- ((compile_options & PCRE2_NO_START_OPTIMIZE) != 0)? ",no_start_optimize" : "",- ((compile_options & PCRE2_UCP) != 0)? ",ucp" : "",- ((compile_options & PCRE2_UNGREEDY) != 0)? ",ungreedy" : "",- ((compile_options & PCRE2_USE_OFFSET_LIMIT) != 0)? ",use_offset_limit" : "",- ((compile_options & PCRE2_UTF) != 0)? ",utf" : "");+ printf("\n");+ print_compile_options(stdout, compile_options); #endif - code = pcre2_compile((PCRE2_SPTR)data, (PCRE2_SIZE)size, compile_options,- &errorcode, &erroroffset, NULL);+ code = pcre2_compile((PCRE2_SPTR)wdata, (PCRE2_SIZE)size, compile_options,+ &errorcode, &erroroffset, compile_context); /* Compilation succeeded */ @@ -151,9 +467,29 @@ int j; uint32_t save_match_options = match_options; + /* Call JIT compile only if the compiled pattern is not too big. */+ #ifdef SUPPORT_JIT- pcre2_jit_compile(code, PCRE2_JIT_COMPLETE);+ int jit_ret = -1;+ if (((struct pcre2_real_code *)code)->blocksize <= JIT_SIZE_LIMIT)+ {+#ifdef STANDALONE+ printf("Compile succeeded; calling JIT compile\n"); #endif+ jit_ret = pcre2_jit_compile(code, PCRE2_JIT_COMPLETE);+#ifdef STANDALONE+ if (jit_ret < 0) printf("JIT compile error %d\n", jit_ret);+#endif+ }+ else+ {+#ifdef STANDALONE+ printf("Not calling JIT: compiled pattern is too long "+ "(%ld bytes; limit=%d)\n",+ ((struct pcre2_real_code *)code)->blocksize, JIT_SIZE_LIMIT);+#endif+ }+#endif /* SUPPORT_JIT */ /* Create match data and context blocks only when we first need them. Set low match and depth limits to avoid wasting too much searching large@@ -162,12 +498,17 @@ if (match_data == NULL) { match_data = pcre2_match_data_create(32, NULL);+#ifdef SUPPORT_JIT+ match_data_jit = pcre2_match_data_create(32, NULL);+ if (match_data == NULL || match_data_jit == NULL)+#else if (match_data == NULL)+#endif { #ifdef STANDALONE- printf("** Failed to create match data block\n");+ fprintf(stderr, "** Failed to create match data block\n"); #endif- return 0;+ abort(); } } @@ -177,9 +518,9 @@ if (match_context == NULL) { #ifdef STANDALONE- printf("** Failed to create match context block\n");+ fprintf(stderr, "** Failed to create match context block\n"); #endif- return 0;+ abort(); } (void)pcre2_set_match_limit(match_context, 100); (void)pcre2_set_depth_limit(match_context, 100);@@ -188,74 +529,150 @@ /* Match twice, with and without options. */ +#ifdef STANDALONE+ printf("\n");+#endif for (j = 0; j < 2; j++) { #ifdef STANDALONE- printf("Match options %.8x", match_options);- printf("%s%s%s%s%s%s%s%s%s%s\n",- ((match_options & PCRE2_ANCHORED) != 0)? ",anchored" : "",- ((match_options & PCRE2_ENDANCHORED) != 0)? ",endanchored" : "",- ((match_options & PCRE2_NO_JIT) != 0)? ",no_jit" : "",- ((match_options & PCRE2_NO_UTF_CHECK) != 0)? ",no_utf_check" : "",- ((match_options & PCRE2_NOTBOL) != 0)? ",notbol" : "",- ((match_options & PCRE2_NOTEMPTY) != 0)? ",notempty" : "",- ((match_options & PCRE2_NOTEMPTY_ATSTART) != 0)? ",notempty_atstart" : "",- ((match_options & PCRE2_NOTEOL) != 0)? ",noteol" : "",- ((match_options & PCRE2_PARTIAL_HARD) != 0)? ",partial_hard" : "",- ((match_options & PCRE2_PARTIAL_SOFT) != 0)? ",partial_soft" : "");+ print_match_options(stdout, match_options); #endif callout_count = 0;- errorcode = pcre2_match(code, (PCRE2_SPTR)data, (PCRE2_SIZE)match_size, 0,+ errorcode = pcre2_match(code, (PCRE2_SPTR)wdata, (PCRE2_SIZE)match_size, 0, match_options, match_data, match_context); #ifdef STANDALONE if (errorcode >= 0) printf("Match returned %d\n", errorcode); else+ print_error(stdout, errorcode, "Match failed: error %d: ", errorcode);+#endif++/* If JIT is enabled, do a JIT match and, if appropriately compiled, compare+with the interpreter. */++#ifdef SUPPORT_JIT+ if (jit_ret >= 0) {- unsigned char buffer[256];- pcre2_get_error_message(errorcode, buffer, 256);- printf("Match failed: error %d: %s\n", errorcode, buffer);- }+#ifdef STANDALONE+ printf("Matching with JIT\n"); #endif+ callout_count = 0;+ errorcode_jit = pcre2_match(code, (PCRE2_SPTR)wdata, (PCRE2_SIZE)match_size, 0,+ match_options & ~PCRE2_NO_JIT, match_data_jit, match_context); - match_options = 0; /* For second time */+#ifdef STANDALONE+ if (errorcode_jit >= 0)+ printf("Match returned %d\n", errorcode_jit);+ else+ print_error(stdout, errorcode_jit, "JIT match failed: error %d: ",+ errorcode_jit);+#else+ (void)errorcode_jit; /* Avoid compiler warning */+#endif /* STANDALONE */++/* With differential matching enabled, compare with interpreter. */++#ifdef SUPPORT_DIFF_FUZZ+ matches = errorcode;+ matches_jit = errorcode_jit;++ if (errorcode_jit != errorcode)+ {+ if (!(errorcode < 0 && errorcode_jit < 0) &&+ errorcode != PCRE2_ERROR_MATCHLIMIT && errorcode != PCRE2_ERROR_CALLOUT &&+ errorcode_jit != PCRE2_ERROR_MATCHLIMIT && errorcode_jit != PCRE2_ERROR_JIT_STACKLIMIT && errorcode_jit != PCRE2_ERROR_CALLOUT)+ {+ describe_failure("match errorcode comparison", wdata, size, compile_options, match_options, errorcode, errorcode_jit, matches, matches_jit, match_data, match_data_jit);+ }+ }+ else+ {+ for (int index = 0; index < errorcode; index++)+ {+ PCRE2_UCHAR *bufferptr, *bufferptr_jit;+ PCRE2_SIZE bufflen, bufflen_jit;++ bufferptr = bufferptr_jit = NULL;+ bufflen = bufflen_jit = 0;++ errorcode = pcre2_substring_get_bynumber(match_data, (uint32_t) index, &bufferptr, &bufflen);+ errorcode_jit = pcre2_substring_get_bynumber(match_data_jit, (uint32_t) index, &bufferptr_jit, &bufflen_jit);++ if (errorcode != errorcode_jit)+ {+ describe_failure("match entry errorcode comparison", wdata, size,+ compile_options, match_options, errorcode, errorcode_jit,+ matches, matches_jit, match_data, match_data_jit);+ }++ if (errorcode >= 0)+ {+ if (bufflen != bufflen_jit)+ {+ describe_failure("match entry length comparison", wdata, size,+ compile_options, match_options, errorcode, errorcode_jit,+ matches, matches_jit, match_data, match_data_jit);+ }++ if (memcmp(bufferptr, bufferptr_jit, bufflen) != 0)+ {+ describe_failure("match entry content comparison", wdata, size,+ compile_options, match_options, errorcode, errorcode_jit,+ matches, matches_jit, match_data, match_data_jit);+ }+ }++ pcre2_substring_free(bufferptr);+ pcre2_substring_free(bufferptr_jit);+ }+ }+#endif /* SUPPORT_DIFF_FUZZ */+ }+#endif /* SUPPORT_JIT */++ if (match_options == BASE_MATCH_OPTIONS) break; /* Don't do same twice */+ match_options = BASE_MATCH_OPTIONS; /* For second time */ } - /* Match with DFA twice, with and without options. */+ /* Match with DFA twice, with and without options, but remove options that+ are not allowed with DFA. */ - match_options = save_match_options & ~PCRE2_NO_JIT; /* Not valid for DFA */+ match_options = save_match_options & ~BASE_MATCH_OPTIONS; +#ifdef STANDALONE+ printf("\n");+#endif+ for (j = 0; j < 2; j++) { #ifdef STANDALONE- printf("DFA match options %.8x", match_options);+ printf("DFA match options %.8x =", match_options); printf("%s%s%s%s%s%s%s%s%s\n",- ((match_options & PCRE2_ANCHORED) != 0)? ",anchored" : "",- ((match_options & PCRE2_ENDANCHORED) != 0)? ",endanchored" : "",- ((match_options & PCRE2_NO_UTF_CHECK) != 0)? ",no_utf_check" : "",- ((match_options & PCRE2_NOTBOL) != 0)? ",notbol" : "",- ((match_options & PCRE2_NOTEMPTY) != 0)? ",notempty" : "",- ((match_options & PCRE2_NOTEMPTY_ATSTART) != 0)? ",notempty_atstart" : "",- ((match_options & PCRE2_NOTEOL) != 0)? ",noteol" : "",- ((match_options & PCRE2_PARTIAL_HARD) != 0)? ",partial_hard" : "",- ((match_options & PCRE2_PARTIAL_SOFT) != 0)? ",partial_soft" : "");+ ((match_options & PCRE2_ANCHORED) != 0)? " anchored" : "",+ ((match_options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",+ ((match_options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",+ ((match_options & PCRE2_NOTBOL) != 0)? " notbol" : "",+ ((match_options & PCRE2_NOTEMPTY) != 0)? " notempty" : "",+ ((match_options & PCRE2_NOTEMPTY_ATSTART) != 0)? " notempty_atstart" : "",+ ((match_options & PCRE2_NOTEOL) != 0)? " noteol" : "",+ ((match_options & PCRE2_PARTIAL_HARD) != 0)? " partial_hard" : "",+ ((match_options & PCRE2_PARTIAL_SOFT) != 0)? " partial_soft" : ""); #endif callout_count = 0;- errorcode = pcre2_dfa_match(code, (PCRE2_SPTR)data,- (PCRE2_SIZE)match_size, 0, match_options, match_data, match_context,- dfa_workspace, DFA_WORKSPACE_COUNT);+ errorcode = pcre2_dfa_match(code, (PCRE2_SPTR)wdata,+ (PCRE2_SIZE)match_size, 0, match_options, match_data,+ match_context, dfa_workspace, DFA_WORKSPACE_COUNT); #ifdef STANDALONE- if (errorcode >= 0) printf("Match returned %d\n", errorcode); else- {- unsigned char buffer[256];- pcre2_get_error_message(errorcode, buffer, 256);- printf("Match failed: error %d: %s\n", errorcode, buffer);- }+ if (errorcode >= 0)+ printf("Match returned %d\n", errorcode);+ else+ print_error(stdout, errorcode, "DFA match failed: error %d: ", errorcode); #endif - match_options = 0; /* For second time */+ if (match_options == 0) break; /* No point doing same twice */+ match_options = 0; /* For second time */ } match_options = save_match_options; /* Reset for the second compile */@@ -266,21 +683,27 @@ else {- unsigned char buffer[256];- pcre2_get_error_message(errorcode, buffer, 256); #ifdef STANDALONE- printf("Error %d at offset %lu: %s\n", errorcode, erroroffset, buffer);+ print_error(stdout, errorcode, "Error %d at offset %lu: ", errorcode,+ erroroffset); #else- if (strstr((const char *)buffer, "internal error") != NULL) abort();+ if (errorcode == PCRE2_ERROR_INTERNAL) abort(); #endif } - compile_options = PCRE2_NEVER_BACKSLASH_C; /* For second time */+ if (compile_options == PCRE2_NEVER_BACKSLASH_C) break; /* Avoid same twice */+ compile_options = PCRE2_NEVER_BACKSLASH_C; /* For second time */ } +/* Tidy up before exiting */+ if (match_data != NULL) pcre2_match_data_free(match_data);+#ifdef SUPPORT_JIT+if (match_data_jit != NULL) pcre2_match_data_free(match_data_jit);+free(newwdata);+#endif if (match_context != NULL) pcre2_match_context_free(match_context);-+if (compile_context != NULL) pcre2_compile_context_free(compile_context); return 0; } @@ -290,7 +713,7 @@ #ifdef STANDALONE int main(int argc, char **argv) {-int i;+LLVMFuzzerInitialize(&argc, &argv); if (argc < 2) {@@ -298,7 +721,7 @@ return 0; } -for (i = 1; i < argc; i++)+for (int i = 1; i < argc; i++) { size_t filelen; size_t readsize;
src/c/pcre2/src/pcre2_internal.h view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2022 University of Cambridge+ New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -51,6 +51,24 @@ #error The use of both EBCDIC and SUPPORT_UNICODE is not supported. #endif +/* When compiling one of the libraries, the value of PCRE2_CODE_UNIT_WIDTH must+be 8, 16, or 32. AutoTools and CMake ensure that this is always the case, but+other other building methods may not, so here is a check. It is cut out when+building pcre2test, bcause that sets the value to zero. No other source should+be including this file. There is no explicit way of forcing a compile to be+abandoned, but trying to include a non-existent file seems cleanest. Otherwise+there will be many irrelevant consequential errors. */++#if (!defined PCRE2_BUILDING_PCRE2TEST && !defined PCRE2_DFTABLES) && \+ (!defined PCRE2_CODE_UNIT_WIDTH || \+ (PCRE2_CODE_UNIT_WIDTH != 8 && \+ PCRE2_CODE_UNIT_WIDTH != 16 && \+ PCRE2_CODE_UNIT_WIDTH != 32))+#error PCRE2_CODE_UNIT_WIDTH must be defined as 8, 16, or 32.+#include <AbandonCompile>+#endif++ /* Standard C headers */ #include <ctype.h>@@ -119,20 +137,20 @@ #ifndef PCRE2_EXP_DECL # ifdef _WIN32 # ifndef PCRE2_STATIC-# define PCRE2_EXP_DECL extern __declspec(dllexport)-# define PCRE2_EXP_DEFN __declspec(dllexport)+# define PCRE2_EXP_DECL extern __declspec(dllexport)+# define PCRE2_EXP_DEFN __declspec(dllexport) # else-# define PCRE2_EXP_DECL extern+# define PCRE2_EXP_DECL extern PCRE2_EXPORT # define PCRE2_EXP_DEFN # endif # else # ifdef __cplusplus-# define PCRE2_EXP_DECL extern "C"+# define PCRE2_EXP_DECL extern "C" PCRE2_EXPORT # else-# define PCRE2_EXP_DECL extern+# define PCRE2_EXP_DECL extern PCRE2_EXPORT # endif # ifndef PCRE2_EXP_DEFN-# define PCRE2_EXP_DEFN PCRE2_EXP_DECL+# define PCRE2_EXP_DEFN PCRE2_EXP_DECL # endif # endif #endif@@ -156,8 +174,8 @@ #define PCRE2_SPTR CUSTOM_SUBJECT_PTR #endif -/* When checking for integer overflow in pcre2_compile(), we need to handle-large integers. If a 64-bit integer type is available, we can use that.+/* When checking for integer overflow, we need to handle large integers.+If a 64-bit integer type is available, we can use that. Otherwise we have to cast to double, which of course requires floating point arithmetic. Handle this by defining a macro for the appropriate type. */ @@ -220,18 +238,17 @@ #define COMPILE_ERROR_BASE 100 -/* The initial frames vector for remembering backtracking points in-pcre2_match() is allocated on the system stack, of this size (bytes). The size-must be a multiple of sizeof(PCRE2_SPTR) in all environments, so making it a-multiple of 8 is best. Typical frame sizes are a few hundred bytes (it depends-on the number of capturing parentheses) so 20KiB handles quite a few frames. A-larger vector on the heap is obtained for patterns that need more frames. The-maximum size of this can be limited. */+/* The initial frames vector for remembering pcre2_match() backtracking points+is allocated on the heap, of this size (bytes) or ten times the frame size if+larger, unless the heap limit is smaller. Typical frame sizes are a few hundred+bytes (it depends on the number of capturing parentheses) so 20KiB handles+quite a few frames. A larger vector on the heap is obtained for matches that+need more frames, subject to the heap limit. */ #define START_FRAMES_SIZE 20480 -/* Similarly, for DFA matching, an initial internal workspace vector is-allocated on the stack. */+/* For DFA matching, an initial internal workspace vector is allocated on the+stack. The heap is used only if this turns out to be too small. */ #define DFA_START_RWS_SIZE 30720 @@ -1282,7 +1299,7 @@ #define PT_ALNUM 6 /* Alphanumeric - the union of L and N */ #define PT_SPACE 7 /* Perl space - general category Z plus 9,10,12,13 */ #define PT_PXSPACE 8 /* POSIX space - Z plus 9,10,11,12,13 */-#define PT_WORD 9 /* Word - L plus N plus underscore */+#define PT_WORD 9 /* Word - L, N, Mn, or Pc */ #define PT_CLIST 10 /* Pseudo-property: match character list */ #define PT_UCNC 11 /* Universal Character nameable character */ #define PT_BIDICL 12 /* Specified bidi class */@@ -1298,6 +1315,7 @@ #define PT_PXGRAPH 14 /* [:graph:] - characters that mark the paper */ #define PT_PXPRINT 15 /* [:print:] - [:graph:] plus non-control spaces */ #define PT_PXPUNCT 16 /* [:punct:] - punctuation characters */+#define PT_PXXDIGIT 17 /* [:xdigit:] - hex digits */ /* This value is used when parsing \p and \P escapes to indicate that neither \p{script:...} nor \p{scx:...} has been encountered. */@@ -1328,6 +1346,12 @@ compatibility mode, and for \C in non-utf mode. In non-DOTALL mode, "." behaves like \N. +ESC_ub is a special return from check_escape() when, in BSUX mode, \u{ is not+followed by hex digits and }, in which case it should mean a literal "u"+followed by a literal "{". This hack is necessary for cases like \u{ 12}+because without it, this is interpreted as u{12} now that spaces are allowed in+quantifiers.+ Negative numbers are used to encode a backreference (\1, \2, \3, etc.) in check_escape(). There are tests in the code for an escape greater than ESC_b and less than ESC_Z to detect the types that may be repeated. These are the@@ -1337,7 +1361,7 @@ enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w, ESC_N, ESC_dum, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H, ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z,- ESC_E, ESC_Q, ESC_g, ESC_k };+ ESC_E, ESC_Q, ESC_g, ESC_k, ESC_ub }; /********************** Opcode definitions ******************/@@ -1373,8 +1397,8 @@ OP_SOD, /* 1 Start of data: \A */ OP_SOM, /* 2 Start of match (subject + offset): \G */ OP_SET_SOM, /* 3 Set start of match (\K) */- OP_NOT_WORD_BOUNDARY, /* 4 \B */- OP_WORD_BOUNDARY, /* 5 \b */+ OP_NOT_WORD_BOUNDARY, /* 4 \B -- see also OP_NOT_UCP_WORD_BOUNDARY */+ OP_WORD_BOUNDARY, /* 5 \b -- see also OP_UCP_WORD_BOUNDARY */ OP_NOT_DIGIT, /* 6 \D */ OP_DIGIT, /* 7 \d */ OP_NOT_WHITESPACE, /* 8 \S */@@ -1548,79 +1572,86 @@ /* The assertions must come before BRA, CBRA, ONCE, and COND. */ OP_REVERSE, /* 125 Move pointer back - used in lookbehind assertions */- OP_ASSERT, /* 126 Positive lookahead */- OP_ASSERT_NOT, /* 127 Negative lookahead */- OP_ASSERTBACK, /* 128 Positive lookbehind */- OP_ASSERTBACK_NOT, /* 129 Negative lookbehind */- OP_ASSERT_NA, /* 130 Positive non-atomic lookahead */- OP_ASSERTBACK_NA, /* 131 Positive non-atomic lookbehind */+ OP_VREVERSE, /* 126 Move pointer back - variable */+ OP_ASSERT, /* 127 Positive lookahead */+ OP_ASSERT_NOT, /* 128 Negative lookahead */+ OP_ASSERTBACK, /* 129 Positive lookbehind */+ OP_ASSERTBACK_NOT, /* 130 Negative lookbehind */+ OP_ASSERT_NA, /* 131 Positive non-atomic lookahead */+ OP_ASSERTBACK_NA, /* 132 Positive non-atomic lookbehind */ /* ONCE, SCRIPT_RUN, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come immediately after the assertions, with ONCE first, as there's a test for >= ONCE for a subpattern that isn't an assertion. The POS versions must immediately follow the non-POS versions in each case. */ - OP_ONCE, /* 132 Atomic group, contains captures */- OP_SCRIPT_RUN, /* 133 Non-capture, but check characters' scripts */- OP_BRA, /* 134 Start of non-capturing bracket */- OP_BRAPOS, /* 135 Ditto, with unlimited, possessive repeat */- OP_CBRA, /* 136 Start of capturing bracket */- OP_CBRAPOS, /* 137 Ditto, with unlimited, possessive repeat */- OP_COND, /* 138 Conditional group */+ OP_ONCE, /* 133 Atomic group, contains captures */+ OP_SCRIPT_RUN, /* 134 Non-capture, but check characters' scripts */+ OP_BRA, /* 135 Start of non-capturing bracket */+ OP_BRAPOS, /* 136 Ditto, with unlimited, possessive repeat */+ OP_CBRA, /* 137 Start of capturing bracket */+ OP_CBRAPOS, /* 138 Ditto, with unlimited, possessive repeat */+ OP_COND, /* 139 Conditional group */ /* These five must follow the previous five, in the same order. There's a check for >= SBRA to distinguish the two sets. */ - OP_SBRA, /* 139 Start of non-capturing bracket, check empty */- OP_SBRAPOS, /* 149 Ditto, with unlimited, possessive repeat */- OP_SCBRA, /* 141 Start of capturing bracket, check empty */- OP_SCBRAPOS, /* 142 Ditto, with unlimited, possessive repeat */- OP_SCOND, /* 143 Conditional group, check empty */+ OP_SBRA, /* 140 Start of non-capturing bracket, check empty */+ OP_SBRAPOS, /* 141 Ditto, with unlimited, possessive repeat */+ OP_SCBRA, /* 142 Start of capturing bracket, check empty */+ OP_SCBRAPOS, /* 143 Ditto, with unlimited, possessive repeat */+ OP_SCOND, /* 144 Conditional group, check empty */ /* The next two pairs must (respectively) be kept together. */ - OP_CREF, /* 144 Used to hold a capture number as condition */- OP_DNCREF, /* 145 Used to point to duplicate names as a condition */- OP_RREF, /* 146 Used to hold a recursion number as condition */- OP_DNRREF, /* 147 Used to point to duplicate names as a condition */- OP_FALSE, /* 148 Always false (used by DEFINE and VERSION) */- OP_TRUE, /* 149 Always true (used by VERSION) */+ OP_CREF, /* 145 Used to hold a capture number as condition */+ OP_DNCREF, /* 146 Used to point to duplicate names as a condition */+ OP_RREF, /* 147 Used to hold a recursion number as condition */+ OP_DNRREF, /* 148 Used to point to duplicate names as a condition */+ OP_FALSE, /* 149 Always false (used by DEFINE and VERSION) */+ OP_TRUE, /* 150 Always true (used by VERSION) */ - OP_BRAZERO, /* 150 These two must remain together and in this */- OP_BRAMINZERO, /* 151 order. */- OP_BRAPOSZERO, /* 152 */+ OP_BRAZERO, /* 151 These two must remain together and in this */+ OP_BRAMINZERO, /* 152 order. */+ OP_BRAPOSZERO, /* 153 */ /* These are backtracking control verbs */ - OP_MARK, /* 153 always has an argument */- OP_PRUNE, /* 154 */- OP_PRUNE_ARG, /* 155 same, but with argument */- OP_SKIP, /* 156 */- OP_SKIP_ARG, /* 157 same, but with argument */- OP_THEN, /* 158 */- OP_THEN_ARG, /* 159 same, but with argument */- OP_COMMIT, /* 160 */- OP_COMMIT_ARG, /* 161 same, but with argument */+ OP_MARK, /* 154 always has an argument */+ OP_PRUNE, /* 155 */+ OP_PRUNE_ARG, /* 156 same, but with argument */+ OP_SKIP, /* 157 */+ OP_SKIP_ARG, /* 158 same, but with argument */+ OP_THEN, /* 159 */+ OP_THEN_ARG, /* 160 same, but with argument */+ OP_COMMIT, /* 161 */+ OP_COMMIT_ARG, /* 162 same, but with argument */ /* These are forced failure and success verbs. FAIL and ACCEPT do accept an argument, but these cases can be compiled as, for example, (*MARK:X)(*FAIL) without the need for a special opcode. */ - OP_FAIL, /* 162 */- OP_ACCEPT, /* 163 */- OP_ASSERT_ACCEPT, /* 164 Used inside assertions */- OP_CLOSE, /* 165 Used before OP_ACCEPT to close open captures */+ OP_FAIL, /* 163 */+ OP_ACCEPT, /* 164 */+ OP_ASSERT_ACCEPT, /* 165 Used inside assertions */+ OP_CLOSE, /* 166 Used before OP_ACCEPT to close open captures */ /* This is used to skip a subpattern with a {0} quantifier */ - OP_SKIPZERO, /* 166 */+ OP_SKIPZERO, /* 167 */ /* This is used to identify a DEFINE group during compilation so that it can be checked for having only one branch. It is changed to OP_FALSE before compilation finishes. */ - OP_DEFINE, /* 167 */+ OP_DEFINE, /* 168 */ + /* These opcodes replace their normal counterparts in UCP mode when+ PCRE2_EXTRA_ASCII_BSW is not set. */++ OP_NOT_UCP_WORD_BOUNDARY, /* 169 */+ OP_UCP_WORD_BOUNDARY, /* 170 */+ /* This is not an opcode, but is used to check that tables indexed by opcode are the correct length, in order to catch updating errors - there have been some in the past. */@@ -1665,7 +1696,7 @@ "class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \ "Recurse", "Callout", "CalloutStr", \ "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \- "Reverse", "Assert", "Assert not", \+ "Reverse", "VReverse", "Assert", "Assert not", \ "Assert back", "Assert back not", \ "Non-atomic assert", "Non-atomic assert back", \ "Once", \@@ -1680,7 +1711,7 @@ "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \ "*THEN", "*THEN", "*COMMIT", "*COMMIT", "*FAIL", \ "*ACCEPT", "*ASSERT_ACCEPT", \- "Close", "Skip zero", "Define"+ "Close", "Skip zero", "Define", "\\B (ucp)", "\\b (ucp)" /* This macro defines the length of fixed length operations in the compiled@@ -1747,7 +1778,8 @@ 1+LINK_SIZE, /* KetRmax */ \ 1+LINK_SIZE, /* KetRmin */ \ 1+LINK_SIZE, /* KetRpos */ \- 1+LINK_SIZE, /* Reverse */ \+ 1+IMM2_SIZE, /* Reverse */ \+ 1+2*IMM2_SIZE, /* VReverse */ \ 1+LINK_SIZE, /* Assert */ \ 1+LINK_SIZE, /* Assert not */ \ 1+LINK_SIZE, /* Assert behind */ \@@ -1776,7 +1808,8 @@ 1, 3, /* COMMIT, COMMIT_ARG */ \ 1, 1, 1, /* FAIL, ACCEPT, ASSERT_ACCEPT */ \ 1+IMM2_SIZE, 1, /* CLOSE, SKIPZERO */ \- 1 /* DEFINE */+ 1, /* DEFINE */ \+ 1, 1 /* \B and \b in UCP mode */ /* A magic value for OP_RREF to indicate the "any recursion" condition. */ @@ -2043,6 +2076,9 @@ #endif #endif /* PCRE2_CODE_UNIT_WIDTH */++extern BOOL PRIV(ckd_smul)(PCRE2_SIZE *, int, int);+ #endif /* PCRE2_INTERNAL_H_IDEMPOTENT_GUARD */ /* End of pcre2_internal.h */
src/c/pcre2/src/pcre2_intmodedep.h view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2018 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -568,10 +568,12 @@ void *stack_guard_data; const uint8_t *tables; PCRE2_SIZE max_pattern_length;+ PCRE2_SIZE max_pattern_compiled_length; uint16_t bsr_convention; uint16_t newline_convention; uint32_t parens_nest_limit; uint32_t extra_options;+ uint32_t max_varlookbehind; } pcre2_real_compile_context; /* The real match context structure. */@@ -605,12 +607,12 @@ copying the size from possibly unaligned memory into a variable of the same type. Use a macro rather than a typedef to avoid compiler warnings when this file is included multiple times by pcre2test. LOOKBEHIND_MAX specifies the-largest lookbehind that is supported. (OP_REVERSE in a pattern has a 16-bit-argument in 8-bit and 16-bit modes, so we need no more than a 16-bit field-here.) */+largest lookbehind that is supported. (OP_REVERSE and OP_VREVERSE in a pattern+have 16-bit arguments in 8-bit and 16-bit modes, so we need no more than a+16-bit field here.) */ #undef CODE_BLOCKSIZE_TYPE-#define CODE_BLOCKSIZE_TYPE size_t+#define CODE_BLOCKSIZE_TYPE PCRE2_SIZE #undef LOOKBEHIND_MAX #define LOOKBEHIND_MAX UINT16_MAX@@ -649,19 +651,24 @@ subpatterns is 65535 we must allow for 65536 strings to include the overall match. (See also the heapframe structure below.) */ +struct heapframe; /* Forward reference */+ typedef struct pcre2_real_match_data {- pcre2_memctl memctl;- const pcre2_real_code *code; /* The pattern used for the match */- PCRE2_SPTR subject; /* The subject that was matched */- PCRE2_SPTR mark; /* Pointer to last mark */- PCRE2_SIZE leftchar; /* Offset to leftmost code unit */- PCRE2_SIZE rightchar; /* Offset to rightmost code unit */- PCRE2_SIZE startchar; /* Offset to starting code unit */- uint8_t matchedby; /* Type of match (normal, JIT, DFA) */- uint8_t flags; /* Various flags */- uint16_t oveccount; /* Number of pairs */- int rc; /* The return code from the match */- PCRE2_SIZE ovector[131072]; /* Must be last in the structure */+ pcre2_memctl memctl; /* Memory control fields */+ const pcre2_real_code *code; /* The pattern used for the match */+ PCRE2_SPTR subject; /* The subject that was matched */+ PCRE2_SPTR mark; /* Pointer to last mark */+ struct heapframe *heapframes; /* Backtracking frames heap memory */+ PCRE2_SIZE heapframes_size; /* Malloc-ed size */+ PCRE2_SIZE subject_length; /* Subject length */+ PCRE2_SIZE leftchar; /* Offset to leftmost code unit */+ PCRE2_SIZE rightchar; /* Offset to rightmost code unit */+ PCRE2_SIZE startchar; /* Offset to starting code unit */+ uint8_t matchedby; /* Type of match (normal, JIT, DFA) */+ uint8_t flags; /* Various flags */+ uint16_t oveccount; /* Number of pairs */+ int rc; /* The return code from the match */+ PCRE2_SIZE ovector[131072]; /* Must be last in the structure */ } pcre2_real_match_data; @@ -671,8 +678,8 @@ #ifndef PCRE2_PCRE2TEST -/* Structures for checking for mutual recursion when scanning compiled or-parsed code. */+/* Structures for checking for mutual function recursion when scanning compiled+or parsed code. */ typedef struct recurse_check { struct recurse_check *prev;@@ -684,7 +691,7 @@ uint32_t *groupptr; } parsed_recurse_check; -/* Structure for building a cache when filling in recursion offsets. */+/* Structure for building a cache when filling in pattern recursion offsets. */ typedef struct recurse_cache { PCRE2_SPTR group;@@ -730,7 +737,6 @@ uint16_t name_entry_size; /* Size of each entry */ uint16_t parens_depth; /* Depth of nested parentheses */ uint16_t assert_depth; /* Depth of nested assertions */- open_capitem *open_caps; /* Chain of open capture items */ named_group *named_groups; /* Points to vector in pre-compile */ uint32_t named_group_list_size; /* Number of entries in the list */ uint32_t external_options; /* External (initial) options */@@ -748,10 +754,11 @@ uint32_t class_range_end; /* Overall class range end */ PCRE2_UCHAR nl[4]; /* Newline string when fixed length */ uint32_t req_varyopt; /* "After variable item" flag for reqbyte */- int max_lookbehind; /* Maximum lookbehind (characters) */+ uint32_t max_varlookbehind; /* Limit for variable lookbehinds */+ int max_lookbehind; /* Maximum lookbehind encountered (characters) */ BOOL had_accept; /* (*ACCEPT) encountered */ BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */- BOOL had_recurse; /* Had a recursion or subroutine call */+ BOOL had_recurse; /* Had a pattern recursion or subroutine call */ BOOL dupnames; /* Duplicate names exist */ } compile_block; @@ -769,6 +776,7 @@ typedef struct dfa_recursion_info { struct dfa_recursion_info *prevrec; PCRE2_SPTR subject_position;+ PCRE2_SPTR last_used_ptr; uint32_t group_num; } dfa_recursion_info; @@ -789,7 +797,7 @@ PCRE2_SIZE length; /* Used for character, string, or code lengths */ PCRE2_SIZE back_frame; /* Amount to subtract on RRETURN */ PCRE2_SIZE temp_size; /* Used for short-term PCRE2_SIZE values */- uint32_t rdepth; /* "Recursion" depth */+ uint32_t rdepth; /* Function "recursion" depth within pcre2_match() */ uint32_t group_frame_type; /* Type information for group frames */ uint32_t temp_32[4]; /* Used for short-term 32-bit or BOOL values */ uint8_t return_id; /* Where to go on in internal "return" */@@ -822,14 +830,15 @@ allows for exactly the right size ovector for the number of capturing parentheses. (See also the comment for pcre2_real_match_data above.) */ - PCRE2_SPTR eptr; /* MUST BE FIRST */- PCRE2_SPTR start_match; /* Can be adjusted by \K */- PCRE2_SPTR mark; /* Most recent mark on the success path */- uint32_t current_recurse; /* Current (deepest) recursion number */- uint32_t capture_last; /* Most recent capture */- PCRE2_SIZE last_group_offset; /* Saved offset to most recent group frame */- PCRE2_SIZE offset_top; /* Offset after highest capture */- PCRE2_SIZE ovector[131072]; /* Must be last in the structure */+ PCRE2_SPTR eptr; /* MUST BE FIRST */+ PCRE2_SPTR start_match; /* Can be adjusted by \K */+ PCRE2_SPTR mark; /* Most recent mark on the success path */+ PCRE2_SPTR recurse_last_used; /* Last character used at time of pattern recursion */+ uint32_t current_recurse; /* Group number of current (deepest) pattern recursion */+ uint32_t capture_last; /* Most recent capture */+ PCRE2_SIZE last_group_offset; /* Saved offset to most recent group frame */+ PCRE2_SIZE offset_top; /* Offset after highest capture */+ PCRE2_SIZE ovector[131072]; /* Must be last in the structure */ } heapframe; /* This typedef is a check that the size of the heapframe structure is a@@ -854,11 +863,7 @@ typedef struct match_block { pcre2_memctl memctl; /* For general use */- PCRE2_SIZE frame_vector_size; /* Size of a backtracking frame */- heapframe *match_frames; /* Points to vector of frames */- heapframe *match_frames_top; /* Points after the end of the vector */- heapframe *stack_frames; /* The original vector on the stack */- PCRE2_SIZE heap_limit; /* As it says */+ uint32_t heap_limit; /* As it says */ uint32_t match_limit; /* As it says */ uint32_t match_limit_depth; /* As it says */ uint32_t match_call_count; /* Number of times a new frame is created */@@ -875,10 +880,11 @@ uint16_t name_count; /* Number of names in name table */ uint16_t name_entry_size; /* Size of entry in names table */ PCRE2_SPTR name_table; /* Table of group names */- PCRE2_SPTR start_code; /* For use when recursing */+ PCRE2_SPTR start_code; /* For use in pattern recursion */ PCRE2_SPTR start_subject; /* Start of the subject string */ PCRE2_SPTR check_subject; /* Where UTF-checked from */- PCRE2_SPTR end_subject; /* End of the subject string */+ PCRE2_SPTR end_subject; /* Usable end of the subject string */+ PCRE2_SPTR true_end_subject; /* Actual end of the subject string */ PCRE2_SPTR end_match_ptr; /* Subject position at end match */ PCRE2_SPTR start_used_ptr; /* Earliest consulted character */ PCRE2_SPTR last_used_ptr; /* Latest consulted character */@@ -886,7 +892,7 @@ PCRE2_SPTR nomatch_mark; /* Mark pointer to pass back on failure */ PCRE2_SPTR verb_ecode_ptr; /* For passing back info */ PCRE2_SPTR verb_skip_ptr; /* For passing back a (*SKIP) name */- uint32_t verb_current_recurse; /* Current recurse when (*VERB) happens */+ uint32_t verb_current_recurse; /* Current recursion group when (*VERB) happens */ uint32_t moptions; /* Match options */ uint32_t poptions; /* Pattern options */ uint32_t skip_arg_count; /* For counting SKIP_ARGs */@@ -911,7 +917,7 @@ PCRE2_SPTR last_used_ptr; /* Latest consulted character */ const uint8_t *tables; /* Character tables */ PCRE2_SIZE start_offset; /* The start offset value */- PCRE2_SIZE heap_limit; /* As it says */+ uint32_t heap_limit; /* As it says */ PCRE2_SIZE heap_used; /* As it says */ uint32_t match_limit; /* As it says */ uint32_t match_limit_depth; /* As it says */@@ -926,7 +932,7 @@ pcre2_callout_block *cb; /* Points to a callout block */ void *callout_data; /* To pass back to callouts */ int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */- dfa_recursion_info *recursive; /* Linked list of recursion data */+ dfa_recursion_info *recursive; /* Linked list of pattern recursion data */ } dfa_match_block; #endif /* PCRE2_PCRE2TEST */
src/c/pcre2/src/pcre2_jit_compile.c view
@@ -8,14462 +8,14925 @@ Written by Philip Hazel This module by Zoltan Herczeg Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2021 University of Cambridge--------------------------------------------------------------------------------Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:-- * Redistributions of source code must retain the above copyright notice,- this list of conditions and the following disclaimer.-- * Redistributions in binary form must reproduce the above copyright- notice, this list of conditions and the following disclaimer in the- documentation and/or other materials provided with the distribution.-- * Neither the name of the University of Cambridge nor the names of its- contributors may be used to endorse or promote products derived from- this software without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE-POSSIBILITY OF SUCH DAMAGE.-------------------------------------------------------------------------------*/--#ifdef HAVE_CONFIG_H-#include "config.h"-#endif--#include "pcre2_internal.h"--#ifdef SUPPORT_JIT--/* All-in-one: Since we use the JIT compiler only from here,-we just include it. This way we don't need to touch the build-system files. */--#define SLJIT_CONFIG_AUTO 1-#define SLJIT_CONFIG_STATIC 1-#define SLJIT_VERBOSE 0--#ifdef PCRE2_DEBUG-#define SLJIT_DEBUG 1-#else-#define SLJIT_DEBUG 0-#endif--#define SLJIT_MALLOC(size, allocator_data) pcre2_jit_malloc(size, allocator_data)-#define SLJIT_FREE(ptr, allocator_data) pcre2_jit_free(ptr, allocator_data)--static void * pcre2_jit_malloc(size_t size, void *allocator_data)-{-pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);-return allocator->malloc(size, allocator->memory_data);-}--static void pcre2_jit_free(void *ptr, void *allocator_data)-{-pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);-allocator->free(ptr, allocator->memory_data);-}--#include "sljit/sljitLir.c"--#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED-#error Unsupported architecture-#endif--/* Defines for debugging purposes. */--/* 1 - Use unoptimized capturing brackets.- 2 - Enable capture_last_ptr (includes option 1). */-/* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */--/* 1 - Always have a control head. */-/* #define DEBUG_FORCE_CONTROL_HEAD 1 */--/* Allocate memory for the regex stack on the real machine stack.-Fast, but limited size. */-#define MACHINE_STACK_SIZE 32768--/* Growth rate for stack allocated by the OS. Should be the multiply-of page size. */-#define STACK_GROWTH_RATE 8192--/* Enable to check that the allocation could destroy temporaries. */-#if defined SLJIT_DEBUG && SLJIT_DEBUG-#define DESTROY_REGISTERS 1-#endif--/*-Short summary about the backtracking mechanism empolyed by the jit code generator:--The code generator follows the recursive nature of the PERL compatible regular-expressions. The basic blocks of regular expressions are condition checkers-whose execute different commands depending on the result of the condition check.-The relationship between the operators can be horizontal (concatenation) and-vertical (sub-expression) (See struct backtrack_common for more details).-- 'ab' - 'a' and 'b' regexps are concatenated- 'a+' - 'a' is the sub-expression of the '+' operator--The condition checkers are boolean (true/false) checkers. Machine code is generated-for the checker itself and for the actions depending on the result of the checker.-The 'true' case is called as the matching path (expected path), and the other is called as-the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken-branches on the matching path.-- Greedy star operator (*) :- Matching path: match happens.- Backtrack path: match failed.- Non-greedy star operator (*?) :- Matching path: no need to perform a match.- Backtrack path: match is required.--The following example shows how the code generated for a capturing bracket-with two alternatives. Let A, B, C, D are arbirary regular expressions, and-we have the following regular expression:-- A(B|C)D--The generated code will be the following:-- A matching path- '(' matching path (pushing arguments to the stack)- B matching path- ')' matching path (pushing arguments to the stack)- D matching path- return with successful match-- D backtrack path- ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")- B backtrack path- C expected path- jump to D matching path- C backtrack path- A backtrack path-- Notice, that the order of backtrack code paths are the opposite of the fast- code paths. In this way the topmost value on the stack is always belong- to the current backtrack code path. The backtrack path must check- whether there is a next alternative. If so, it needs to jump back to- the matching path eventually. Otherwise it needs to clear out its own stack- frame and continue the execution on the backtrack code paths.-*/--/*-Saved stack frames:--Atomic blocks and asserts require reloading the values of private data-when the backtrack mechanism performed. Because of OP_RECURSE, the data-are not necessarly known in compile time, thus we need a dynamic restore-mechanism.--The stack frames are stored in a chain list, and have the following format:-([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]--Thus we can restore the private data to a particular point in the stack.-*/--typedef struct jit_arguments {- /* Pointers first. */- struct sljit_stack *stack;- PCRE2_SPTR str;- PCRE2_SPTR begin;- PCRE2_SPTR end;- pcre2_match_data *match_data;- PCRE2_SPTR startchar_ptr;- PCRE2_UCHAR *mark_ptr;- int (*callout)(pcre2_callout_block *, void *);- void *callout_data;- /* Everything else after. */- sljit_uw offset_limit;- sljit_u32 limit_match;- sljit_u32 oveccount;- sljit_u32 options;-} jit_arguments;--#define JIT_NUMBER_OF_COMPILE_MODES 3--typedef struct executable_functions {- void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];- void *read_only_data_heads[JIT_NUMBER_OF_COMPILE_MODES];- sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];- sljit_u32 top_bracket;- sljit_u32 limit_match;-} executable_functions;--typedef struct jump_list {- struct sljit_jump *jump;- struct jump_list *next;-} jump_list;--typedef struct stub_list {- struct sljit_jump *start;- struct sljit_label *quit;- struct stub_list *next;-} stub_list;--enum frame_types {- no_frame = -1,- no_stack = -2-};--enum control_types {- type_mark = 0,- type_then_trap = 1-};--enum early_fail_types {- type_skip = 0,- type_fail = 1,- type_fail_range = 2-};--typedef int (SLJIT_FUNC *jit_function)(jit_arguments *args);--/* The following structure is the key data type for the recursive-code generator. It is allocated by compile_matchingpath, and contains-the arguments for compile_backtrackingpath. Must be the first member-of its descendants. */-typedef struct backtrack_common {- /* Concatenation stack. */- struct backtrack_common *prev;- jump_list *nextbacktracks;- /* Internal stack (for component operators). */- struct backtrack_common *top;- jump_list *topbacktracks;- /* Opcode pointer. */- PCRE2_SPTR cc;-} backtrack_common;--typedef struct assert_backtrack {- backtrack_common common;- jump_list *condfailed;- /* Less than 0 if a frame is not needed. */- int framesize;- /* Points to our private memory word on the stack. */- int private_data_ptr;- /* For iterators. */- struct sljit_label *matchingpath;-} assert_backtrack;--typedef struct bracket_backtrack {- backtrack_common common;- /* Where to coninue if an alternative is successfully matched. */- struct sljit_label *alternative_matchingpath;- /* For rmin and rmax iterators. */- struct sljit_label *recursive_matchingpath;- /* For greedy ? operator. */- struct sljit_label *zero_matchingpath;- /* Contains the branches of a failed condition. */- union {- /* Both for OP_COND, OP_SCOND. */- jump_list *condfailed;- assert_backtrack *assert;- /* For OP_ONCE. Less than 0 if not needed. */- int framesize;- /* For brackets with >3 alternatives. */- struct sljit_put_label *matching_put_label;- } u;- /* Points to our private memory word on the stack. */- int private_data_ptr;-} bracket_backtrack;--typedef struct bracketpos_backtrack {- backtrack_common common;- /* Points to our private memory word on the stack. */- int private_data_ptr;- /* Reverting stack is needed. */- int framesize;- /* Allocated stack size. */- int stacksize;-} bracketpos_backtrack;--typedef struct braminzero_backtrack {- backtrack_common common;- struct sljit_label *matchingpath;-} braminzero_backtrack;--typedef struct char_iterator_backtrack {- backtrack_common common;- /* Next iteration. */- struct sljit_label *matchingpath;- union {- jump_list *backtracks;- struct {- unsigned int othercasebit;- PCRE2_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;- /* Contains the function entry label. */- struct sljit_label *entry_label;- /* Contains the function entry label. */- struct sljit_label *backtrack_label;- /* Collects the entry calls until the function is not created. */- jump_list *entry_calls;- /* Collects the backtrack calls until the function is not created. */- jump_list *backtrack_calls;- /* Points to the starting opcode. */- sljit_sw start;-} recurse_entry;--typedef struct recurse_backtrack {- backtrack_common common;- /* Return to the matching path. */- struct sljit_label *matchingpath;- /* Recursive pattern. */- recurse_entry *entry;- /* Pattern is inlined. */- BOOL inlined_pattern;-} recurse_backtrack;--#define OP_THEN_TRAP OP_TABLE_LENGTH--typedef struct then_trap_backtrack {- backtrack_common common;- /* If then_trap is not NULL, this structure contains the real- then_trap for the backtracking path. */- struct then_trap_backtrack *then_trap;- /* Points to the starting opcode. */- sljit_sw start;- /* Exit point for the then opcodes of this alternative. */- jump_list *quit;- /* Frame size of the current alternative. */- int framesize;-} then_trap_backtrack;--#define MAX_N_CHARS 12-#define MAX_DIFF_CHARS 5--typedef struct fast_forward_char_data {- /* Number of characters in the chars array, 255 for any character. */- sljit_u8 count;- /* Number of last UTF-8 characters in the chars array. */- sljit_u8 last_count;- /* Available characters in the current position. */- PCRE2_UCHAR chars[MAX_DIFF_CHARS];-} fast_forward_char_data;--#define MAX_CLASS_RANGE_SIZE 4-#define MAX_CLASS_CHARS_SIZE 3--typedef struct compiler_common {- /* The sljit ceneric compiler. */- struct sljit_compiler *compiler;- /* Compiled regular expression. */- pcre2_real_code *re;- /* First byte code. */- PCRE2_SPTR start;- /* Maps private data offset to each opcode. */- sljit_s32 *private_data_ptrs;- /* Chain list of read-only data ptrs. */- void *read_only_data_head;- /* Tells whether the capturing bracket is optimized. */- sljit_u8 *optimized_cbracket;- /* Tells whether the starting offset is a target of then. */- sljit_u8 *then_offsets;- /* Current position where a THEN must jump. */- then_trap_backtrack *then_trap;- /* Starting offset of private data for capturing brackets. */- sljit_s32 cbra_ptr;- /* Output vector starting point. Must be divisible by 2. */- sljit_s32 ovector_start;- /* Points to the starting character of the current match. */- sljit_s32 start_ptr;- /* Last known position of the requested byte. */- sljit_s32 req_char_ptr;- /* Head of the last recursion. */- 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. */- sljit_s32 hit_start;- /* Pointer of the match end position. */- sljit_s32 match_end_ptr;- /* Points to the marked string. */- sljit_s32 mark_ptr;- /* Recursive control verb management chain. */- sljit_s32 control_head_ptr;- /* Points to the last matched capture block index. */- sljit_s32 capture_last_ptr;- /* Fast forward skipping byte code pointer. */- PCRE2_SPTR fast_forward_bc_ptr;- /* Locals used by fast fail optimization. */- sljit_s32 early_fail_start_ptr;- sljit_s32 early_fail_end_ptr;- /* Variables used by recursive call generator. */- sljit_s32 recurse_bitset_size;- uint8_t *recurse_bitset;-- /* Flipped and lower case tables. */- const sljit_u8 *fcc;- sljit_sw lcc;- /* Mode can be PCRE2_JIT_COMPLETE and others. */- int mode;- /* TRUE, when empty match is accepted for partial matching. */- BOOL allow_empty_partial;- /* TRUE, when minlength is greater than 0. */- BOOL might_be_empty;- /* \K is found in the pattern. */- BOOL has_set_som;- /* (*SKIP:arg) is found in the pattern. */- BOOL has_skip_arg;- /* (*THEN) is found in the pattern. */- BOOL has_then;- /* (*SKIP) or (*SKIP:arg) is found in lookbehind assertion. */- BOOL has_skip_in_assert_back;- /* Quit is redirected by recurse, negative assertion, or positive assertion in conditional block. */- BOOL local_quit_available;- /* Currently in a positive assertion. */- BOOL in_positive_assertion;- /* Newline control. */- int nltype;- sljit_u32 nlmax;- sljit_u32 nlmin;- int newline;- int bsr_nltype;- sljit_u32 bsr_nlmax;- sljit_u32 bsr_nlmin;- /* Dollar endonly. */- int endonly;- /* Tables. */- sljit_sw ctypes;- /* Named capturing brackets. */- PCRE2_SPTR name_table;- sljit_sw name_count;- sljit_sw name_entry_size;-- /* Labels and jump lists. */- struct sljit_label *partialmatchlabel;- struct sljit_label *quit_label;- struct sljit_label *abort_label;- struct sljit_label *accept_label;- struct sljit_label *ff_newline_shortcut;- stub_list *stubs;- recurse_entry *entries;- recurse_entry *currententry;- jump_list *partialmatch;- jump_list *quit;- jump_list *positive_assertion_quit;- jump_list *abort;- jump_list *failed_match;- jump_list *accept;- jump_list *calllimit;- jump_list *stackalloc;- jump_list *revertframes;- jump_list *wordboundary;- jump_list *anynewline;- jump_list *hspace;- jump_list *vspace;- jump_list *casefulcmp;- jump_list *caselesscmp;- jump_list *reset_match;- BOOL unset_backref;- BOOL alt_circumflex;-#ifdef SUPPORT_UNICODE- BOOL utf;- BOOL invalid_utf;- BOOL ucp;- /* Points to saving area for iref. */- sljit_s32 iref_ptr;- jump_list *getucd;- jump_list *getucdtype;-#if PCRE2_CODE_UNIT_WIDTH == 8- jump_list *utfreadchar;- jump_list *utfreadtype8;- jump_list *utfpeakcharback;-#endif-#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16- jump_list *utfreadchar_invalid;- jump_list *utfreadnewline_invalid;- jump_list *utfmoveback_invalid;- jump_list *utfpeakcharback_invalid;-#endif-#endif /* SUPPORT_UNICODE */-} compiler_common;--/* For byte_sequence_compare. */--typedef struct compare_context {- int length;- int sourcereg;-#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED- int ucharptr;- union {- sljit_s32 asint;- sljit_u16 asushort;-#if PCRE2_CODE_UNIT_WIDTH == 8- sljit_u8 asbyte;- sljit_u8 asuchars[4];-#elif PCRE2_CODE_UNIT_WIDTH == 16- sljit_u16 asuchars[2];-#elif PCRE2_CODE_UNIT_WIDTH == 32- sljit_u32 asuchars[1];-#endif- } c;- union {- sljit_s32 asint;- sljit_u16 asushort;-#if PCRE2_CODE_UNIT_WIDTH == 8- sljit_u8 asbyte;- sljit_u8 asuchars[4];-#elif PCRE2_CODE_UNIT_WIDTH == 16- sljit_u16 asuchars[2];-#elif PCRE2_CODE_UNIT_WIDTH == 32- sljit_u32 asuchars[1];-#endif- } oc;-#endif-} compare_context;--/* Undefine sljit macros. */-#undef CMP--/* Used for accessing the elements of the stack. */-#define STACK(i) ((i) * (int)sizeof(sljit_sw))--#ifdef SLJIT_PREF_SHIFT_REG-#if SLJIT_PREF_SHIFT_REG == SLJIT_R2-/* Nothing. */-#elif SLJIT_PREF_SHIFT_REG == SLJIT_R3-#define SHIFT_REG_IS_R3-#else-#error "Unsupported shift register"-#endif-#endif--#define TMP1 SLJIT_R0-#ifdef SHIFT_REG_IS_R3-#define TMP2 SLJIT_R3-#define TMP3 SLJIT_R2-#else-#define TMP2 SLJIT_R2-#define TMP3 SLJIT_R3-#endif-#define STR_PTR SLJIT_R1-#define STR_END SLJIT_S0-#define STACK_TOP SLJIT_S1-#define STACK_LIMIT SLJIT_S2-#define COUNT_MATCH SLJIT_S3-#define ARGUMENTS SLJIT_S4-#define RETURN_ADDR SLJIT_R4--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)-#define HAS_VIRTUAL_REGISTERS 1-#else-#define HAS_VIRTUAL_REGISTERS 0-#endif--/* Local space layout. */-/* These two locals can be used by the current opcode. */-#define LOCALS0 (0 * sizeof(sljit_sw))-#define LOCALS1 (1 * sizeof(sljit_sw))-/* Two local variables for possessive quantifiers (char1 cannot use them). */-#define POSSESSIVE0 (2 * sizeof(sljit_sw))-#define POSSESSIVE1 (3 * sizeof(sljit_sw))-/* Max limit of recursions. */-#define LIMIT_MATCH (4 * sizeof(sljit_sw))-/* The output vector is stored on the stack, and contains pointers-to characters. The vector data is divided into two groups: the first-group contains the start / end character pointers, and the second is-the start pointers when the end of the capturing group has not yet reached. */-#define OVECTOR_START (common->ovector_start)-#define OVECTOR(i) (OVECTOR_START + (i) * (sljit_sw)sizeof(sljit_sw))-#define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * (sljit_sw)sizeof(sljit_sw))-#define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])--#if PCRE2_CODE_UNIT_WIDTH == 8-#define MOV_UCHAR SLJIT_MOV_U8-#define IN_UCHARS(x) (x)-#elif PCRE2_CODE_UNIT_WIDTH == 16-#define MOV_UCHAR SLJIT_MOV_U16-#define UCHAR_SHIFT (1)-#define IN_UCHARS(x) ((x) * 2)-#elif PCRE2_CODE_UNIT_WIDTH == 32-#define MOV_UCHAR SLJIT_MOV_U32-#define UCHAR_SHIFT (2)-#define IN_UCHARS(x) ((x) * 4)-#else-#error Unsupported compiling mode-#endif--/* Shortcuts. */-#define DEFINE_COMPILER \- struct sljit_compiler *compiler = common->compiler-#define OP1(op, dst, dstw, src, srcw) \- sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))-#define OP2(op, dst, dstw, src1, src1w, src2, src2w) \- sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))-#define OP2U(op, src1, src1w, src2, src2w) \- sljit_emit_op2u(compiler, (op), (src1), (src1w), (src2), (src2w))-#define OP_SRC(op, src, srcw) \- sljit_emit_op_src(compiler, (op), (src), (srcw))-#define LABEL() \- sljit_emit_label(compiler)-#define JUMP(type) \- sljit_emit_jump(compiler, (type))-#define JUMPTO(type, label) \- sljit_set_label(sljit_emit_jump(compiler, (type)), (label))-#define JUMPHERE(jump) \- sljit_set_label((jump), sljit_emit_label(compiler))-#define SET_LABEL(jump, label) \- sljit_set_label((jump), (label))-#define CMP(type, src1, src1w, src2, src2w) \- 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, type) \- sljit_emit_op_flags(compiler, (op), (dst), (dstw), (type))-#define CMOV(type, dst_reg, src, srcw) \- sljit_emit_cmov(compiler, (type), (dst_reg), (src), (srcw))-#define GET_LOCAL_BASE(dst, dstw, offset) \- sljit_get_local_base(compiler, (dst), (dstw), (offset))--#define READ_CHAR_MAX 0x7fffffff--#define INVALID_UTF_CHAR -1-#define UNASSIGNED_UTF_CHAR 888--#if defined SUPPORT_UNICODE-#if PCRE2_CODE_UNIT_WIDTH == 8--#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \- { \- if (ptr[0] <= 0x7f) \- c = *ptr++; \- else if (ptr + 1 < end && ptr[1] >= 0x80 && ptr[1] < 0xc0) \- { \- c = ptr[1] - 0x80; \- \- if (ptr[0] >= 0xc2 && ptr[0] <= 0xdf) \- { \- c |= (ptr[0] - 0xc0) << 6; \- ptr += 2; \- } \- else if (ptr + 2 < end && ptr[2] >= 0x80 && ptr[2] < 0xc0) \- { \- c = c << 6 | (ptr[2] - 0x80); \- \- if (ptr[0] >= 0xe0 && ptr[0] <= 0xef) \- { \- c |= (ptr[0] - 0xe0) << 12; \- ptr += 3; \- \- if (c < 0x800 || (c >= 0xd800 && c < 0xe000)) \- { \- invalid_action; \- } \- } \- else if (ptr + 3 < end && ptr[3] >= 0x80 && ptr[3] < 0xc0) \- { \- c = c << 6 | (ptr[3] - 0x80); \- \- if (ptr[0] >= 0xf0 && ptr[0] <= 0xf4) \- { \- c |= (ptr[0] - 0xf0) << 18; \- ptr += 4; \- \- if (c >= 0x110000 || c < 0x10000) \- { \- invalid_action; \- } \- } \- else \- { \- invalid_action; \- } \- } \- else \- { \- invalid_action; \- } \- } \- else \- { \- invalid_action; \- } \- } \- else \- { \- invalid_action; \- } \- }--#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \- { \- c = ptr[-1]; \- if (c <= 0x7f) \- ptr--; \- else if (ptr - 1 > start && ptr[-1] >= 0x80 && ptr[-1] < 0xc0) \- { \- c -= 0x80; \- \- if (ptr[-2] >= 0xc2 && ptr[-2] <= 0xdf) \- { \- c |= (ptr[-2] - 0xc0) << 6; \- ptr -= 2; \- } \- else if (ptr - 2 > start && ptr[-2] >= 0x80 && ptr[-2] < 0xc0) \- { \- c = c << 6 | (ptr[-2] - 0x80); \- \- if (ptr[-3] >= 0xe0 && ptr[-3] <= 0xef) \- { \- c |= (ptr[-3] - 0xe0) << 12; \- ptr -= 3; \- \- if (c < 0x800 || (c >= 0xd800 && c < 0xe000)) \- { \- invalid_action; \- } \- } \- else if (ptr - 3 > start && ptr[-3] >= 0x80 && ptr[-3] < 0xc0) \- { \- c = c << 6 | (ptr[-3] - 0x80); \- \- if (ptr[-4] >= 0xf0 && ptr[-4] <= 0xf4) \- { \- c |= (ptr[-4] - 0xf0) << 18; \- ptr -= 4; \- \- if (c >= 0x110000 || c < 0x10000) \- { \- invalid_action; \- } \- } \- else \- { \- invalid_action; \- } \- } \- else \- { \- invalid_action; \- } \- } \- else \- { \- invalid_action; \- } \- } \- else \- { \- invalid_action; \- } \- }--#elif PCRE2_CODE_UNIT_WIDTH == 16--#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \- { \- if (ptr[0] < 0xd800 || ptr[0] >= 0xe000) \- c = *ptr++; \- else if (ptr[0] < 0xdc00 && ptr + 1 < end && ptr[1] >= 0xdc00 && ptr[1] < 0xe000) \- { \- c = (((ptr[0] - 0xd800) << 10) | (ptr[1] - 0xdc00)) + 0x10000; \- ptr += 2; \- } \- else \- { \- invalid_action; \- } \- }--#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \- { \- c = ptr[-1]; \- if (c < 0xd800 || c >= 0xe000) \- ptr--; \- else if (c >= 0xdc00 && ptr - 1 > start && ptr[-2] >= 0xd800 && ptr[-2] < 0xdc00) \- { \- c = (((ptr[-2] - 0xd800) << 10) | (c - 0xdc00)) + 0x10000; \- ptr -= 2; \- } \- else \- { \- invalid_action; \- } \- }---#elif PCRE2_CODE_UNIT_WIDTH == 32--#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \- { \- if (ptr[0] < 0xd800 || (ptr[0] >= 0xe000 && ptr[0] < 0x110000)) \- c = *ptr++; \- else \- { \- invalid_action; \- } \- }--#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \- { \- c = ptr[-1]; \- if (ptr[-1] < 0xd800 || (ptr[-1] >= 0xe000 && ptr[-1] < 0x110000)) \- ptr--; \- else \- { \- invalid_action; \- } \- }--#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */-#endif /* SUPPORT_UNICODE */--static PCRE2_SPTR bracketend(PCRE2_SPTR cc)-{-SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND));-do cc += GET(cc, 1); while (*cc == OP_ALT);-SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);-cc += 1 + LINK_SIZE;-return cc;-}--static int no_alternatives(PCRE2_SPTR cc)-{-int count = 0;-SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND));-do- {- cc += GET(cc, 1);- count++;- }-while (*cc == OP_ALT);-SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);-return count;-}--/* Functions whose might need modification for all new supported opcodes:- next_opcode- check_opcode_types- set_private_data_ptrs- get_framesize- init_frame- get_recurse_data_length- copy_recurse_data- compile_matchingpath- compile_backtrackingpath-*/--static PCRE2_SPTR next_opcode(compiler_common *common, PCRE2_SPTR cc)-{-SLJIT_UNUSED_ARG(common);-switch(*cc)- {- case OP_SOD:- case OP_SOM:- case OP_SET_SOM:- case OP_NOT_WORD_BOUNDARY:- case OP_WORD_BOUNDARY:- 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_NOTPROP:- case OP_PROP:- case OP_ANYNL:- case OP_NOT_HSPACE:- case OP_HSPACE:- 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_CRSTAR:- case OP_CRMINSTAR:- case OP_CRPLUS:- case OP_CRMINPLUS:- case OP_CRQUERY:- case OP_CRMINQUERY:- case OP_CRRANGE:- case OP_CRMINRANGE:- case OP_CRPOSSTAR:- case OP_CRPOSPLUS:- case OP_CRPOSQUERY:- case OP_CRPOSRANGE:- case OP_CLASS:- case OP_NCLASS:- case OP_REF:- case OP_REFI:- case OP_DNREF:- case OP_DNREFI:- case OP_RECURSE:- case OP_CALLOUT:- case OP_ALT:- case OP_KET:- case OP_KETRMAX:- case OP_KETRMIN:- case OP_KETRPOS:- case OP_REVERSE:- case OP_ASSERT:- case OP_ASSERT_NOT:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT:- case OP_ASSERT_NA:- case OP_ASSERTBACK_NA:- case OP_ONCE:- case OP_SCRIPT_RUN:- case OP_BRA:- case OP_BRAPOS:- case OP_CBRA:- case OP_CBRAPOS:- case OP_COND:- case OP_SBRA:- case OP_SBRAPOS:- case OP_SCBRA:- case OP_SCBRAPOS:- case OP_SCOND:- case OP_CREF:- case OP_DNCREF:- case OP_RREF:- case OP_DNRREF:- case OP_FALSE:- case OP_TRUE:- case OP_BRAZERO:- case OP_BRAMINZERO:- case OP_BRAPOSZERO:- case OP_PRUNE:- case OP_SKIP:- case OP_THEN:- case OP_COMMIT:- case OP_FAIL:- case OP_ACCEPT:- case OP_ASSERT_ACCEPT:- case OP_CLOSE:- case OP_SKIPZERO:- return cc + PRIV(OP_lengths)[*cc];-- case OP_CHAR:- case OP_CHARI:- case OP_NOT:- case OP_NOTI:- case OP_STAR:- case OP_MINSTAR:- case OP_PLUS:- case OP_MINPLUS:- case OP_QUERY:- case OP_MINQUERY:- case OP_UPTO:- case OP_MINUPTO:- case OP_EXACT:- case OP_POSSTAR:- case OP_POSPLUS:- case OP_POSQUERY:- case OP_POSUPTO:- case OP_STARI:- case OP_MINSTARI:- case OP_PLUSI:- case OP_MINPLUSI:- case OP_QUERYI:- case OP_MINQUERYI:- case OP_UPTOI:- case OP_MINUPTOI:- case OP_EXACTI:- case OP_POSSTARI:- case OP_POSPLUSI:- case OP_POSQUERYI:- case OP_POSUPTOI:- case OP_NOTSTAR:- case OP_NOTMINSTAR:- case OP_NOTPLUS:- case OP_NOTMINPLUS:- case OP_NOTQUERY:- case OP_NOTMINQUERY:- case OP_NOTUPTO:- case OP_NOTMINUPTO:- case OP_NOTEXACT:- case OP_NOTPOSSTAR:- case OP_NOTPOSPLUS:- case OP_NOTPOSQUERY:- case OP_NOTPOSUPTO:- case OP_NOTSTARI:- case OP_NOTMINSTARI:- case OP_NOTPLUSI:- case OP_NOTMINPLUSI:- case OP_NOTQUERYI:- case OP_NOTMINQUERYI:- case OP_NOTUPTOI:- case OP_NOTMINUPTOI:- case OP_NOTEXACTI:- case OP_NOTPOSSTARI:- case OP_NOTPOSPLUSI:- case OP_NOTPOSQUERYI:- case OP_NOTPOSUPTOI:- cc += PRIV(OP_lengths)[*cc];-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- return cc;-- /* Special cases. */- case OP_TYPESTAR:- case OP_TYPEMINSTAR:- case OP_TYPEPLUS:- case OP_TYPEMINPLUS:- case OP_TYPEQUERY:- case OP_TYPEMINQUERY:- case OP_TYPEUPTO:- case OP_TYPEMINUPTO:- case OP_TYPEEXACT:- case OP_TYPEPOSSTAR:- case OP_TYPEPOSPLUS:- case OP_TYPEPOSQUERY:- case OP_TYPEPOSUPTO:- return cc + PRIV(OP_lengths)[*cc] - 1;-- case OP_ANYBYTE:-#ifdef SUPPORT_UNICODE- if (common->utf) return NULL;-#endif- return cc + 1;-- case OP_CALLOUT_STR:- return cc + GET(cc, 1 + 2*LINK_SIZE);--#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8- case OP_XCLASS:- return cc + GET(cc, 1);-#endif-- case OP_MARK:- case OP_COMMIT_ARG:- case OP_PRUNE_ARG:- case OP_SKIP_ARG:- case OP_THEN_ARG:- return cc + 1 + 2 + cc[1];-- default:- SLJIT_UNREACHABLE();- return NULL;- }-}--static BOOL check_opcode_types(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend)-{-int count;-PCRE2_SPTR slot;-PCRE2_SPTR assert_back_end = cc - 1;-PCRE2_SPTR assert_na_end = cc - 1;--/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */-while (cc < ccend)- {- switch(*cc)- {- case OP_SET_SOM:- common->has_set_som = TRUE;- common->might_be_empty = TRUE;- cc += 1;- break;-- case OP_REFI:-#ifdef SUPPORT_UNICODE- if (common->iref_ptr == 0)- {- common->iref_ptr = common->ovector_start;- common->ovector_start += 3 * sizeof(sljit_sw);- }-#endif /* SUPPORT_UNICODE */- /* Fall through. */- case OP_REF:- common->optimized_cbracket[GET2(cc, 1)] = 0;- cc += 1 + IMM2_SIZE;- break;-- case OP_ASSERT_NA:- case OP_ASSERTBACK_NA:- slot = bracketend(cc);- if (slot > assert_na_end)- assert_na_end = slot;- cc += 1 + LINK_SIZE;- break;-- case OP_CBRAPOS:- case OP_SCBRAPOS:- common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;- cc += 1 + LINK_SIZE + IMM2_SIZE;- break;-- case OP_COND:- case OP_SCOND:- /* Only AUTO_CALLOUT can insert this opcode. We do- not intend to support this case. */- if (cc[1 + LINK_SIZE] == OP_CALLOUT || cc[1 + LINK_SIZE] == OP_CALLOUT_STR)- return FALSE;- cc += 1 + LINK_SIZE;- break;-- case OP_CREF:- common->optimized_cbracket[GET2(cc, 1)] = 0;- cc += 1 + IMM2_SIZE;- break;-- case OP_DNREF:- case OP_DNREFI:- case OP_DNCREF:- count = GET2(cc, 1 + IMM2_SIZE);- slot = common->name_table + GET2(cc, 1) * common->name_entry_size;- while (count-- > 0)- {- common->optimized_cbracket[GET2(slot, 0)] = 0;- slot += common->name_entry_size;- }- cc += 1 + 2 * IMM2_SIZE;- break;-- case OP_RECURSE:- /* Set its value only once. */- if (common->recursive_head_ptr == 0)- {- common->recursive_head_ptr = common->ovector_start;- common->ovector_start += sizeof(sljit_sw);- }- cc += 1 + LINK_SIZE;- break;-- case OP_CALLOUT:- case OP_CALLOUT_STR:- if (common->capture_last_ptr == 0)- {- common->capture_last_ptr = common->ovector_start;- common->ovector_start += sizeof(sljit_sw);- }- cc += (*cc == OP_CALLOUT) ? PRIV(OP_lengths)[OP_CALLOUT] : GET(cc, 1 + 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_COMMIT_ARG:- case OP_PRUNE_ARG:- if (cc < assert_na_end)- return FALSE;- /* Fall through */- case OP_MARK:- if (common->mark_ptr == 0)- {- common->mark_ptr = common->ovector_start;- common->ovector_start += sizeof(sljit_sw);- }- cc += 1 + 2 + cc[1];- break;-- case OP_THEN:- common->has_then = TRUE;- common->control_head_ptr = 1;- cc += 1;- break;-- case OP_SKIP:- if (cc < assert_back_end)- common->has_skip_in_assert_back = TRUE;- if (cc < assert_na_end)- return FALSE;- 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;- if (cc < assert_na_end)- return FALSE;- cc += 1 + 2 + cc[1];- break;-- case OP_PRUNE:- case OP_COMMIT:- case OP_ASSERT_ACCEPT:- if (cc < assert_na_end)- return FALSE;- cc++;- break;-- default:- cc = next_opcode(common, cc);- if (cc == NULL)- return FALSE;- break;- }- }-return TRUE;-}--#define EARLY_FAIL_ENHANCE_MAX (1 + 3)--/*-start:- 0 - skip / early fail allowed- 1 - only early fail with range allowed- >1 - (start - 1) early fail is processed--return: current number of iterators enhanced with fast fail-*/-static int detect_early_fail(compiler_common *common, PCRE2_SPTR cc, int *private_data_start,- sljit_s32 depth, int start, BOOL fast_forward_allowed)-{-PCRE2_SPTR begin = cc;-PCRE2_SPTR next_alt;-PCRE2_SPTR end;-PCRE2_SPTR accelerated_start;-BOOL prev_fast_forward_allowed;-int result = 0;-int count;--SLJIT_ASSERT(*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA);-SLJIT_ASSERT(*cc != OP_CBRA || common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] != 0);-SLJIT_ASSERT(start < EARLY_FAIL_ENHANCE_MAX);--next_alt = cc + GET(cc, 1);-if (*next_alt == OP_ALT)- fast_forward_allowed = FALSE;--do- {- count = start;- cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0);-- while (TRUE)- {- accelerated_start = NULL;-- 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;-- 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_NOT_HSPACE:- case OP_HSPACE:- case OP_NOT_VSPACE:- case OP_VSPACE:- fast_forward_allowed = FALSE;- cc++;- continue;-- case OP_ANYNL:- case OP_EXTUNI:- fast_forward_allowed = FALSE;- if (count == 0)- count = 1;- cc++;- continue;-- case OP_NOTPROP:- case OP_PROP:- fast_forward_allowed = FALSE;- cc += 1 + 2;- continue;-- case OP_CHAR:- case OP_CHARI:- case OP_NOT:- case OP_NOTI:- fast_forward_allowed = FALSE;- cc += 2;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- continue;-- case OP_TYPESTAR:- case OP_TYPEMINSTAR:- case OP_TYPEPLUS:- case OP_TYPEMINPLUS:- case OP_TYPEPOSSTAR:- case OP_TYPEPOSPLUS:- /* The type or prop opcode is skipped in the next iteration. */- cc += 1;-- if (cc[0] != OP_ANYNL && cc[0] != OP_EXTUNI)- {- accelerated_start = cc - 1;- break;- }-- if (count == 0)- count = 1;- fast_forward_allowed = FALSE;- continue;-- case OP_TYPEUPTO:- case OP_TYPEMINUPTO:- case OP_TYPEEXACT:- case OP_TYPEPOSUPTO:- cc += IMM2_SIZE;- /* Fall through */-- case OP_TYPEQUERY:- case OP_TYPEMINQUERY:- case OP_TYPEPOSQUERY:- /* The type or prop opcode is skipped in the next iteration. */- fast_forward_allowed = FALSE;- if (count == 0)- count = 1;- cc += 1;- continue;-- 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:- accelerated_start = cc;- cc += 2;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- break;-- case OP_UPTO:- case OP_MINUPTO:- case OP_EXACT:- case OP_POSUPTO:- case OP_UPTOI:- case OP_MINUPTOI:- case OP_EXACTI:- case OP_POSUPTOI:- case OP_NOTUPTO:- case OP_NOTMINUPTO:- case OP_NOTEXACT:- case OP_NOTPOSUPTO:- case OP_NOTUPTOI:- case OP_NOTMINUPTOI:- case OP_NOTEXACTI:- case OP_NOTPOSUPTOI:- cc += IMM2_SIZE;- /* Fall through */-- case OP_QUERY:- case OP_MINQUERY:- case OP_POSQUERY:- case OP_QUERYI:- case OP_MINQUERYI:- case OP_POSQUERYI:- case OP_NOTQUERY:- case OP_NOTMINQUERY:- case OP_NOTPOSQUERY:- case OP_NOTQUERYI:- case OP_NOTMINQUERYI:- case OP_NOTPOSQUERYI:- fast_forward_allowed = FALSE;- if (count == 0)- count = 1;- cc += 2;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- continue;-- case OP_CLASS:- case OP_NCLASS:-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8- case OP_XCLASS:- accelerated_start = cc;- cc += ((*cc == OP_XCLASS) ? GET(cc, 1) : (unsigned int)(1 + (32 / sizeof(PCRE2_UCHAR))));-#else- accelerated_start = cc;- cc += (1 + (32 / sizeof(PCRE2_UCHAR)));-#endif-- switch (*cc)- {- case OP_CRSTAR:- case OP_CRMINSTAR:- case OP_CRPLUS:- case OP_CRMINPLUS:- case OP_CRPOSSTAR:- case OP_CRPOSPLUS:- cc++;- break;-- case OP_CRRANGE:- case OP_CRMINRANGE:- case OP_CRPOSRANGE:- cc += 2 * IMM2_SIZE;- /* Fall through */- case OP_CRQUERY:- case OP_CRMINQUERY:- case OP_CRPOSQUERY:- cc++;- if (count == 0)- count = 1;- /* Fall through */- default:- accelerated_start = NULL;- fast_forward_allowed = FALSE;- continue;- }- break;-- case OP_ONCE:- case OP_BRA:- case OP_CBRA:- end = cc + GET(cc, 1);-- prev_fast_forward_allowed = fast_forward_allowed;- fast_forward_allowed = FALSE;- if (depth >= 4)- break;-- end = bracketend(cc) - (1 + LINK_SIZE);- if (*end != OP_KET || (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0))- break;-- count = detect_early_fail(common, cc, private_data_start, depth + 1, count, prev_fast_forward_allowed);-- if (PRIVATE_DATA(cc) != 0)- common->private_data_ptrs[begin - common->start] = 1;-- if (count < EARLY_FAIL_ENHANCE_MAX)- {- cc = end + (1 + LINK_SIZE);- continue;- }- break;-- case OP_KET:- SLJIT_ASSERT(PRIVATE_DATA(cc) == 0);- if (cc >= next_alt)- break;- cc += 1 + LINK_SIZE;- continue;- }-- if (accelerated_start != NULL)- {- if (count == 0)- {- count++;-- if (fast_forward_allowed)- {- common->fast_forward_bc_ptr = accelerated_start;- common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_skip;- *private_data_start += sizeof(sljit_sw);- }- else- {- common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_fail;-- if (common->early_fail_start_ptr == 0)- common->early_fail_start_ptr = *private_data_start;-- *private_data_start += sizeof(sljit_sw);- common->early_fail_end_ptr = *private_data_start;-- if (*private_data_start > SLJIT_MAX_LOCAL_SIZE)- return EARLY_FAIL_ENHANCE_MAX;- }- }- else- {- common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_fail_range;-- if (common->early_fail_start_ptr == 0)- common->early_fail_start_ptr = *private_data_start;-- *private_data_start += 2 * sizeof(sljit_sw);- common->early_fail_end_ptr = *private_data_start;-- if (*private_data_start > SLJIT_MAX_LOCAL_SIZE)- return EARLY_FAIL_ENHANCE_MAX;- }-- /* Cannot be part of a repeat. */- common->private_data_ptrs[begin - common->start] = 1;- count++;-- if (count < EARLY_FAIL_ENHANCE_MAX)- continue;- }-- break;- }-- if (*cc != OP_ALT && *cc != OP_KET)- result = EARLY_FAIL_ENHANCE_MAX;- else if (result < count)- result = count;-- cc = next_alt;- next_alt = cc + GET(cc, 1);- }-while (*cc == OP_ALT);--return result;-}--static int get_class_iterator_size(PCRE2_SPTR cc)-{-sljit_u32 min;-sljit_u32 max;-switch(*cc)- {- case OP_CRSTAR:- case OP_CRPLUS:- return 2;-- case OP_CRMINSTAR:- case OP_CRMINPLUS:- case OP_CRQUERY:- case OP_CRMINQUERY:- return 1;-- case OP_CRRANGE:- case OP_CRMINRANGE:- 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;- }-}--static BOOL detect_repeat(compiler_common *common, PCRE2_SPTR begin)-{-PCRE2_SPTR end = bracketend(begin);-PCRE2_SPTR next;-PCRE2_SPTR next_end;-PCRE2_SPTR max_end;-PCRE2_UCHAR type;-sljit_sw length = end - begin;-sljit_s32 min, max, i;--/* Detect fixed iterations first. */-if (end[-(1 + LINK_SIZE)] != OP_KET || PRIVATE_DATA(begin) != 0)- return FALSE;--/* /(?:AB){4,6}/ is currently converted to /(?:AB){3}(?AB){1,3}/- * Skip the check of the second part. */-if (PRIVATE_DATA(end - LINK_SIZE) != 0)- return TRUE;--next = end;-min = 1;-while (1)- {- if (*next != *begin)- break;- next_end = bracketend(next);- if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0)- break;- next = next_end;- min++;- }--if (min == 2)- return FALSE;--max = 0;-max_end = next;-if (*next == OP_BRAZERO || *next == OP_BRAMINZERO)- {- type = *next;- while (1)- {- if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin)- break;- next_end = bracketend(next + 2 + LINK_SIZE);- if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0)- break;- next = next_end;- max++;- }-- if (next[0] == type && next[1] == *begin && max >= 1)- {- next_end = bracketend(next + 1);- if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0)- {- for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE)- if (*next_end != OP_KET)- break;-- if (i == max)- {- common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end;- common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO;- /* +2 the original and the last. */- common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2;- if (min == 1)- return TRUE;- min--;- max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE);- }- }- }- }--if (min >= 3)- {- common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end;- common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT;- common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min;- return TRUE;- }--return FALSE;-}--#define CASE_ITERATOR_PRIVATE_DATA_1 \- case OP_MINSTAR: \- case OP_MINPLUS: \- case OP_QUERY: \- case OP_MINQUERY: \- case OP_MINSTARI: \- case OP_MINPLUSI: \- case OP_QUERYI: \- case OP_MINQUERYI: \- case OP_NOTMINSTAR: \- case OP_NOTMINPLUS: \- case OP_NOTQUERY: \- case OP_NOTMINQUERY: \- case OP_NOTMINSTARI: \- case OP_NOTMINPLUSI: \- case OP_NOTQUERYI: \- case OP_NOTMINQUERYI:--#define CASE_ITERATOR_PRIVATE_DATA_2A \- case OP_STAR: \- case OP_PLUS: \- case OP_STARI: \- case OP_PLUSI: \- case OP_NOTSTAR: \- case OP_NOTPLUS: \- case OP_NOTSTARI: \- case OP_NOTPLUSI:--#define CASE_ITERATOR_PRIVATE_DATA_2B \- case OP_UPTO: \- case OP_MINUPTO: \- case OP_UPTOI: \- case OP_MINUPTOI: \- case OP_NOTUPTO: \- case OP_NOTMINUPTO: \- case OP_NOTUPTOI: \- case OP_NOTMINUPTOI:--#define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \- case OP_TYPEMINSTAR: \- case OP_TYPEMINPLUS: \- case OP_TYPEQUERY: \- case OP_TYPEMINQUERY:--#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \- case OP_TYPESTAR: \- case OP_TYPEPLUS:--#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \- case OP_TYPEUPTO: \- case OP_TYPEMINUPTO:--static void set_private_data_ptrs(compiler_common *common, int *private_data_start, PCRE2_SPTR ccend)-{-PCRE2_SPTR cc = common->start;-PCRE2_SPTR alternative;-PCRE2_SPTR end = NULL;-int private_data_ptr = *private_data_start;-int space, size, bracketlen;-BOOL repeat_check = TRUE;--while (cc < ccend)- {- space = 0;- size = 0;- bracketlen = 0;- if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE)- break;-- /* When the bracket is prefixed by a zero iteration, skip the repeat check (at this point). */- if (repeat_check && (*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND))- {- if (detect_repeat(common, cc))- {- /* These brackets are converted to repeats, so no global- based single character repeat is allowed. */- if (cc >= end)- end = bracketend(cc);- }- }- repeat_check = TRUE;-- switch(*cc)- {- case OP_KET:- if (common->private_data_ptrs[cc + 1 - common->start] != 0)- {- common->private_data_ptrs[cc - common->start] = private_data_ptr;- private_data_ptr += sizeof(sljit_sw);- cc += common->private_data_ptrs[cc + 1 - common->start];- }- cc += 1 + LINK_SIZE;- break;-- case OP_ASSERT:- case OP_ASSERT_NOT:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT:- case OP_ASSERT_NA:- case OP_ASSERTBACK_NA:- case OP_ONCE:- case OP_SCRIPT_RUN:- case OP_BRAPOS:- case OP_SBRA:- case OP_SBRAPOS:- case OP_SCOND:- common->private_data_ptrs[cc - common->start] = private_data_ptr;- private_data_ptr += sizeof(sljit_sw);- bracketlen = 1 + LINK_SIZE;- break;-- case OP_CBRAPOS:- case OP_SCBRAPOS:- common->private_data_ptrs[cc - common->start] = private_data_ptr;- private_data_ptr += sizeof(sljit_sw);- bracketlen = 1 + LINK_SIZE + IMM2_SIZE;- break;-- case OP_COND:- /* Might be a hidden SCOND. */- common->private_data_ptrs[cc - common->start] = 0;- alternative = cc + GET(cc, 1);- if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)- {- common->private_data_ptrs[cc - common->start] = private_data_ptr;- private_data_ptr += sizeof(sljit_sw);- }- bracketlen = 1 + LINK_SIZE;- break;-- case OP_BRA:- bracketlen = 1 + LINK_SIZE;- break;-- case OP_CBRA:- case OP_SCBRA:- bracketlen = 1 + LINK_SIZE + IMM2_SIZE;- break;-- case OP_BRAZERO:- case OP_BRAMINZERO:- case OP_BRAPOSZERO:- size = 1;- repeat_check = FALSE;- break;-- CASE_ITERATOR_PRIVATE_DATA_1- size = -2;- space = 1;- break;-- CASE_ITERATOR_PRIVATE_DATA_2A- size = -2;- space = 2;- break;-- CASE_ITERATOR_PRIVATE_DATA_2B- size = -(2 + IMM2_SIZE);- space = 2;- break;-- CASE_ITERATOR_TYPE_PRIVATE_DATA_1- size = 1;- space = 1;- break;-- CASE_ITERATOR_TYPE_PRIVATE_DATA_2A- size = 1;- if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI)- space = 2;- break;-- case OP_TYPEUPTO:- size = 1 + IMM2_SIZE;- if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI)- space = 2;- break;-- case OP_TYPEMINUPTO:- size = 1 + IMM2_SIZE;- space = 2;- break;-- case OP_CLASS:- case OP_NCLASS:- size = 1 + 32 / sizeof(PCRE2_UCHAR);- space = get_class_iterator_size(cc + size);- break;--#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8- case OP_XCLASS:- size = GET(cc, 1);- space = get_class_iterator_size(cc + size);- break;-#endif-- default:- cc = next_opcode(common, cc);- SLJIT_ASSERT(cc != NULL);- break;- }-- /* Character iterators, which are not inside a repeated bracket,- gets a private slot instead of allocating it on the stack. */- if (space > 0 && cc >= end)- {- common->private_data_ptrs[cc - common->start] = private_data_ptr;- private_data_ptr += sizeof(sljit_sw) * space;- }-- if (size != 0)- {- if (size < 0)- {- cc += -size;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- }- else- cc += size;- }-- if (bracketlen > 0)- {- if (cc >= end)- {- end = bracketend(cc);- if (end[-1 - LINK_SIZE] == OP_KET)- end = NULL;- }- cc += bracketlen;- }- }-*private_data_start = private_data_ptr;-}--/* Returns with a frame_types (always < 0) if no need for frame. */-static int get_framesize(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, BOOL recursive, BOOL *needs_control_head)-{-int length = 0;-int possessive = 0;-BOOL stack_restore = FALSE;-BOOL setsom_found = recursive;-BOOL setmark_found = recursive;-/* The last capture is a local variable even for recursions. */-BOOL capture_last_found = FALSE;--#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD-SLJIT_ASSERT(common->control_head_ptr != 0);-*needs_control_head = TRUE;-#else-*needs_control_head = FALSE;-#endif--if (ccend == NULL)- {- ccend = bracketend(cc) - (1 + LINK_SIZE);- if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))- {- possessive = length = (common->capture_last_ptr != 0) ? 5 : 3;- /* This is correct regardless of common->capture_last_ptr. */- capture_last_found = TRUE;- }- cc = next_opcode(common, cc);- }--SLJIT_ASSERT(cc != NULL);-while (cc < ccend)- switch(*cc)- {- case OP_SET_SOM:- SLJIT_ASSERT(common->has_set_som);- stack_restore = TRUE;- if (!setsom_found)- {- length += 2;- setsom_found = TRUE;- }- cc += 1;- break;-- case OP_MARK:- case OP_COMMIT_ARG:- case OP_PRUNE_ARG:- case OP_THEN_ARG:- SLJIT_ASSERT(common->mark_ptr != 0);- stack_restore = TRUE;- if (!setmark_found)- {- length += 2;- setmark_found = TRUE;- }- if (common->control_head_ptr != 0)- *needs_control_head = TRUE;- cc += 1 + 2 + cc[1];- break;-- case OP_RECURSE:- stack_restore = TRUE;- if (common->has_set_som && !setsom_found)- {- length += 2;- setsom_found = TRUE;- }- if (common->mark_ptr != 0 && !setmark_found)- {- length += 2;- setmark_found = TRUE;- }- if (common->capture_last_ptr != 0 && !capture_last_found)- {- length += 2;- capture_last_found = TRUE;- }- cc += 1 + LINK_SIZE;- break;-- case OP_CBRA:- case OP_CBRAPOS:- case OP_SCBRA:- case OP_SCBRAPOS:- stack_restore = TRUE;- if (common->capture_last_ptr != 0 && !capture_last_found)- {- length += 2;- capture_last_found = TRUE;- }- length += 3;- cc += 1 + LINK_SIZE + IMM2_SIZE;- break;-- case OP_THEN:- stack_restore = TRUE;- if (common->control_head_ptr != 0)- *needs_control_head = TRUE;- cc ++;- break;-- default:- stack_restore = TRUE;- /* Fall through. */-- case OP_NOT_WORD_BOUNDARY:- case OP_WORD_BOUNDARY:- 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_NOTPROP:- case OP_PROP:- case OP_ANYNL:- case OP_NOT_HSPACE:- case OP_HSPACE:- 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_CHAR:- case OP_CHARI:- case OP_NOT:- case OP_NOTI:-- case OP_EXACT:- case OP_POSSTAR:- case OP_POSPLUS:- case OP_POSQUERY:- case OP_POSUPTO:-- case OP_EXACTI:- case OP_POSSTARI:- case OP_POSPLUSI:- case OP_POSQUERYI:- case OP_POSUPTOI:-- case OP_NOTEXACT:- case OP_NOTPOSSTAR:- case OP_NOTPOSPLUS:- case OP_NOTPOSQUERY:- case OP_NOTPOSUPTO:-- case OP_NOTEXACTI:- case OP_NOTPOSSTARI:- case OP_NOTPOSPLUSI:- case OP_NOTPOSQUERYI:- case OP_NOTPOSUPTOI:-- case OP_TYPEEXACT:- case OP_TYPEPOSSTAR:- case OP_TYPEPOSPLUS:- case OP_TYPEPOSQUERY:- case OP_TYPEPOSUPTO:-- case OP_CLASS:- case OP_NCLASS:- case OP_XCLASS:-- case OP_CALLOUT:- case OP_CALLOUT_STR:-- cc = next_opcode(common, cc);- SLJIT_ASSERT(cc != NULL);- break;- }--/* Possessive quantifiers can use a special case. */-if (SLJIT_UNLIKELY(possessive == length))- return stack_restore ? no_frame : no_stack;--if (length > 0)- return length + 1;-return stack_restore ? no_frame : no_stack;-}--static void init_frame(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, int stackpos, int stacktop)-{-DEFINE_COMPILER;-BOOL setsom_found = FALSE;-BOOL setmark_found = FALSE;-/* The last capture is a local variable even for recursions. */-BOOL capture_last_found = FALSE;-int offset;--/* >= 1 + shortest item size (2) */-SLJIT_UNUSED_ARG(stacktop);-SLJIT_ASSERT(stackpos >= stacktop + 2);--stackpos = STACK(stackpos);-if (ccend == NULL)- {- ccend = bracketend(cc) - (1 + LINK_SIZE);- if (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)- cc = next_opcode(common, cc);- }--SLJIT_ASSERT(cc != NULL);-while (cc < ccend)- switch(*cc)- {- case OP_SET_SOM:- SLJIT_ASSERT(common->has_set_som);- if (!setsom_found)- {- 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);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);- stackpos -= (int)sizeof(sljit_sw);- setsom_found = TRUE;- }- cc += 1;- break;-- case OP_MARK:- case OP_COMMIT_ARG:- case OP_PRUNE_ARG:- case OP_THEN_ARG:- SLJIT_ASSERT(common->mark_ptr != 0);- if (!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);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);- stackpos -= (int)sizeof(sljit_sw);- setmark_found = TRUE;- }- cc += 1 + 2 + cc[1];- break;-- case OP_RECURSE:- if (common->has_set_som && !setsom_found)- {- 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);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);- 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);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);- 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);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);- stackpos -= (int)sizeof(sljit_sw);- capture_last_found = TRUE;- }- cc += 1 + LINK_SIZE;- break;-- case OP_CBRA:- case OP_CBRAPOS:- case OP_SCBRA:- case OP_SCBRAPOS:- 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);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);- 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);- 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);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);- stackpos -= (int)sizeof(sljit_sw);-- cc += 1 + LINK_SIZE + IMM2_SIZE;- break;-- default:- cc = next_opcode(common, cc);- SLJIT_ASSERT(cc != NULL);- break;- }--OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, 0);-SLJIT_ASSERT(stackpos == STACK(stacktop));-}--#define RECURSE_TMP_REG_COUNT 3--typedef struct delayed_mem_copy_status {- struct sljit_compiler *compiler;- int store_bases[RECURSE_TMP_REG_COUNT];- int store_offsets[RECURSE_TMP_REG_COUNT];- int tmp_regs[RECURSE_TMP_REG_COUNT];- int saved_tmp_regs[RECURSE_TMP_REG_COUNT];- int next_tmp_reg;-} delayed_mem_copy_status;--static void delayed_mem_copy_init(delayed_mem_copy_status *status, compiler_common *common)-{-int i;--for (i = 0; i < RECURSE_TMP_REG_COUNT; i++)- {- SLJIT_ASSERT(status->tmp_regs[i] >= 0);- SLJIT_ASSERT(sljit_get_register_index(status->saved_tmp_regs[i]) < 0 || status->tmp_regs[i] == status->saved_tmp_regs[i]);-- status->store_bases[i] = -1;- }-status->next_tmp_reg = 0;-status->compiler = common->compiler;-}--static void delayed_mem_copy_move(delayed_mem_copy_status *status, int load_base, sljit_sw load_offset,- int store_base, sljit_sw store_offset)-{-struct sljit_compiler *compiler = status->compiler;-int next_tmp_reg = status->next_tmp_reg;-int tmp_reg = status->tmp_regs[next_tmp_reg];--SLJIT_ASSERT(load_base > 0 && store_base > 0);--if (status->store_bases[next_tmp_reg] == -1)- {- /* Preserve virtual registers. */- if (sljit_get_register_index(status->saved_tmp_regs[next_tmp_reg]) < 0)- OP1(SLJIT_MOV, status->saved_tmp_regs[next_tmp_reg], 0, tmp_reg, 0);- }-else- OP1(SLJIT_MOV, SLJIT_MEM1(status->store_bases[next_tmp_reg]), status->store_offsets[next_tmp_reg], tmp_reg, 0);--OP1(SLJIT_MOV, tmp_reg, 0, SLJIT_MEM1(load_base), load_offset);-status->store_bases[next_tmp_reg] = store_base;-status->store_offsets[next_tmp_reg] = store_offset;--status->next_tmp_reg = (next_tmp_reg + 1) % RECURSE_TMP_REG_COUNT;-}--static void delayed_mem_copy_finish(delayed_mem_copy_status *status)-{-struct sljit_compiler *compiler = status->compiler;-int next_tmp_reg = status->next_tmp_reg;-int tmp_reg, saved_tmp_reg, i;--for (i = 0; i < RECURSE_TMP_REG_COUNT; i++)- {- if (status->store_bases[next_tmp_reg] != -1)- {- tmp_reg = status->tmp_regs[next_tmp_reg];- saved_tmp_reg = status->saved_tmp_regs[next_tmp_reg];-- OP1(SLJIT_MOV, SLJIT_MEM1(status->store_bases[next_tmp_reg]), status->store_offsets[next_tmp_reg], tmp_reg, 0);-- /* Restore virtual registers. */- if (sljit_get_register_index(saved_tmp_reg) < 0)- OP1(SLJIT_MOV, tmp_reg, 0, saved_tmp_reg, 0);- }-- next_tmp_reg = (next_tmp_reg + 1) % RECURSE_TMP_REG_COUNT;- }-}--#undef RECURSE_TMP_REG_COUNT--static BOOL recurse_check_bit(compiler_common *common, sljit_sw bit_index)-{-uint8_t *byte;-uint8_t mask;--SLJIT_ASSERT((bit_index & (sizeof(sljit_sw) - 1)) == 0);--bit_index >>= SLJIT_WORD_SHIFT;--SLJIT_ASSERT((bit_index >> 3) < common->recurse_bitset_size);--mask = 1 << (bit_index & 0x7);-byte = common->recurse_bitset + (bit_index >> 3);--if (*byte & mask)- return FALSE;--*byte |= mask;-return TRUE;-}--enum get_recurse_flags {- recurse_flag_quit_found = (1 << 0),- recurse_flag_accept_found = (1 << 1),- recurse_flag_setsom_found = (1 << 2),- recurse_flag_setmark_found = (1 << 3),- recurse_flag_control_head_found = (1 << 4),-};--static int get_recurse_data_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, uint32_t *result_flags)-{-int length = 1;-int size, offset;-PCRE2_SPTR alternative;-uint32_t recurse_flags = 0;--memset(common->recurse_bitset, 0, common->recurse_bitset_size);--#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD-SLJIT_ASSERT(common->control_head_ptr != 0);-recurse_flags |= recurse_flag_control_head_found;-#endif--/* Calculate the sum of the private machine words. */-while (cc < ccend)- {- size = 0;- switch(*cc)- {- case OP_SET_SOM:- SLJIT_ASSERT(common->has_set_som);- recurse_flags |= recurse_flag_setsom_found;- cc += 1;- break;-- case OP_RECURSE:- if (common->has_set_som)- recurse_flags |= recurse_flag_setsom_found;- if (common->mark_ptr != 0)- recurse_flags |= recurse_flag_setmark_found;- if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))- length++;- cc += 1 + LINK_SIZE;- break;-- case OP_KET:- offset = PRIVATE_DATA(cc);- if (offset != 0)- {- if (recurse_check_bit(common, offset))- length++;- SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);- cc += PRIVATE_DATA(cc + 1);- }- cc += 1 + LINK_SIZE;- break;-- case OP_ASSERT:- case OP_ASSERT_NOT:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT:- case OP_ASSERT_NA:- case OP_ASSERTBACK_NA:- case OP_ONCE:- case OP_SCRIPT_RUN:- case OP_BRAPOS:- case OP_SBRA:- case OP_SBRAPOS:- case OP_SCOND:- SLJIT_ASSERT(PRIVATE_DATA(cc) != 0);- if (recurse_check_bit(common, PRIVATE_DATA(cc)))- length++;- cc += 1 + LINK_SIZE;- break;-- case OP_CBRA:- case OP_SCBRA:- offset = GET2(cc, 1 + LINK_SIZE);- if (recurse_check_bit(common, OVECTOR(offset << 1)))- {- SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));- length += 2;- }- if (common->optimized_cbracket[offset] == 0 && recurse_check_bit(common, OVECTOR_PRIV(offset)))- length++;- if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))- length++;- cc += 1 + LINK_SIZE + IMM2_SIZE;- break;-- case OP_CBRAPOS:- case OP_SCBRAPOS:- offset = GET2(cc, 1 + LINK_SIZE);- if (recurse_check_bit(common, OVECTOR(offset << 1)))- {- SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));- length += 2;- }- if (recurse_check_bit(common, OVECTOR_PRIV(offset)))- length++;- if (recurse_check_bit(common, PRIVATE_DATA(cc)))- length++;- if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))- length++;- 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) && recurse_check_bit(common, PRIVATE_DATA(cc)))- length++;- cc += 1 + LINK_SIZE;- break;-- CASE_ITERATOR_PRIVATE_DATA_1- offset = PRIVATE_DATA(cc);- if (offset != 0 && recurse_check_bit(common, offset))- length++;- cc += 2;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- break;-- CASE_ITERATOR_PRIVATE_DATA_2A- offset = PRIVATE_DATA(cc);- if (offset != 0 && recurse_check_bit(common, offset))- {- SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));- length += 2;- }- cc += 2;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- break;-- CASE_ITERATOR_PRIVATE_DATA_2B- offset = PRIVATE_DATA(cc);- if (offset != 0 && recurse_check_bit(common, offset))- {- SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));- length += 2;- }- cc += 2 + IMM2_SIZE;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- break;-- CASE_ITERATOR_TYPE_PRIVATE_DATA_1- offset = PRIVATE_DATA(cc);- if (offset != 0 && recurse_check_bit(common, offset))- length++;- cc += 1;- break;-- CASE_ITERATOR_TYPE_PRIVATE_DATA_2A- offset = PRIVATE_DATA(cc);- if (offset != 0 && recurse_check_bit(common, offset))- {- SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));- length += 2;- }- cc += 1;- break;-- CASE_ITERATOR_TYPE_PRIVATE_DATA_2B- offset = PRIVATE_DATA(cc);- if (offset != 0 && recurse_check_bit(common, offset))- {- SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));- length += 2;- }- cc += 1 + IMM2_SIZE;- break;-- case OP_CLASS:- case OP_NCLASS:-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8- case OP_XCLASS:- size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR);-#else- size = 1 + 32 / (int)sizeof(PCRE2_UCHAR);-#endif-- offset = PRIVATE_DATA(cc);- if (offset != 0 && recurse_check_bit(common, offset))- length += get_class_iterator_size(cc + size);- cc += size;- break;-- case OP_MARK:- case OP_COMMIT_ARG:- case OP_PRUNE_ARG:- case OP_THEN_ARG:- SLJIT_ASSERT(common->mark_ptr != 0);- recurse_flags |= recurse_flag_setmark_found;- if (common->control_head_ptr != 0)- recurse_flags |= recurse_flag_control_head_found;- if (*cc != OP_MARK)- recurse_flags |= recurse_flag_quit_found;-- cc += 1 + 2 + cc[1];- break;-- case OP_PRUNE:- case OP_SKIP:- case OP_COMMIT:- recurse_flags |= recurse_flag_quit_found;- cc++;- break;-- case OP_SKIP_ARG:- recurse_flags |= recurse_flag_quit_found;- cc += 1 + 2 + cc[1];- break;-- case OP_THEN:- SLJIT_ASSERT(common->control_head_ptr != 0);- recurse_flags |= recurse_flag_quit_found | recurse_flag_control_head_found;- cc++;- break;-- case OP_ACCEPT:- case OP_ASSERT_ACCEPT:- recurse_flags |= recurse_flag_accept_found;- cc++;- break;-- default:- cc = next_opcode(common, cc);- SLJIT_ASSERT(cc != NULL);- break;- }- }-SLJIT_ASSERT(cc == ccend);--if (recurse_flags & recurse_flag_control_head_found)- length++;-if (recurse_flags & recurse_flag_quit_found)- {- if (recurse_flags & recurse_flag_setsom_found)- length++;- if (recurse_flags & recurse_flag_setmark_found)- length++;- }--*result_flags = recurse_flags;-return length;-}--enum copy_recurse_data_types {- recurse_copy_from_global,- recurse_copy_private_to_global,- recurse_copy_shared_to_global,- recurse_copy_kept_shared_to_global,- recurse_swap_global-};--static void copy_recurse_data(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend,- int type, int stackptr, int stacktop, uint32_t recurse_flags)-{-delayed_mem_copy_status status;-PCRE2_SPTR alternative;-sljit_sw private_srcw[2];-sljit_sw shared_srcw[3];-sljit_sw kept_shared_srcw[2];-int private_count, shared_count, kept_shared_count;-int from_sp, base_reg, offset, i;--memset(common->recurse_bitset, 0, common->recurse_bitset_size);--#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD-SLJIT_ASSERT(common->control_head_ptr != 0);-recurse_check_bit(common, common->control_head_ptr);-#endif--switch (type)- {- case recurse_copy_from_global:- from_sp = TRUE;- base_reg = STACK_TOP;- break;-- case recurse_copy_private_to_global:- case recurse_copy_shared_to_global:- case recurse_copy_kept_shared_to_global:- from_sp = FALSE;- base_reg = STACK_TOP;- break;-- default:- SLJIT_ASSERT(type == recurse_swap_global);- from_sp = FALSE;- base_reg = TMP2;- break;- }--stackptr = STACK(stackptr);-stacktop = STACK(stacktop);--status.tmp_regs[0] = TMP1;-status.saved_tmp_regs[0] = TMP1;--if (base_reg != TMP2)- {- status.tmp_regs[1] = TMP2;- status.saved_tmp_regs[1] = TMP2;- }-else- {- status.saved_tmp_regs[1] = RETURN_ADDR;- if (HAS_VIRTUAL_REGISTERS)- status.tmp_regs[1] = STR_PTR;- else- status.tmp_regs[1] = RETURN_ADDR;- }--status.saved_tmp_regs[2] = TMP3;-if (HAS_VIRTUAL_REGISTERS)- status.tmp_regs[2] = STR_END;-else- status.tmp_regs[2] = TMP3;--delayed_mem_copy_init(&status, common);--if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global)- {- SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_private_to_global || type == recurse_swap_global);-- if (!from_sp)- delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, common->recursive_head_ptr);-- if (from_sp || type == recurse_swap_global)- delayed_mem_copy_move(&status, SLJIT_SP, common->recursive_head_ptr, base_reg, stackptr);- }--stackptr += sizeof(sljit_sw);--#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD-if (type != recurse_copy_shared_to_global)- {- if (!from_sp)- delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, common->control_head_ptr);-- if (from_sp || type == recurse_swap_global)- delayed_mem_copy_move(&status, SLJIT_SP, common->control_head_ptr, base_reg, stackptr);- }--stackptr += sizeof(sljit_sw);-#endif--while (cc < ccend)- {- private_count = 0;- shared_count = 0;- kept_shared_count = 0;-- switch(*cc)- {- case OP_SET_SOM:- SLJIT_ASSERT(common->has_set_som);- if ((recurse_flags & recurse_flag_quit_found) && recurse_check_bit(common, OVECTOR(0)))- {- kept_shared_srcw[0] = OVECTOR(0);- kept_shared_count = 1;- }- cc += 1;- break;-- case OP_RECURSE:- if (recurse_flags & recurse_flag_quit_found)- {- if (common->has_set_som && recurse_check_bit(common, OVECTOR(0)))- {- kept_shared_srcw[0] = OVECTOR(0);- kept_shared_count = 1;- }- if (common->mark_ptr != 0 && recurse_check_bit(common, common->mark_ptr))- {- kept_shared_srcw[kept_shared_count] = common->mark_ptr;- kept_shared_count++;- }- }- if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))- {- shared_srcw[0] = common->capture_last_ptr;- shared_count = 1;- }- cc += 1 + LINK_SIZE;- break;-- case OP_KET:- private_srcw[0] = PRIVATE_DATA(cc);- if (private_srcw[0] != 0)- {- if (recurse_check_bit(common, private_srcw[0]))- private_count = 1;- SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);- cc += PRIVATE_DATA(cc + 1);- }- cc += 1 + LINK_SIZE;- break;-- case OP_ASSERT:- case OP_ASSERT_NOT:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT:- case OP_ASSERT_NA:- case OP_ASSERTBACK_NA:- case OP_ONCE:- case OP_SCRIPT_RUN:- case OP_BRAPOS:- case OP_SBRA:- case OP_SBRAPOS:- case OP_SCOND:- private_srcw[0] = PRIVATE_DATA(cc);- if (recurse_check_bit(common, private_srcw[0]))- private_count = 1;- cc += 1 + LINK_SIZE;- break;-- case OP_CBRA:- case OP_SCBRA:- offset = GET2(cc, 1 + LINK_SIZE);- shared_srcw[0] = OVECTOR(offset << 1);- if (recurse_check_bit(common, shared_srcw[0]))- {- shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw);- SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1]));- shared_count = 2;- }-- if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))- {- shared_srcw[shared_count] = common->capture_last_ptr;- shared_count++;- }-- if (common->optimized_cbracket[offset] == 0)- {- private_srcw[0] = OVECTOR_PRIV(offset);- if (recurse_check_bit(common, private_srcw[0]))- private_count = 1;- }-- cc += 1 + LINK_SIZE + IMM2_SIZE;- break;-- case OP_CBRAPOS:- case OP_SCBRAPOS:- offset = GET2(cc, 1 + LINK_SIZE);- shared_srcw[0] = OVECTOR(offset << 1);- if (recurse_check_bit(common, shared_srcw[0]))- {- shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw);- SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1]));- shared_count = 2;- }-- if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))- {- shared_srcw[shared_count] = common->capture_last_ptr;- shared_count++;- }-- private_srcw[0] = PRIVATE_DATA(cc);- if (recurse_check_bit(common, private_srcw[0]))- private_count = 1;-- offset = OVECTOR_PRIV(offset);- if (recurse_check_bit(common, offset))- {- private_srcw[private_count] = offset;- private_count++;- }- 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)- {- private_srcw[0] = PRIVATE_DATA(cc);- if (recurse_check_bit(common, private_srcw[0]))- private_count = 1;- }- cc += 1 + LINK_SIZE;- break;-- CASE_ITERATOR_PRIVATE_DATA_1- private_srcw[0] = PRIVATE_DATA(cc);- if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))- private_count = 1;- cc += 2;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- break;-- CASE_ITERATOR_PRIVATE_DATA_2A- private_srcw[0] = PRIVATE_DATA(cc);- if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))- {- private_count = 2;- private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);- SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));- }- cc += 2;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- break;-- CASE_ITERATOR_PRIVATE_DATA_2B- private_srcw[0] = PRIVATE_DATA(cc);- if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))- {- private_count = 2;- private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);- SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));- }- cc += 2 + IMM2_SIZE;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);-#endif- break;-- CASE_ITERATOR_TYPE_PRIVATE_DATA_1- private_srcw[0] = PRIVATE_DATA(cc);- if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))- private_count = 1;- cc += 1;- break;-- CASE_ITERATOR_TYPE_PRIVATE_DATA_2A- private_srcw[0] = PRIVATE_DATA(cc);- if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))- {- private_count = 2;- private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);- SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));- }- cc += 1;- break;-- CASE_ITERATOR_TYPE_PRIVATE_DATA_2B- private_srcw[0] = PRIVATE_DATA(cc);- if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))- {- private_count = 2;- private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);- SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));- }- cc += 1 + IMM2_SIZE;- break;-- case OP_CLASS:- case OP_NCLASS:-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8- case OP_XCLASS:- i = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR);-#else- i = 1 + 32 / (int)sizeof(PCRE2_UCHAR);-#endif- if (PRIVATE_DATA(cc) != 0)- {- private_count = 1;- private_srcw[0] = PRIVATE_DATA(cc);- switch(get_class_iterator_size(cc + i))- {- case 1:- break;-- case 2:- if (recurse_check_bit(common, private_srcw[0]))- {- private_count = 2;- private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);- SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));- }- break;-- default:- SLJIT_UNREACHABLE();- break;- }- }- cc += i;- break;-- case OP_MARK:- case OP_COMMIT_ARG:- case OP_PRUNE_ARG:- case OP_THEN_ARG:- SLJIT_ASSERT(common->mark_ptr != 0);- if ((recurse_flags & recurse_flag_quit_found) && recurse_check_bit(common, common->mark_ptr))- {- kept_shared_srcw[0] = common->mark_ptr;- kept_shared_count = 1;- }- if (common->control_head_ptr != 0 && recurse_check_bit(common, common->control_head_ptr))- {- private_srcw[0] = common->control_head_ptr;- private_count = 1;- }- cc += 1 + 2 + cc[1];- break;-- case OP_THEN:- SLJIT_ASSERT(common->control_head_ptr != 0);- if (recurse_check_bit(common, common->control_head_ptr))- {- private_srcw[0] = common->control_head_ptr;- private_count = 1;- }- cc++;- break;-- default:- cc = next_opcode(common, cc);- SLJIT_ASSERT(cc != NULL);- continue;- }-- if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global)- {- SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_private_to_global || type == recurse_swap_global);-- for (i = 0; i < private_count; i++)- {- SLJIT_ASSERT(private_srcw[i] != 0);-- if (!from_sp)- delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, private_srcw[i]);-- if (from_sp || type == recurse_swap_global)- delayed_mem_copy_move(&status, SLJIT_SP, private_srcw[i], base_reg, stackptr);-- stackptr += sizeof(sljit_sw);- }- }- else- stackptr += sizeof(sljit_sw) * private_count;-- if (type != recurse_copy_private_to_global && type != recurse_copy_kept_shared_to_global)- {- SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_shared_to_global || type == recurse_swap_global);-- for (i = 0; i < shared_count; i++)- {- SLJIT_ASSERT(shared_srcw[i] != 0);-- if (!from_sp)- delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, shared_srcw[i]);-- if (from_sp || type == recurse_swap_global)- delayed_mem_copy_move(&status, SLJIT_SP, shared_srcw[i], base_reg, stackptr);-- stackptr += sizeof(sljit_sw);- }- }- else- stackptr += sizeof(sljit_sw) * shared_count;-- if (type != recurse_copy_private_to_global && type != recurse_swap_global)- {- SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_shared_to_global || type == recurse_copy_kept_shared_to_global);-- for (i = 0; i < kept_shared_count; i++)- {- SLJIT_ASSERT(kept_shared_srcw[i] != 0);-- if (!from_sp)- delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, kept_shared_srcw[i]);-- if (from_sp || type == recurse_swap_global)- delayed_mem_copy_move(&status, SLJIT_SP, kept_shared_srcw[i], base_reg, stackptr);-- stackptr += sizeof(sljit_sw);- }- }- else- stackptr += sizeof(sljit_sw) * kept_shared_count;- }--SLJIT_ASSERT(cc == ccend && stackptr == stacktop);--delayed_mem_copy_finish(&status);-}--static SLJIT_INLINE PCRE2_SPTR set_then_offsets(compiler_common *common, PCRE2_SPTR cc, sljit_u8 *current_offset)-{-PCRE2_SPTR end = bracketend(cc);-BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT;--/* Assert captures then. */-if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA)- current_offset = NULL;-/* Conditional block does not. */-if (*cc == OP_COND || *cc == OP_SCOND)- has_alternatives = FALSE;--cc = next_opcode(common, cc);-if (has_alternatives)- current_offset = common->then_offsets + (cc - common->start);--while (cc < end)- {- if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND))- cc = set_then_offsets(common, cc, current_offset);- else- {- if (*cc == OP_ALT && has_alternatives)- current_offset = common->then_offsets + (cc + 1 + LINK_SIZE - common->start);- if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL)- *current_offset = 1;- cc = next_opcode(common, cc);- }- }--return end;-}--#undef CASE_ITERATOR_PRIVATE_DATA_1-#undef CASE_ITERATOR_PRIVATE_DATA_2A-#undef CASE_ITERATOR_PRIVATE_DATA_2B-#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_1-#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2A-#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2B--static SLJIT_INLINE BOOL is_powerof2(unsigned int value)-{-return (value & (value - 1)) == 0;-}--static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)-{-while (list)- {- /* sljit_set_label is clever enough to do nothing- if either the jump or the label is NULL. */- SET_LABEL(list->jump, label);- list = list->next;- }-}--static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump *jump)-{-jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));-if (list_item)- {- list_item->next = *list;- list_item->jump = jump;- *list = list_item;- }-}--static void add_stub(compiler_common *common, struct sljit_jump *start)-{-DEFINE_COMPILER;-stub_list *list_item = sljit_alloc_memory(compiler, sizeof(stub_list));--if (list_item)- {- list_item->start = start;- list_item->quit = LABEL();- list_item->next = common->stubs;- common->stubs = list_item;- }-}--static void flush_stubs(compiler_common *common)-{-DEFINE_COMPILER;-stub_list *list_item = common->stubs;--while (list_item)- {- JUMPHERE(list_item->start);- add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));- JUMPTO(SLJIT_JUMP, list_item->quit);- list_item = list_item->next;- }-common->stubs = NULL;-}--static SLJIT_INLINE void count_match(compiler_common *common)-{-DEFINE_COMPILER;--OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);-add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO));-}--static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)-{-/* May destroy all locals and registers except TMP2. */-DEFINE_COMPILER;--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);-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_LESS, STACK_TOP, 0, STACK_LIMIT, 0));-}--static SLJIT_INLINE void free_stack(compiler_common *common, int size)-{-DEFINE_COMPILER;--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)-{-DEFINE_COMPILER;-sljit_uw *result;--if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- return NULL;--result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw), compiler->allocator_data);-if (SLJIT_UNLIKELY(result == NULL))- {- sljit_set_compiler_memory_error(compiler);- return NULL;- }--*(void**)result = common->read_only_data_head;-common->read_only_data_head = (void *)result;-return result + 1;-}--static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)-{-DEFINE_COMPILER;-struct sljit_label *loop;-sljit_s32 i;--/* At this point we can freely use all temporary registers. */-SLJIT_ASSERT(length > 1);-/* TMP1 returns with begin - 1. */-OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1));-if (length < 8)- {- for (i = 1; i < length; i++)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), SLJIT_R0, 0);- }-else- {- if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS)- {- GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START);- OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);- loop = LABEL();- sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw));- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);- JUMPTO(SLJIT_NOT_ZERO, loop);- }- else- {- GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START + sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);- loop = LABEL();- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);- OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));- 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_early_fail(compiler_common *common)-{-DEFINE_COMPILER;-sljit_u32 size = (sljit_u32)(common->early_fail_end_ptr - common->early_fail_start_ptr);-sljit_u32 uncleared_size;-sljit_s32 src = SLJIT_IMM;-sljit_s32 i;-struct sljit_label *loop;--SLJIT_ASSERT(common->early_fail_start_ptr < common->early_fail_end_ptr);--if (size == sizeof(sljit_sw))- {- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->early_fail_start_ptr, SLJIT_IMM, 0);- return;- }--if (sljit_get_register_index(TMP3) >= 0 && !sljit_has_cpu_feature(SLJIT_HAS_ZERO_REGISTER))- {- OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);- src = TMP3;- }--if (size <= 6 * sizeof(sljit_sw))- {- for (i = common->early_fail_start_ptr; i < common->early_fail_end_ptr; i += sizeof(sljit_sw))- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, src, 0);- return;- }--GET_LOCAL_BASE(TMP1, 0, common->early_fail_start_ptr);--uncleared_size = ((size / sizeof(sljit_sw)) % 3) * sizeof(sljit_sw);--OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, size - uncleared_size);--loop = LABEL();-OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), 0, src, 0);-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));-OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -2 * (sljit_sw)sizeof(sljit_sw), src, 0);-OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -1 * (sljit_sw)sizeof(sljit_sw), src, 0);-CMPTO(SLJIT_LESS, TMP1, 0, TMP2, 0, loop);--if (uncleared_size >= sizeof(sljit_sw))- OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), 0, src, 0);--if (uncleared_size >= 2 * sizeof(sljit_sw))- OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), sizeof(sljit_sw), src, 0);-}--static SLJIT_INLINE void do_reset_match(compiler_common *common, int length)-{-DEFINE_COMPILER;-struct sljit_label *loop;-int i;--SLJIT_ASSERT(length > 1);-/* OVECTOR(1) contains the "string begin - 1" constant. */-if (length > 2)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));-if (length < 8)- {- for (i = 2; i < length; i++)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), TMP1, 0);- }-else- {- if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS)- {- GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);- loop = LABEL();- sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw));- OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);- JUMPTO(SLJIT_NOT_ZERO, loop);- }- else- {- GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + 2 * sizeof(sljit_sw));- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);- loop = LABEL();- OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(sljit_sw));- OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);- JUMPTO(SLJIT_NOT_ZERO, loop);- }- }--if (!HAS_VIRTUAL_REGISTERS)- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, stack));-else- OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);--if (common->mark_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);-if (common->control_head_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);-if (HAS_VIRTUAL_REGISTERS)- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));--OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);-OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end));-}--static sljit_sw SLJIT_FUNC do_search_mark(sljit_sw *current, PCRE2_SPTR skip_arg)-{-while (current != NULL)- {- switch (current[1])- {- case type_then_trap:- break;-- case type_mark:- if (PRIV(strcmp)(skip_arg, (PCRE2_SPTR)current[2]) == 0)- return current[3];- break;-- default:- SLJIT_UNREACHABLE();- break;- }- SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]);- current = (sljit_sw*)current[0];- }-return 0;-}--static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)-{-DEFINE_COMPILER;-struct sljit_label *loop;-BOOL has_pre;--/* At this point we can freely use all registers. */-OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0);--if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);- if (common->mark_ptr != 0)- OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);- OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, oveccount));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);- if (common->mark_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);- OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),- SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));- }-else- {- OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);- OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, match_data));- if (common->mark_ptr != 0)- OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);- OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, oveccount));- OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);- if (common->mark_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R0, 0);- OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));- }--has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS;--GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0));-OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? SLJIT_R0 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));--loop = LABEL();--if (has_pre)- sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));-else- {- OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0);- OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));- }--OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, sizeof(PCRE2_SIZE));-OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0);-/* Copy the integer value to the output buffer */-#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32-OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);-#endif--SLJIT_ASSERT(sizeof(PCRE2_SIZE) == 4 || sizeof(PCRE2_SIZE) == 8);-OP1(((sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV), SLJIT_MEM1(SLJIT_R2), 0, SLJIT_S1, 0);--OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);-JUMPTO(SLJIT_NOT_ZERO, loop);--/* Calculate the return value, which is the maximum ovector value. */-if (topbracket > 1)- {- if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))) == SLJIT_SUCCESS)- {- GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);-- /* OVECTOR(0) is never equal to SLJIT_S2. */- loop = LABEL();- sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw)));- OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);- CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);- }- else- {- GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + (topbracket - 1) * 2 * sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);-- /* OVECTOR(0) is never equal to SLJIT_S2. */- loop = LABEL();- OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0);- OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * (sljit_sw)sizeof(sljit_sw));- OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);- CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);- }- }-else- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);-}--static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit)-{-DEFINE_COMPILER;-sljit_s32 mov_opcode;-sljit_s32 arguments_reg = !HAS_VIRTUAL_REGISTERS ? ARGUMENTS : SLJIT_R1;--SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S0, str_end_must_be_saved_reg0);-SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0- && (common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start != 0 : common->hit_start == 0));--if (arguments_reg != ARGUMENTS)- OP1(SLJIT_MOV, arguments_reg, 0, ARGUMENTS, 0);-OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP),- common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start : common->start_ptr);-OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_PARTIAL);--/* Store match begin and end. */-OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, begin));-OP1(SLJIT_MOV, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0);-OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, match_data));--mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;--OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S1, 0);-#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32-OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);-#endif-OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector), SLJIT_R2, 0);--OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_S1, 0);-#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32-OP2(SLJIT_ASHR, STR_END, 0, STR_END, 0, SLJIT_IMM, UCHAR_SHIFT);-#endif-OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector) + sizeof(PCRE2_SIZE), STR_END, 0);--JUMPTO(SLJIT_JUMP, quit);-}--static SLJIT_INLINE void check_start_used_ptr(compiler_common *common)-{-/* May destroy TMP1. */-DEFINE_COMPILER;-struct sljit_jump *jump;--if (common->mode == PCRE2_JIT_PARTIAL_SOFT)- {- /* The value of -1 must be kept for start_used_ptr! */- OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, 1);- /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting- is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */- jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);- JUMPHERE(jump);- }-else if (common->mode == PCRE2_JIT_PARTIAL_HARD)- {- jump = CMP(SLJIT_LESS_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);- JUMPHERE(jump);- }-}--static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, PCRE2_SPTR cc)-{-/* Detects if the character has an othercase. */-unsigned int c;--#ifdef SUPPORT_UNICODE-if (common->utf || common->ucp)- {- if (common->utf)- {- GETCHAR(c, cc);- }- else- c = *cc;-- if (c > 127)- return c != UCD_OTHERCASE(c);-- return common->fcc[c] != c;- }-else-#endif- c = *cc;-return MAX_255(c) ? common->fcc[c] != c : FALSE;-}--static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)-{-/* Returns with the othercase. */-#ifdef SUPPORT_UNICODE-if ((common->utf || common->ucp) && c > 127)- return UCD_OTHERCASE(c);-#endif-return TABLE_GET(c, common->fcc, c);-}--static unsigned int char_get_othercase_bit(compiler_common *common, PCRE2_SPTR cc)-{-/* Detects if the character and its othercase has only 1 bit difference. */-unsigned int c, oc, bit;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8-int n;-#endif--#ifdef SUPPORT_UNICODE-if (common->utf || common->ucp)- {- if (common->utf)- {- GETCHAR(c, cc);- }- else- c = *cc;-- if (c <= 127)- oc = common->fcc[c];- else- oc = UCD_OTHERCASE(c);- }-else- {- c = *cc;- oc = TABLE_GET(c, common->fcc, c);- }-#else-c = *cc;-oc = TABLE_GET(c, common->fcc, c);-#endif--SLJIT_ASSERT(c != oc);--bit = c ^ oc;-/* Optimized for English alphabet. */-if (c <= 127 && bit == 0x20)- return (0 << 8) | 0x20;--/* Since c != oc, they must have at least 1 bit difference. */-if (!is_powerof2(bit))- return 0;--#if PCRE2_CODE_UNIT_WIDTH == 8--#ifdef SUPPORT_UNICODE-if (common->utf && c > 127)- {- n = GET_EXTRALEN(*cc);- while ((bit & 0x3f) == 0)- {- n--;- bit >>= 6;- }- return (n << 8) | bit;- }-#endif /* SUPPORT_UNICODE */-return (0 << 8) | bit;--#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32--#ifdef SUPPORT_UNICODE-if (common->utf && c > 65535)- {- if (bit >= (1u << 10))- bit >>= 10;- else- return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));- }-#endif /* SUPPORT_UNICODE */-return (bit < 256) ? ((0u << 8) | bit) : ((1u << 8) | (bit >> 8));--#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */-}--static void check_partial(compiler_common *common, BOOL force)-{-/* Checks whether a partial matching is occurred. Does not modify registers. */-DEFINE_COMPILER;-struct sljit_jump *jump = NULL;--SLJIT_ASSERT(!force || common->mode != PCRE2_JIT_COMPLETE);--if (common->mode == PCRE2_JIT_COMPLETE)- return;--if (!force && !common->allow_empty_partial)- jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);-else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)- jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);--if (common->mode == PCRE2_JIT_PARTIAL_SOFT)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);-else- {- if (common->partialmatchlabel != NULL)- JUMPTO(SLJIT_JUMP, common->partialmatchlabel);- else- add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));- }--if (jump != NULL)- JUMPHERE(jump);-}--static void check_str_end(compiler_common *common, jump_list **end_reached)-{-/* Does not affect registers. Usually used in a tight spot. */-DEFINE_COMPILER;-struct sljit_jump *jump;--if (common->mode == PCRE2_JIT_COMPLETE)- {- add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));- return;- }--jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);-if (common->mode == PCRE2_JIT_PARTIAL_SOFT)- {- add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);- add_jump(compiler, end_reached, JUMP(SLJIT_JUMP));- }-else- {- add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));- if (common->partialmatchlabel != NULL)- JUMPTO(SLJIT_JUMP, common->partialmatchlabel);- else- add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));- }-JUMPHERE(jump);-}--static void detect_partial_match(compiler_common *common, jump_list **backtracks)-{-DEFINE_COMPILER;-struct sljit_jump *jump;--if (common->mode == PCRE2_JIT_COMPLETE)- {- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));- return;- }--/* Partial matching mode. */-jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);-if (!common->allow_empty_partial)- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));-else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1));--if (common->mode == PCRE2_JIT_PARTIAL_SOFT)- {- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);- add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));- }-else- {- if (common->partialmatchlabel != NULL)- JUMPTO(SLJIT_JUMP, common->partialmatchlabel);- else- add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));- }-JUMPHERE(jump);-}--static void process_partial_match(compiler_common *common)-{-DEFINE_COMPILER;-struct sljit_jump *jump;--/* Partial matching mode. */-if (common->mode == PCRE2_JIT_PARTIAL_SOFT)- {- jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);- JUMPHERE(jump);- }-else if (common->mode == PCRE2_JIT_PARTIAL_HARD)- {- if (common->partialmatchlabel != NULL)- CMPTO(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0, common->partialmatchlabel);- else- add_jump(compiler, &common->partialmatch, CMP(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));- }-}--static void detect_partial_match_to(compiler_common *common, struct sljit_label *label)-{-DEFINE_COMPILER;--CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, label);-process_partial_match(common);-}--static void peek_char(compiler_common *common, sljit_u32 max, sljit_s32 dst, sljit_sw dstw, jump_list **backtracks)-{-/* Reads the character into TMP1, keeps STR_PTR.-Does not check STR_END. TMP2, dst, RETURN_ADDR Destroyed. */-DEFINE_COMPILER;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-struct sljit_jump *jump;-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */--SLJIT_UNUSED_ARG(max);-SLJIT_UNUSED_ARG(dst);-SLJIT_UNUSED_ARG(dstw);-SLJIT_UNUSED_ARG(backtracks);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));--#ifdef SUPPORT_UNICODE-#if PCRE2_CODE_UNIT_WIDTH == 8-if (common->utf)- {- if (max < 128) return;-- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);- OP1(SLJIT_MOV, dst, dstw, STR_PTR, 0);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- add_jump(compiler, common->invalid_utf ? &common->utfreadchar_invalid : &common->utfreadchar, JUMP(SLJIT_FAST_CALL));- OP1(SLJIT_MOV, STR_PTR, 0, dst, dstw);- if (backtracks && common->invalid_utf)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));- JUMPHERE(jump);- }-#elif PCRE2_CODE_UNIT_WIDTH == 16-if (common->utf)- {- if (max < 0xd800) return;-- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);-- if (common->invalid_utf)- {- jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);- OP1(SLJIT_MOV, dst, dstw, STR_PTR, 0);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));- OP1(SLJIT_MOV, STR_PTR, 0, dst, dstw);- if (backtracks && common->invalid_utf)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));- }- else- {- /* TMP2 contains the high surrogate. */- jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800);- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);- }-- JUMPHERE(jump);- }-#elif PCRE2_CODE_UNIT_WIDTH == 32-if (common->invalid_utf)- {- if (max < 0xd800) return;-- if (backtracks != NULL)- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));- }- else- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);- OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000);- CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);- CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);- }- }-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */-#endif /* SUPPORT_UNICODE */-}--static void peek_char_back(compiler_common *common, sljit_u32 max, jump_list **backtracks)-{-/* Reads one character back without moving STR_PTR. TMP2 must-contain the start of the subject buffer. Affects TMP1, TMP2, and RETURN_ADDR. */-DEFINE_COMPILER;--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-struct sljit_jump *jump;-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */--SLJIT_UNUSED_ARG(max);-SLJIT_UNUSED_ARG(backtracks);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));--#ifdef SUPPORT_UNICODE-#if PCRE2_CODE_UNIT_WIDTH == 8-if (common->utf)- {- if (max < 128) return;-- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);- if (common->invalid_utf)- {- add_jump(compiler, &common->utfpeakcharback_invalid, JUMP(SLJIT_FAST_CALL));- if (backtracks != NULL)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));- }- else- add_jump(compiler, &common->utfpeakcharback, JUMP(SLJIT_FAST_CALL));- JUMPHERE(jump);- }-#elif PCRE2_CODE_UNIT_WIDTH == 16-if (common->utf)- {- if (max < 0xd800) return;-- if (common->invalid_utf)- {- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);- add_jump(compiler, &common->utfpeakcharback_invalid, JUMP(SLJIT_FAST_CALL));- if (backtracks != NULL)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));- }- else- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xdc00);- jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xdc00);- /* TMP2 contains the low surrogate. */- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x10000);- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);- }- JUMPHERE(jump);- }-#elif PCRE2_CODE_UNIT_WIDTH == 32-if (common->invalid_utf)- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));- }-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */-#endif /* SUPPORT_UNICODE */-}--#define READ_CHAR_UPDATE_STR_PTR 0x1-#define READ_CHAR_UTF8_NEWLINE 0x2-#define READ_CHAR_NEWLINE (READ_CHAR_UPDATE_STR_PTR | READ_CHAR_UTF8_NEWLINE)-#define READ_CHAR_VALID_UTF 0x4--static void read_char(compiler_common *common, sljit_u32 min, sljit_u32 max,- jump_list **backtracks, sljit_u32 options)-{-/* 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-outside the range. Does not check STR_END. */-DEFINE_COMPILER;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-struct sljit_jump *jump;-#endif-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8-struct sljit_jump *jump2;-#endif--SLJIT_UNUSED_ARG(min);-SLJIT_UNUSED_ARG(max);-SLJIT_UNUSED_ARG(backtracks);-SLJIT_UNUSED_ARG(options);-SLJIT_ASSERT(min <= max);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--#ifdef SUPPORT_UNICODE-#if PCRE2_CODE_UNIT_WIDTH == 8-if (common->utf)- {- if (max < 128 && !(options & READ_CHAR_UPDATE_STR_PTR)) return;-- if (common->invalid_utf && !(options & READ_CHAR_VALID_UTF))- {- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);-- if (options & READ_CHAR_UTF8_NEWLINE)- add_jump(compiler, &common->utfreadnewline_invalid, JUMP(SLJIT_FAST_CALL));- else- add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));-- if (backtracks != NULL)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));- JUMPHERE(jump);- return;- }-- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);- if (min >= 0x10000)- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0);- if (options & READ_CHAR_UPDATE_STR_PTR)- 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);- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));- 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);- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));- if (!(options & READ_CHAR_UPDATE_STR_PTR))- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));- 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);- JUMPHERE(jump2);- if (options & READ_CHAR_UPDATE_STR_PTR)- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);- }- else if (min >= 0x800 && max <= 0xffff)- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0);- if (options & READ_CHAR_UPDATE_STR_PTR)- 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);- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));- if (!(options & READ_CHAR_UPDATE_STR_PTR))- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));- 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);- JUMPHERE(jump2);- if (options & READ_CHAR_UPDATE_STR_PTR)- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);- }- else if (max >= 0x800)- {- add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));- }- else if (max < 128)- {- 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- {- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));- if (!(options & READ_CHAR_UPDATE_STR_PTR))- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- else- 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);- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);- if (options & READ_CHAR_UPDATE_STR_PTR)- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);- }- JUMPHERE(jump);- }-#elif PCRE2_CODE_UNIT_WIDTH == 16-if (common->utf)- {- if (max < 0xd800 && !(options & READ_CHAR_UPDATE_STR_PTR)) return;-- if (common->invalid_utf && !(options & READ_CHAR_VALID_UTF))- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);- jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);-- if (options & READ_CHAR_UTF8_NEWLINE)- add_jump(compiler, &common->utfreadnewline_invalid, JUMP(SLJIT_FAST_CALL));- else- add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));-- if (backtracks != NULL)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));- JUMPHERE(jump);- return;- }-- if (max >= 0x10000)- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);- jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800);- /* TMP2 contains the high surrogate. */- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);- JUMPHERE(jump);- return;- }-- /* Skip low surrogate if necessary. */- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);-- if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)- {- if (options & READ_CHAR_UPDATE_STR_PTR)- OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0x400);- if (options & READ_CHAR_UPDATE_STR_PTR)- CMOV(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0);- if (max >= 0xd800)- CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, 0x10000);- }- else- {- jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);- if (options & READ_CHAR_UPDATE_STR_PTR)- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- if (max >= 0xd800)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);- JUMPHERE(jump);- }- }-#elif PCRE2_CODE_UNIT_WIDTH == 32-if (common->invalid_utf)- {- if (backtracks != NULL)- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));- }- else- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);- OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000);- CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);- CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);- }- }-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */-#endif /* SUPPORT_UNICODE */-}--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8--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 sljit_u8 value = nclass ? 0xff : 0;-const sljit_u8 *end = bitset + 32;--bitset += 16;-do- {- if (*bitset++ != value)- return FALSE;- }-while (bitset < end);-return TRUE;-}--static void read_char7_type(compiler_common *common, jump_list **backtracks, BOOL negated)-{-/* Reads the precise character type of a character into TMP1, if the character-is less than 128. Otherwise it returns with zero. Does not check STR_END. The-full_read argument tells whether characters above max are accepted or not. */-DEFINE_COMPILER;-struct sljit_jump *jump;--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));--/* All values > 127 are zero in ctypes. */-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);--if (negated)- {- jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x80);-- if (common->invalid_utf)- {- add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);- }- else- {- 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);- }-}--#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */--static void read_char8_type(compiler_common *common, jump_list **backtracks, BOOL negated)-{-/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */-DEFINE_COMPILER;-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8-struct sljit_jump *jump;-#endif-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8-struct sljit_jump *jump2;-#endif--SLJIT_UNUSED_ARG(backtracks);-SLJIT_UNUSED_ARG(negated);--OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8-if (common->utf)- {- /* The result of this read may be unused, but saves an "else" part. */- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);- jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x80);-- if (!negated)- {- if (common->invalid_utf)- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));-- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);- if (common->invalid_utf)- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe0 - 0xc2));-- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);- if (common->invalid_utf)- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40));-- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);- jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);- JUMPHERE(jump2);- }- else if (common->invalid_utf)- {- add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));- OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));-- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);- jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);- JUMPHERE(jump2);- }- else- add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));-- JUMPHERE(jump);- return;- }-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32-if (common->invalid_utf && negated)- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x110000));-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32 */--#if PCRE2_CODE_UNIT_WIDTH != 8-/* The ctypes array contains only 256 values. */-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);-jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);-#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);-#if PCRE2_CODE_UNIT_WIDTH != 8-JUMPHERE(jump);-#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16-if (common->utf && negated)- {- /* Skip low surrogate if necessary. */- if (!common->invalid_utf)- {- OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);-- if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)- {- OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0x400);- CMOV(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0);- }- else- {- jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- JUMPHERE(jump);- }- return;- }-- OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);- jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400));- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));-- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xdc00);- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400));-- JUMPHERE(jump);- return;- }-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16 */-}--static void move_back(compiler_common *common, jump_list **backtracks, BOOL must_be_valid)-{-/* Goes one character back. Affects STR_PTR and TMP1. If must_be_valid is TRUE,-TMP2 is not used. Otherwise TMP2 must contain the start of the subject buffer,-and it is destroyed. Does not modify STR_PTR for invalid character sequences. */-DEFINE_COMPILER;--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-struct sljit_jump *jump;-#endif--#ifdef SUPPORT_UNICODE-#if PCRE2_CODE_UNIT_WIDTH == 8-struct sljit_label *label;--if (common->utf)- {- if (!must_be_valid && common->invalid_utf)- {- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);- add_jump(compiler, &common->utfmoveback_invalid, JUMP(SLJIT_FAST_CALL));- if (backtracks != NULL)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));- JUMPHERE(jump);- return;- }-- label = LABEL();- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);- CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);- return;- }-#elif PCRE2_CODE_UNIT_WIDTH == 16-if (common->utf)- {- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-- if (!must_be_valid && common->invalid_utf)- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);- jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000 - 0xd800);- add_jump(compiler, &common->utfmoveback_invalid, JUMP(SLJIT_FAST_CALL));- if (backtracks != NULL)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));- JUMPHERE(jump);- return;- }-- /* Skip low surrogate if necessary. */- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0xdc00);- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);- return;- }-#elif PCRE2_CODE_UNIT_WIDTH == 32-if (common->invalid_utf && !must_be_valid)- {- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));- if (backtracks != NULL)- {- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- return;- }-- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x110000);- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);- return;- }-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */-#endif /* SUPPORT_UNICODE */--SLJIT_UNUSED_ARG(backtracks);-SLJIT_UNUSED_ARG(must_be_valid);--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-}--static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpifmatch)-{-/* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */-DEFINE_COMPILER;-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)- {- if (jumpifmatch)- {- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR));- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));- }- else- {- jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));- JUMPHERE(jump);- }- }-else- {- SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);- add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));- }-}--#ifdef SUPPORT_UNICODE--#if PCRE2_CODE_UNIT_WIDTH == 8-static void do_utfreadchar(compiler_common *common)-{-/* Fast decoding a UTF-8 character. TMP1 contains the first byte-of the character (>= 0xc0). Return char value in TMP1. */-DEFINE_COMPILER;-struct sljit_jump *jump;--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));-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);--/* Searching for the first zero. */-OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x800);-jump = JUMP(SLJIT_NOT_ZERO);-/* Two byte sequence. */-OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3000);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(jump);-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));-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);--OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x10000);-jump = JUMP(SLJIT_NOT_ZERO);-/* Three byte sequence. */-OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0000);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--/* Four byte sequence. */-JUMPHERE(jump);-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));-OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xf0000);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));-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);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_utfreadtype8(compiler_common *common)-{-/* Fast decoding a UTF-8 character type. TMP2 contains the first byte-of the character (>= 0xc0). Return value in TMP1. */-DEFINE_COMPILER;-struct sljit_jump *jump;-struct sljit_jump *compare;--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--OP2U(SLJIT_AND | SLJIT_SET_Z, 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));-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);-/* The upper 5 bits are known at this point. */-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_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(compare);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--/* We only have types for characters less than 256. */-JUMPHERE(jump);-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);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_utfreadchar_invalid(compiler_common *common)-{-/* Slow decoding a UTF-8 character. TMP1 contains the first byte-of the character (>= 0xc0). Return char value in TMP1. STR_PTR is-undefined for invalid characters. */-DEFINE_COMPILER;-sljit_s32 i;-sljit_s32 has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV);-struct sljit_jump *jump;-struct sljit_jump *buffer_end_close;-struct sljit_label *three_byte_entry;-struct sljit_label *exit_invalid_label;-struct sljit_jump *exit_invalid[11];--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc2);--/* Usually more than 3 characters remained in the subject buffer. */-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));--/* Not a valid start of a multi-byte sequence, no more bytes read. */-exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xf5 - 0xc2);--buffer_end_close = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);--OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);-/* If TMP2 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);-exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);--OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x800);-jump = JUMP(SLJIT_NOT_ZERO);--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(jump);--/* Three-byte sequence. */-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);-if (has_cmov)- {- OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);- CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0x20000);- exit_invalid[2] = NULL;- }-else- exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);--OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x10000);-jump = JUMP(SLJIT_NOT_ZERO);--three_byte_entry = LABEL();--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2d800);-if (has_cmov)- {- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);- CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0xd800);- exit_invalid[3] = NULL;- }-else- exit_invalid[3] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--if (has_cmov)- {- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);- CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);- exit_invalid[4] = NULL;- }-else- exit_invalid[4] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(jump);--/* Four-byte sequence. */-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);-if (has_cmov)- {- OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);- CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0);- exit_invalid[5] = NULL;- }-else- exit_invalid[5] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc10000);-if (has_cmov)- {- OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);- CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000);- exit_invalid[6] = NULL;- }-else- exit_invalid[6] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);--OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(buffer_end_close);-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));-exit_invalid[7] = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);--/* Two-byte sequence. */-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);-/* If TMP2 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);-exit_invalid[8] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);--OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x800);-jump = JUMP(SLJIT_NOT_ZERO);--OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--/* Three-byte sequence. */-JUMPHERE(jump);-exit_invalid[9] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);--OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);-if (has_cmov)- {- OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);- CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);- exit_invalid[10] = NULL;- }-else- exit_invalid[10] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);--/* One will be substracted from STR_PTR later. */-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));--/* Four byte sequences are not possible. */-CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x30000, three_byte_entry);--exit_invalid_label = LABEL();-for (i = 0; i < 11; i++)- sljit_set_label(exit_invalid[i], exit_invalid_label);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_utfreadnewline_invalid(compiler_common *common)-{-/* Slow decoding a UTF-8 character, specialized for newlines.-TMP1 contains the first byte of the character (>= 0xc0). Return-char value in TMP1. */-DEFINE_COMPILER;-struct sljit_label *loop;-struct sljit_label *skip_start;-struct sljit_label *three_byte_exit;-struct sljit_jump *jump[5];--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--if (common->nltype != NLTYPE_ANY)- {- SLJIT_ASSERT(common->nltype != NLTYPE_FIXED || common->newline < 128);-- /* All newlines are ascii, just skip intermediate octets. */- jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);- loop = LABEL();- if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)) == SLJIT_SUCCESS)- sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));- else- {- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- }-- OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);- CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop);- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-- JUMPHERE(jump[0]);-- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);- OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);- return;- }--jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--jump[1] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xc2);-jump[2] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xe2);--skip_start = LABEL();-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);-jump[3] = CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80);--/* Skip intermediate octets. */-loop = LABEL();-jump[4] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);-CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop);--JUMPHERE(jump[3]);-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--three_byte_exit = LABEL();-JUMPHERE(jump[0]);-JUMPHERE(jump[4]);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--/* Two byte long newline: 0x85. */-JUMPHERE(jump[1]);-CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x85, skip_start);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x85);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--/* Three byte long newlines: 0x2028 and 0x2029. */-JUMPHERE(jump[2]);-CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, skip_start);-CMPTO(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0, three_byte_exit);--OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--OP2(SLJIT_SUB, TMP1, 0, TMP2, 0, SLJIT_IMM, 0x80);-CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x40, skip_start);--OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0x2000);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_utfmoveback_invalid(compiler_common *common)-{-/* Goes one character back. */-DEFINE_COMPILER;-sljit_s32 i;-struct sljit_jump *jump;-struct sljit_jump *buffer_start_close;-struct sljit_label *exit_ok_label;-struct sljit_label *exit_invalid_label;-struct sljit_jump *exit_invalid[7];--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));-exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xc0);--/* Two-byte sequence. */-buffer_start_close = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);-jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x20);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--/* Three-byte sequence. */-JUMPHERE(jump);-exit_invalid[1] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, -0x40);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);-jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x10);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--/* Four-byte sequence. */-JUMPHERE(jump);-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0 - 0x80);-exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x40);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));-OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xf0);-exit_invalid[3] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x05);--exit_ok_label = LABEL();-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--/* Two-byte sequence. */-JUMPHERE(buffer_start_close);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));--exit_invalid[4] = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);-CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x20, exit_ok_label);--/* Three-byte sequence. */-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-exit_invalid[5] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, -0x40);-exit_invalid[6] = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);-CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10, exit_ok_label);--/* Four-byte sequences are not possible. */--exit_invalid_label = LABEL();-sljit_set_label(exit_invalid[5], exit_invalid_label);-sljit_set_label(exit_invalid[6], exit_invalid_label);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(exit_invalid[4]);-/* -2 + 4 = 2 */-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));--exit_invalid_label = LABEL();-for (i = 0; i < 4; i++)- sljit_set_label(exit_invalid[i], exit_invalid_label);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(4));-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_utfpeakcharback(compiler_common *common)-{-/* Peak a character back. Does not modify STR_PTR. */-DEFINE_COMPILER;-struct sljit_jump *jump[2];--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));-OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);-jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x20);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));-OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);-jump[1] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10);--OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-4));-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0 - 0x80);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf0);-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);--JUMPHERE(jump[1]);-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);--JUMPHERE(jump[0]);-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);--OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_utfpeakcharback_invalid(compiler_common *common)-{-/* Peak a character back. Does not modify STR_PTR. */-DEFINE_COMPILER;-sljit_s32 i;-sljit_s32 has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV);-struct sljit_jump *jump[2];-struct sljit_label *two_byte_entry;-struct sljit_label *three_byte_entry;-struct sljit_label *exit_invalid_label;-struct sljit_jump *exit_invalid[8];--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));-exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xc0);-jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);--/* Two-byte sequence. */-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);-jump[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x1e);--two_byte_entry = LABEL();-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);-/* If TMP1 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(jump[1]);-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2 - 0x80);-OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);-exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);--/* Three-byte sequence. */-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0);-jump[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x10);--three_byte_entry = LABEL();-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);-if (has_cmov)- {- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);- CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, -0xd800);- exit_invalid[2] = NULL;- }-else- exit_invalid[2] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);--OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);-if (has_cmov)- {- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);- CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);- exit_invalid[3] = NULL;- }-else- exit_invalid[3] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);--OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(jump[1]);-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0 - 0x80);-exit_invalid[4] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);--/* Four-byte sequence. */-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-4));-OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf0);-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 18);-/* ADD is used instead of OR because of the SUB 0x10000 above. */-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);--if (has_cmov)- {- OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);- CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000);- exit_invalid[5] = NULL;- }-else- exit_invalid[5] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);--OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(jump[0]);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));-jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);--/* Two-byte sequence. */-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);-CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x1e, two_byte_entry);--OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2 - 0x80);-OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);-exit_invalid[6] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);--/* Three-byte sequence. */-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0);-CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x10, three_byte_entry);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(jump[0]);-exit_invalid[7] = CMP(SLJIT_GREATER, TMP2, 0, STR_PTR, 0);--/* Two-byte sequence. */-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);-CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x1e, two_byte_entry);--exit_invalid_label = LABEL();-for (i = 0; i < 8; i++)- sljit_set_label(exit_invalid[i], exit_invalid_label);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */--#if PCRE2_CODE_UNIT_WIDTH == 16--static void do_utfreadchar_invalid(compiler_common *common)-{-/* Slow decoding a UTF-16 character. TMP1 contains the first half-of the character (>= 0xd800). Return char value in TMP1. STR_PTR is-undefined for invalid characters. */-DEFINE_COMPILER;-struct sljit_jump *exit_invalid[3];--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--/* TMP2 contains the high surrogate. */-exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00);-exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xdc00);-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x10000);-exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400);--OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(exit_invalid[0]);-JUMPHERE(exit_invalid[1]);-JUMPHERE(exit_invalid[2]);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_utfreadnewline_invalid(compiler_common *common)-{-/* Slow decoding a UTF-16 character, specialized for newlines.-TMP1 contains the first half of the character (>= 0xd800). Return-char value in TMP1. */--DEFINE_COMPILER;-struct sljit_jump *exit_invalid[2];--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--/* TMP2 contains the high surrogate. */-exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);--OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));-exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00);--OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xdc00);-OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0x400);-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);--OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(exit_invalid[0]);-JUMPHERE(exit_invalid[1]);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_utfmoveback_invalid(compiler_common *common)-{-/* Goes one character back. */-DEFINE_COMPILER;-struct sljit_jump *exit_invalid[3];--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--exit_invalid[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x400);-exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));-OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);-exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400);--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(exit_invalid[0]);-JUMPHERE(exit_invalid[1]);-JUMPHERE(exit_invalid[2]);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_utfpeakcharback_invalid(compiler_common *common)-{-/* Peak a character back. Does not modify STR_PTR. */-DEFINE_COMPILER;-struct sljit_jump *jump;-struct sljit_jump *exit_invalid[3];--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000);-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));-exit_invalid[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);-exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);--OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);-OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);-exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);--JUMPHERE(jump);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(exit_invalid[0]);-JUMPHERE(exit_invalid[1]);-JUMPHERE(exit_invalid[2]);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */--/* UCD_BLOCK_SIZE must be 128 (see the assert below). */-#define UCD_BLOCK_MASK 127-#define UCD_BLOCK_SHIFT 7--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;-#if PCRE2_CODE_UNIT_WIDTH == 32-struct sljit_jump *jump;-#endif--#if defined SLJIT_DEBUG && SLJIT_DEBUG-/* dummy_ucd_record */-const ucd_record *record = GET_UCD(UNASSIGNED_UTF_CHAR);-SLJIT_ASSERT(record->script == ucp_Unknown && 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) == 12);--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--#if PCRE2_CODE_UNIT_WIDTH == 32-if (!common->utf)- {- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);- JUMPHERE(jump);- }-#endif--OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);-OP1(SLJIT_MOV_U16, 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);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_getucdtype(compiler_common *common)-{-/* Search the UCD record for the character comes in TMP1.-Returns chartype in TMP1 and UCD offset in TMP2. */-DEFINE_COMPILER;-#if PCRE2_CODE_UNIT_WIDTH == 32-struct sljit_jump *jump;-#endif--#if defined SLJIT_DEBUG && SLJIT_DEBUG-/* dummy_ucd_record */-const ucd_record *record = GET_UCD(UNASSIGNED_UTF_CHAR);-SLJIT_ASSERT(record->script == ucp_Unknown && 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) == 12);--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--#if PCRE2_CODE_UNIT_WIDTH == 32-if (!common->utf)- {- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);- JUMPHERE(jump);- }-#endif--OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);-OP1(SLJIT_MOV_U16, 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);--/* TMP2 is multiplied by 12. Same as (TMP2 << 2) + ((TMP2 << 2) << 1). */-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 1);--OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--#endif /* SUPPORT_UNICODE */--static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common)-{-DEFINE_COMPILER;-struct sljit_label *mainloop;-struct sljit_label *newlinelabel = NULL;-struct sljit_jump *start;-struct sljit_jump *end = NULL;-struct sljit_jump *end2 = NULL;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-struct sljit_label *loop;-struct sljit_jump *jump;-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */-jump_list *newline = NULL;-sljit_u32 overall_options = common->re->overall_options;-BOOL hascrorlf = (common->re->flags & PCRE2_HASCRORLF) != 0;-BOOL newlinecheck = FALSE;-BOOL readuchar = FALSE;--if (!(hascrorlf || (overall_options & PCRE2_FIRSTLINE) != 0)- && (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255))- newlinecheck = TRUE;--SLJIT_ASSERT(common->abort_label == NULL);--if ((overall_options & PCRE2_FIRSTLINE) != 0)- {- /* Search for the end of the first line. */- SLJIT_ASSERT(common->match_end_ptr != 0);- OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);-- if (common->nltype == NLTYPE_FIXED && common->newline > 255)- {- mainloop = LABEL();- 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), IN_UCHARS(-1));- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));- 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->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->match_end_ptr, STR_PTR, 0);- read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE);- 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->match_end_ptr, STR_PTR, 0);- set_jumps(newline, LABEL());- }-- OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);- }-else if ((overall_options & PCRE2_USE_OFFSET_LIMIT) != 0)- {- /* Check whether offset limit is set and valid. */- SLJIT_ASSERT(common->match_end_ptr != 0);-- if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, offset_limit));- }- else- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, offset_limit));-- OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);- end = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw) PCRE2_UNSET);- if (HAS_VIRTUAL_REGISTERS)- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);- else- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));--#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);-#endif /* PCRE2_CODE_UNIT_WIDTH == [16|32] */- if (HAS_VIRTUAL_REGISTERS)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));-- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);- end2 = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);- OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);- JUMPHERE(end2);- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);- add_jump(compiler, &common->abort, CMP(SLJIT_LESS, TMP2, 0, STR_PTR, 0));- JUMPHERE(end);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, TMP2, 0);- }--start = JUMP(SLJIT_JUMP);--if (newlinecheck)- {- newlinelabel = LABEL();- 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);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, common->newline & 0xff);- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);-#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);-#endif /* PCRE2_CODE_UNIT_WIDTH == [16|32] */- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);- end2 = JUMP(SLJIT_JUMP);- }--mainloop = LABEL();--/* Increasing the STR_PTR here requires one less jump in the most common case. */-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-if (common->utf && !common->invalid_utf) readuchar = TRUE;-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */-if (newlinecheck) readuchar = TRUE;--if (readuchar)- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);--if (newlinecheck)- CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-#if PCRE2_CODE_UNIT_WIDTH == 8-if (common->invalid_utf)- {- /* Skip continuation code units. */- loop = LABEL();- jump = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);- 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, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);- CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x40, loop);- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- JUMPHERE(jump);- }-else if (common->utf)- {- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 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(jump);- }-#elif PCRE2_CODE_UNIT_WIDTH == 16-if (common->invalid_utf)- {- /* Skip continuation code units. */- loop = LABEL();- jump = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);- 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, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xdc00);- CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x400, loop);- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- JUMPHERE(jump);- }-else if (common->utf)- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);-- if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))- {- OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x400);- CMOV(SLJIT_LESS, STR_PTR, TMP2, 0);- }- else- {- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x400);- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);- }- }-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */-JUMPHERE(start);--if (newlinecheck)- {- JUMPHERE(end);- JUMPHERE(end2);- }--return mainloop;-}---static SLJIT_INLINE void add_prefix_char(PCRE2_UCHAR chr, fast_forward_char_data *chars, BOOL last)-{-sljit_u32 i, count = chars->count;--if (count == 255)- return;--if (count == 0)- {- chars->count = 1;- chars->chars[0] = chr;-- if (last)- chars->last_count = 1;- return;- }--for (i = 0; i < count; i++)- if (chars->chars[i] == chr)- return;--if (count >= MAX_DIFF_CHARS)- {- chars->count = 255;- return;- }--chars->chars[count] = chr;-chars->count = count + 1;--if (last)- chars->last_count++;-}--static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, fast_forward_char_data *chars, int max_chars, sljit_u32 *rec_count)-{-/* Recursive function, which scans prefix literals. */-BOOL last, any, class, caseless;-int len, repeat, len_save, consumed = 0;-sljit_u32 chr; /* Any unicode character. */-sljit_u8 *bytes, *bytes_end, byte;-PCRE2_SPTR alternative, cc_save, oc;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8-PCRE2_UCHAR othercase[4];-#elif defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16-PCRE2_UCHAR othercase[2];-#else-PCRE2_UCHAR othercase[1];-#endif--repeat = 1;-while (TRUE)- {- if (*rec_count == 0)- return 0;- (*rec_count)--;-- last = TRUE;- any = FALSE;- class = FALSE;- caseless = FALSE;-- switch (*cc)- {- case OP_CHARI:- caseless = TRUE;- /* Fall through */- case OP_CHAR:- last = FALSE;- cc++;- break;-- 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;-- case OP_ASSERT:- case OP_ASSERT_NOT:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT:- case OP_ASSERT_NA:- case OP_ASSERTBACK_NA:- cc = bracketend(cc);- continue;-- case OP_PLUSI:- case OP_MINPLUSI:- case OP_POSPLUSI:- caseless = TRUE;- /* Fall through */- case OP_PLUS:- case OP_MINPLUS:- case OP_POSPLUS:- cc++;- break;-- case OP_EXACTI:- caseless = TRUE;- /* Fall through */- case OP_EXACT:- repeat = GET2(cc, 1);- last = FALSE;- cc += 1 + IMM2_SIZE;- break;-- case OP_QUERYI:- case OP_MINQUERYI:- case OP_POSQUERYI:- caseless = TRUE;- /* Fall through */- case OP_QUERY:- case OP_MINQUERY:- case OP_POSQUERY:- len = 1;- cc++;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);-#endif- max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count);- if (max_chars == 0)- return consumed;- last = FALSE;- break;-- case OP_KET:- cc += 1 + LINK_SIZE;- continue;-- case OP_ALT:- cc += GET(cc, 1);- continue;-- case OP_ONCE:- case OP_BRA:- case OP_BRAPOS:- case OP_CBRA:- case OP_CBRAPOS:- alternative = cc + GET(cc, 1);- while (*alternative == OP_ALT)- {- max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, max_chars, rec_count);- if (max_chars == 0)- return consumed;- alternative += GET(alternative, 1);- }-- if (*cc == OP_CBRA || *cc == OP_CBRAPOS)- cc += IMM2_SIZE;- cc += 1 + LINK_SIZE;- continue;-- case OP_CLASS:-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8- if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE))- return consumed;-#endif- class = TRUE;- break;-- case OP_NCLASS:-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf) return consumed;-#endif- class = TRUE;- break;--#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8- case OP_XCLASS:-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf) return consumed;-#endif- any = TRUE;- cc += GET(cc, 1);- break;-#endif-- case OP_DIGIT:-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8- if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE))- return consumed;-#endif- any = TRUE;- cc++;- break;-- case OP_WHITESPACE:-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8- if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE))- return consumed;-#endif- any = TRUE;- cc++;- break;-- case OP_WORDCHAR:-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8- if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE))- return consumed;-#endif- any = TRUE;- cc++;- break;-- case OP_NOT:- case OP_NOTI:- cc++;- /* Fall through. */- case OP_NOT_DIGIT:- case OP_NOT_WHITESPACE:- case OP_NOT_WORDCHAR:- case OP_ANY:- case OP_ALLANY:-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf) return consumed;-#endif- any = TRUE;- cc++;- break;--#ifdef SUPPORT_UNICODE- case OP_NOTPROP:- case OP_PROP:-#if PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf) return consumed;-#endif- any = TRUE;- cc += 1 + 2;- break;-#endif-- case OP_TYPEEXACT:- repeat = GET2(cc, 1);- cc += 1 + IMM2_SIZE;- continue;-- case OP_NOTEXACT:- case OP_NOTEXACTI:-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf) return consumed;-#endif- any = TRUE;- repeat = GET2(cc, 1);- cc += 1 + IMM2_SIZE + 1;- break;-- default:- return consumed;- }-- if (any)- {- do- {- chars->count = 255;-- consumed++;- if (--max_chars == 0)- return consumed;- chars++;- }- while (--repeat > 0);-- repeat = 1;- continue;- }-- if (class)- {- bytes = (sljit_u8*) (cc + 1);- cc += 1 + 32 / sizeof(PCRE2_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- {- if (bytes[31] & 0x80)- chars->count = 255;- else if (chars->count != 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, TRUE);- byte >>= 1;- chr++;- }- while (byte != 0);- chr = (chr + 7) & ~7;- }- }- while (chars->count != 255 && bytes < bytes_end);- bytes = bytes_end - 32;- }-- consumed++;- if (--max_chars == 0)- return consumed;- 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;- }-- len = 1;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);-#endif-- if (caseless && char_has_othercase(common, cc))- {-#ifdef SUPPORT_UNICODE- if (common->utf)- {- GETCHAR(chr, cc);- if ((int)PRIV(ord2utf)(char_othercase(common, chr), othercase) != len)- return consumed;- }- else-#endif- {- chr = *cc;-#ifdef SUPPORT_UNICODE- if (common->ucp && chr > 127)- othercase[0] = UCD_OTHERCASE(chr);- else-#endif- othercase[0] = TABLE_GET(chr, common->fcc, chr);- }- }- else- {- caseless = FALSE;- othercase[0] = 0; /* Stops compiler warning - PH */- }-- len_save = len;- cc_save = cc;- while (TRUE)- {- oc = othercase;- do- {- len--;- consumed++;-- chr = *cc;- add_prefix_char(*cc, chars, len == 0);-- if (caseless)- add_prefix_char(*oc, chars, len == 0);-- if (--max_chars == 0)- return consumed;- chars++;- cc++;- oc++;- }- while (len > 0);-- if (--repeat == 0)- break;-- len = len_save;- cc = cc_save;- }-- repeat = 1;- if (last)- return consumed;- }-}--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-static void jumpto_if_not_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg, struct sljit_label *label)-{-#if PCRE2_CODE_UNIT_WIDTH == 8-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);-CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0x80, label);-#elif PCRE2_CODE_UNIT_WIDTH == 16-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);-CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00, label);-#else-#error "Unknown code width"-#endif-}-#endif--#include "pcre2_jit_simd_inc.h"--#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD--static BOOL check_fast_forward_char_pair_simd(compiler_common *common, fast_forward_char_data *chars, int max)-{- sljit_s32 i, j, max_i = 0, max_j = 0;- sljit_u32 max_pri = 0;- PCRE2_UCHAR a1, a2, a_pri, b1, b2, b_pri;-- for (i = max - 1; i >= 1; i--)- {- if (chars[i].last_count > 2)- {- a1 = chars[i].chars[0];- a2 = chars[i].chars[1];- a_pri = chars[i].last_count;-- j = i - max_fast_forward_char_pair_offset();- if (j < 0)- j = 0;-- while (j < i)- {- b_pri = chars[j].last_count;- if (b_pri > 2 && a_pri + b_pri >= max_pri)- {- b1 = chars[j].chars[0];- b2 = chars[j].chars[1];-- if (a1 != b1 && a1 != b2 && a2 != b1 && a2 != b2)- {- max_pri = a_pri + b_pri;- max_i = i;- max_j = j;- }- }- j++;- }- }- }--if (max_pri == 0)- return FALSE;--fast_forward_char_pair_simd(common, max_i, chars[max_i].chars[0], chars[max_i].chars[1], max_j, chars[max_j].chars[0], chars[max_j].chars[1]);-return TRUE;-}--#endif /* JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD */--static void fast_forward_first_char2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)-{-DEFINE_COMPILER;-struct sljit_label *start;-struct sljit_jump *match;-struct sljit_jump *partial_quit;-PCRE2_UCHAR mask;-BOOL has_match_end = (common->match_end_ptr != 0);--SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE || offset == 0);--if (has_match_end)- OP1(SLJIT_MOV, TMP1, 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));--if (has_match_end)- {- OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);-- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offset + 1));- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_END, 0, TMP1, 0);- CMOV(SLJIT_GREATER, STR_END, TMP1, 0);- }--#ifdef JIT_HAS_FAST_FORWARD_CHAR_SIMD--if (JIT_HAS_FAST_FORWARD_CHAR_SIMD)- {- fast_forward_char_simd(common, char1, char2, offset);-- if (offset > 0)- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));-- if (has_match_end)- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);- return;- }--#endif--start = LABEL();--partial_quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-if (common->mode == PCRE2_JIT_COMPLETE)- add_jump(compiler, &common->failed_match, partial_quit);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--if (char1 == char2)- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char1, start);-else- {- mask = char1 ^ char2;- if (is_powerof2(mask))- {- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask, start);- }- else- {- match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1);- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char2, start);- JUMPHERE(match);- }- }--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-if (common->utf && offset > 0)- {- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-(offset + 1)));- jumpto_if_not_utf_char_start(compiler, TMP1, start);- }-#endif--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset + 1));--if (common->mode != PCRE2_JIT_COMPLETE)- JUMPHERE(partial_quit);--if (has_match_end)- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);-}--static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common)-{-DEFINE_COMPILER;-struct sljit_label *start;-struct sljit_jump *match;-fast_forward_char_data chars[MAX_N_CHARS];-sljit_s32 offset;-PCRE2_UCHAR mask;-PCRE2_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].count = 0;- chars[i].last_count = 0;- }--rec_count = 10000;-max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count);--if (max < 1)- return FALSE;--/* Convert last_count to priority. */-for (i = 0; i < max; i++)- {- SLJIT_ASSERT(chars[i].count > 0 && chars[i].last_count <= chars[i].count);-- if (chars[i].count == 1)- {- chars[i].last_count = (chars[i].last_count == 1) ? 7 : 5;- /* Simplifies algorithms later. */- chars[i].chars[1] = chars[i].chars[0];- }- else if (chars[i].count == 2)- {- SLJIT_ASSERT(chars[i].chars[0] != chars[i].chars[1]);-- if (is_powerof2(chars[i].chars[0] ^ chars[i].chars[1]))- chars[i].last_count = (chars[i].last_count == 2) ? 6 : 4;- else- chars[i].last_count = (chars[i].last_count == 2) ? 3 : 2;- }- else- chars[i].last_count = (chars[i].count == 255) ? 0 : 1;- }--#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD-if (JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD && check_fast_forward_char_pair_simd(common, chars, max))- return TRUE;-#endif--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].count < 255))- {- range_len = i - from;- range_right = i - 1;- }-- if (i < max && chars[i].count < 255)- {- SLJIT_ASSERT(chars[i].count > 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++)- {- SLJIT_ASSERT(chars[range_right - i].count > 0 && chars[range_right - i].count < 255);-- char_set = chars[range_right - i].chars;- char_set_end = char_set + chars[range_right - i].count;- do- {- if (update_table[(*char_set) & 0xff] > IN_UCHARS(i))- update_table[(*char_set) & 0xff] = IN_UCHARS(i);- char_set++;- }- while (char_set < char_set_end);- }- }--offset = -1;-/* Scan forward. */-for (i = 0; i < max; i++)- {- if (range_right == i)- continue;-- if (offset == -1)- {- if (chars[i].last_count >= 2)- offset = i;- }- else if (chars[offset].last_count < chars[i].last_count)- offset = i;- }--SLJIT_ASSERT(offset == -1 || (chars[offset].count >= 1 && chars[offset].count <= 2));--if (range_right < 0)- {- if (offset < 0)- return FALSE;- /* Works regardless the value is 1 or 2. */- fast_forward_first_char2(common, chars[offset].chars[0], chars[offset].chars[1], offset);- return TRUE;- }--SLJIT_ASSERT(range_right != offset);--if (common->match_end_ptr != 0)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);- OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);- OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));- add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_END, 0, TMP1, 0);- CMOV(SLJIT_GREATER, STR_END, TMP1, 0);- }-else- {- OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));- add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));- }--SLJIT_ASSERT(range_right >= 0);--if (!HAS_VIRTUAL_REGISTERS)- OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);--start = LABEL();-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));--#if PCRE2_CODE_UNIT_WIDTH == 8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));-#else-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);-#endif--if (!HAS_VIRTUAL_REGISTERS)- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);-else- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);-CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);--if (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 (chars[offset].count == 1)- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0], start);- else- {- mask = chars[offset].chars[0] ^ chars[offset].chars[1];- if (is_powerof2(mask))- {- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0] | mask, start);- }- else- {- match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0]);- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[1], start);- JUMPHERE(match);- }- }- }--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-if (common->utf && offset != 0)- {- if (offset < 0)- {- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- }- else- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));-- jumpto_if_not_utf_char_start(compiler, TMP1, start);-- 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));--if (common->match_end_ptr != 0)- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);-else- OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));-return TRUE;-}--static SLJIT_INLINE void fast_forward_first_char(compiler_common *common)-{-PCRE2_UCHAR first_char = (PCRE2_UCHAR)(common->re->first_codeunit);-PCRE2_UCHAR oc;--oc = first_char;-if ((common->re->flags & PCRE2_FIRSTCASELESS) != 0)- {- oc = TABLE_GET(first_char, common->fcc, first_char);-#if defined SUPPORT_UNICODE- if (first_char > 127 && (common->utf || common->ucp))- oc = UCD_OTHERCASE(first_char);-#endif- }--fast_forward_first_char2(common, first_char, oc, 0);-}--static SLJIT_INLINE void fast_forward_newline(compiler_common *common)-{-DEFINE_COMPILER;-struct sljit_label *loop;-struct sljit_jump *lastchar = NULL;-struct sljit_jump *firstchar;-struct sljit_jump *quit = NULL;-struct sljit_jump *foundcr = NULL;-struct sljit_jump *notfoundnl;-jump_list *newline = NULL;--if (common->match_end_ptr != 0)- {- OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);- OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);- }--if (common->nltype == NLTYPE_FIXED && common->newline > 255)- {-#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD- if (JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD && common->mode == PCRE2_JIT_COMPLETE)- {- if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));- }- else- {- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));- }- firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);-- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- OP2U(SLJIT_SUB | SLJIT_SET_Z, STR_PTR, 0, TMP1, 0);- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_NOT_EQUAL);-#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);-#endif- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);-- fast_forward_char_pair_simd(common, 1, common->newline & 0xff, common->newline & 0xff, 0, (common->newline >> 8) & 0xff, (common->newline >> 8) & 0xff);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));- }- else-#endif /* JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD */- {- lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);- if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));- }- else- {- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));- }- firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);-- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));- OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, STR_PTR, 0, TMP1, 0);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL);-#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);-#endif- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);-- loop = LABEL();- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 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));- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);- CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);-- JUMPHERE(quit);- JUMPHERE(lastchar);- }-- JUMPHERE(firstchar);-- if (common->match_end_ptr != 0)- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);- return;- }--if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));- }-else- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));--/* Example: match /^/ to \r\n from offset 1. */-firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);--if (common->nltype == NLTYPE_ANY)- move_back(common, NULL, FALSE);-else- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--loop = LABEL();-common->ff_newline_shortcut = loop;--#ifdef JIT_HAS_FAST_FORWARD_CHAR_SIMD-if (JIT_HAS_FAST_FORWARD_CHAR_SIMD && (common->nltype == NLTYPE_FIXED || common->nltype == NLTYPE_ANYCRLF))- {- if (common->nltype == NLTYPE_ANYCRLF)- {- fast_forward_char_simd(common, CHAR_CR, CHAR_LF, 0);- if (common->mode != PCRE2_JIT_COMPLETE)- lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- quit = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);- }- else- {- fast_forward_char_simd(common, common->newline, common->newline, 0);-- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- if (common->mode != PCRE2_JIT_COMPLETE)- {- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);- CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);- }- }- }-else-#endif /* JIT_HAS_FAST_FORWARD_CHAR_SIMD */- {- read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE);- lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);- if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)- foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);- check_newlinechar(common, common->nltype, &newline, FALSE);- set_jumps(newline, loop);- }--if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)- {- if (quit == NULL)- {- quit = JUMP(SLJIT_JUMP);- JUMPHERE(foundcr);- }-- notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NL);- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);-#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);-#endif- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);- JUMPHERE(notfoundnl);- JUMPHERE(quit);- }--if (lastchar)- JUMPHERE(lastchar);-JUMPHERE(firstchar);--if (common->match_end_ptr != 0)- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);-}--static BOOL optimize_class(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)-{-DEFINE_COMPILER;-const sljit_u8 *start_bits = common->re->start_bitmap;-struct sljit_label *start;-struct sljit_jump *partial_quit;-#if PCRE2_CODE_UNIT_WIDTH != 8-struct sljit_jump *found = NULL;-#endif-jump_list *matches = NULL;--if (common->match_end_ptr != 0)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);- OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_END, 0, TMP1, 0);- CMOV(SLJIT_GREATER, STR_END, TMP1, 0);- }--start = LABEL();--partial_quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-if (common->mode == PCRE2_JIT_COMPLETE)- add_jump(compiler, &common->failed_match, partial_quit);--OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--if (!optimize_class(common, start_bits, (start_bits[31] & 0x80) != 0, FALSE, &matches))- {-#if PCRE2_CODE_UNIT_WIDTH != 8- if ((start_bits[31] & 0x80) != 0)- found = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 255);- else- CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 255, start);-#elif defined SUPPORT_UNICODE- if (common->utf && is_char7_bitset(start_bits, FALSE))- CMPTO(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 127, start);-#endif- OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);- OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);- if (!HAS_VIRTUAL_REGISTERS)- {- OP2(SLJIT_SHL, TMP3, 0, SLJIT_IMM, 1, TMP2, 0);- OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP3, 0);- }- else- {- OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);- OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);- }- JUMPTO(SLJIT_ZERO, start);- }-else- set_jumps(matches, start);--#if PCRE2_CODE_UNIT_WIDTH != 8-if (found != NULL)- JUMPHERE(found);-#endif--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--if (common->mode != PCRE2_JIT_COMPLETE)- JUMPHERE(partial_quit);--if (common->match_end_ptr != 0)- OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0);-}--static SLJIT_INLINE jump_list *search_requested_char(compiler_common *common, PCRE2_UCHAR req_char, BOOL caseless, BOOL has_firstchar)-{-DEFINE_COMPILER;-struct sljit_label *loop;-struct sljit_jump *toolong;-struct sljit_jump *already_found;-struct sljit_jump *found;-struct sljit_jump *found_oc = NULL;-jump_list *not_found = NULL;-sljit_u32 oc, bit;--SLJIT_ASSERT(common->req_char_ptr != 0);-OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(REQ_CU_MAX) * 100);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr);-toolong = CMP(SLJIT_LESS, TMP2, 0, STR_END, 0);-already_found = CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0);--if (has_firstchar)- OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-else- OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);--oc = req_char;-if (caseless)- {- oc = TABLE_GET(req_char, common->fcc, req_char);-#if defined SUPPORT_UNICODE- if (req_char > 127 && (common->utf || common->ucp))- oc = UCD_OTHERCASE(req_char);-#endif- }--#ifdef JIT_HAS_FAST_REQUESTED_CHAR_SIMD-if (JIT_HAS_FAST_REQUESTED_CHAR_SIMD)- {- not_found = fast_requested_char_simd(common, req_char, oc);- }-else-#endif- {- loop = LABEL();- add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));-- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0);-- if (req_char == oc)- found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char);- else- {- bit = req_char ^ oc;- if (is_powerof2(bit))- {- OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);- found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit);- }- else- {- found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char);- found_oc = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, oc);- }- }- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));- JUMPTO(SLJIT_JUMP, loop);-- JUMPHERE(found);- if (found_oc)- JUMPHERE(found_oc);- }--OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, TMP1, 0);--JUMPHERE(already_found);-JUMPHERE(toolong);-return not_found;-}--static void do_revertframes(compiler_common *common)-{-DEFINE_COMPILER;-struct sljit_jump *jump;-struct sljit_label *mainloop;--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);-GET_LOCAL_BASE(TMP1, 0, 0);--/* Drop frames until we reach STACK_TOP. */-mainloop = LABEL();-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);-if (HAS_VIRTUAL_REGISTERS)- {- 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));- }-else- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));- OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(3 * sizeof(sljit_sw)));- OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);- GET_LOCAL_BASE(TMP1, 0, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP3, 0);- }-JUMPTO(SLJIT_JUMP, mainloop);--JUMPHERE(jump);-jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0);-/* End of reverting values. */-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);--JUMPHERE(jump);-OP2(SLJIT_SUB, TMP2, 0, SLJIT_IMM, 0, TMP2, 0);-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);-if (HAS_VIRTUAL_REGISTERS)- {- 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));- }-else- {- OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));- OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP3, 0);- }-JUMPTO(SLJIT_JUMP, mainloop);-}--static void check_wordboundary(compiler_common *common)-{-DEFINE_COMPILER;-struct sljit_jump *skipread;-jump_list *skipread_list = NULL;-#ifdef SUPPORT_UNICODE-struct sljit_label *valid_utf;-jump_list *invalid_utf1 = NULL;-#endif /* SUPPORT_UNICODE */-jump_list *invalid_utf2 = NULL;-#if PCRE2_CODE_UNIT_WIDTH != 8 || defined SUPPORT_UNICODE-struct sljit_jump *jump;-#endif /* PCRE2_CODE_UNIT_WIDTH != 8 || SUPPORT_UNICODE */--SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);--sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);-/* Get type of the previous char, and put it to TMP3. */-OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);-OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));-OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);-skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);--#ifdef SUPPORT_UNICODE-if (common->invalid_utf)- {- peek_char_back(common, READ_CHAR_MAX, &invalid_utf1);-- if (common->mode != PCRE2_JIT_COMPLETE)- {- OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);- OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);- move_back(common, NULL, TRUE);- check_start_used_ptr(common);- OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);- OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);- }- }-else-#endif /* SUPPORT_UNICODE */- {- if (common->mode == PCRE2_JIT_COMPLETE)- peek_char_back(common, READ_CHAR_MAX, NULL);- else- {- move_back(common, NULL, TRUE);- check_start_used_ptr(common);- read_char(common, 0, READ_CHAR_MAX, NULL, READ_CHAR_UPDATE_STR_PTR);- }- }--/* Testing char type. */-#ifdef SUPPORT_UNICODE-if (common->ucp)- {- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);- jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);- add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);- JUMPHERE(jump);- OP1(SLJIT_MOV, TMP3, 0, TMP2, 0);- }-else-#endif /* SUPPORT_UNICODE */- {-#if PCRE2_CODE_UNIT_WIDTH != 8- jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);-#elif defined SUPPORT_UNICODE- /* Here TMP3 has already been zeroed. */- jump = NULL;- if (common->utf)- jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */- 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, TMP3, 0, TMP1, 0, SLJIT_IMM, 1);-#if PCRE2_CODE_UNIT_WIDTH != 8- JUMPHERE(jump);-#elif defined SUPPORT_UNICODE- if (jump != NULL)- JUMPHERE(jump);-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */- }-JUMPHERE(skipread);--OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);-check_str_end(common, &skipread_list);-peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, &invalid_utf2);--/* Testing char type. This is a code duplication. */-#ifdef SUPPORT_UNICODE--valid_utf = LABEL();--if (common->ucp)- {- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);- jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);- add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);- JUMPHERE(jump);- }-else-#endif /* SUPPORT_UNICODE */- {-#if PCRE2_CODE_UNIT_WIDTH != 8- /* TMP2 may be destroyed by peek_char. */- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);- jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);-#elif defined SUPPORT_UNICODE- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);- jump = NULL;- if (common->utf)- jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);-#endif- 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);-#if PCRE2_CODE_UNIT_WIDTH != 8- JUMPHERE(jump);-#elif defined SUPPORT_UNICODE- if (jump != NULL)- JUMPHERE(jump);-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */- }-set_jumps(skipread_list, LABEL());--OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);-OP2(SLJIT_XOR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, TMP3, 0);-OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);--#ifdef SUPPORT_UNICODE-if (common->invalid_utf)- {- set_jumps(invalid_utf1, LABEL());-- peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, NULL);- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR, valid_utf);-- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, -1);- OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);-- set_jumps(invalid_utf2, LABEL());- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);- OP1(SLJIT_MOV, TMP2, 0, TMP3, 0);- OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);- }-#endif /* SUPPORT_UNICODE */-}--static BOOL optimize_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)-{-/* May destroy TMP1. */-DEFINE_COMPILER;-int ranges[MAX_CLASS_RANGE_SIZE];-sljit_u8 bit, cbit, all;-int i, byte, length = 0;--bit = bits[0] & 0x1;-/* All bits will be zero or one (since bit is zero or one). */-all = -bit;--for (i = 0; i < 256; )- {- byte = i >> 3;- if ((i & 0x7) == 0 && bits[byte] == all)- i += 8;- else- {- cbit = (bits[byte] >> (i & 0x7)) & 0x1;- if (cbit != bit)- {- if (length >= MAX_CLASS_RANGE_SIZE)- return FALSE;- ranges[length] = i;- length++;- bit = cbit;- all = -cbit;- }- i++;- }- }--if (((bit == 0) && nclass) || ((bit == 1) && !nclass))- {- if (length >= MAX_CLASS_RANGE_SIZE)- return FALSE;- ranges[length] = 256;- length++;- }--if (length < 0 || length > 4)- return FALSE;--bit = bits[0] & 0x1;-if (invert) bit ^= 0x1;--/* No character is accepted. */-if (length == 0 && bit == 0)- add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));--switch(length)- {- case 0:- /* When bit != 0, all characters are accepted. */- return TRUE;-- case 1:- add_jump(compiler, backtracks, CMP(bit == 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));- return TRUE;-- case 2:- if (ranges[0] + 1 != ranges[1])- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);- add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));- }- else- add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));- return TRUE;-- case 3:- if (bit != 0)- {- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));- if (ranges[0] + 1 != ranges[1])- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));- }- else- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));- return TRUE;- }-- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[0]));- if (ranges[1] + 1 != ranges[2])- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1]);- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));- }- else- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1]));- return TRUE;-- case 4:- if ((ranges[1] - ranges[0]) == (ranges[3] - ranges[2])- && (ranges[0] | (ranges[2] - ranges[0])) == ranges[2]- && (ranges[1] & (ranges[2] - ranges[0])) == 0- && is_powerof2(ranges[2] - ranges[0]))- {- SLJIT_ASSERT((ranges[0] & (ranges[2] - ranges[0])) == 0 && (ranges[2] & ranges[3] & (ranges[2] - ranges[0])) != 0);- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[0]);- if (ranges[2] + 1 != ranges[3])- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]);- add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));- }- else- add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));- return TRUE;- }-- if (bit != 0)- {- i = 0;- if (ranges[0] + 1 != ranges[1])- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));- i = ranges[0];- }- else- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));-- if (ranges[2] + 1 != ranges[3])- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - i);- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));- }- else- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2] - i));- return TRUE;- }-- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[0]));- if (ranges[1] + 1 != ranges[2])- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]);- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));- }- else- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));- return TRUE;-- default:- SLJIT_UNREACHABLE();- return FALSE;- }-}--static BOOL optimize_class_chars(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)-{-/* May destroy TMP1. */-DEFINE_COMPILER;-uint16_t char_list[MAX_CLASS_CHARS_SIZE];-uint8_t byte;-sljit_s32 type;-int i, j, k, len, c;--if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV))- return FALSE;--len = 0;--for (i = 0; i < 32; i++)- {- byte = bits[i];-- if (nclass)- byte = ~byte;-- j = 0;- while (byte != 0)- {- if (byte & 0x1)- {- c = i * 8 + j;-- k = len;-- if ((c & 0x20) != 0)- {- for (k = 0; k < len; k++)- if (char_list[k] == c - 0x20)- {- char_list[k] |= 0x120;- break;- }- }-- if (k == len)- {- if (len >= MAX_CLASS_CHARS_SIZE)- return FALSE;-- char_list[len++] = (uint16_t) c;- }- }-- byte >>= 1;- j++;- }- }--if (len == 0) return FALSE; /* Should never occur, but stops analyzers complaining. */--i = 0;-j = 0;--if (char_list[0] == 0)- {- i++;- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_ZERO);- }-else- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);--while (i < len)- {- if ((char_list[i] & 0x100) != 0)- j++;- else- {- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, char_list[i]);- CMOV(SLJIT_ZERO, TMP2, TMP1, 0);- }- i++;- }--if (j != 0)- {- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x20);-- for (i = 0; i < len; i++)- if ((char_list[i] & 0x100) != 0)- {- j--;- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, char_list[i] & 0xff);- CMOV(SLJIT_ZERO, TMP2, TMP1, 0);- }- }--if (invert)- nclass = !nclass;--type = nclass ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;-add_jump(compiler, backtracks, CMP(type, TMP2, 0, SLJIT_IMM, 0));-return TRUE;-}--static BOOL optimize_class(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)-{-/* May destroy TMP1. */-if (optimize_class_ranges(common, bits, nclass, invert, backtracks))- return TRUE;-return optimize_class_chars(common, bits, nclass, invert, backtracks);-}--static void check_anynewline(compiler_common *common)-{-/* Check whether TMP1 contains a newline character. TMP2 destroyed. */-DEFINE_COMPILER;--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);-OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);-OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32-#if PCRE2_CODE_UNIT_WIDTH == 8-if (common->utf)- {-#endif- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);-#if PCRE2_CODE_UNIT_WIDTH == 8- }-#endif-#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */-OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);-OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void check_hspace(compiler_common *common)-{-/* Check whether TMP1 contains a newline character. TMP2 destroyed. */-DEFINE_COMPILER;--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x09);-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);-OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x20);-OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);-OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0xa0);-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32-#if PCRE2_CODE_UNIT_WIDTH == 8-if (common->utf)- {-#endif- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x1680);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);-#if PCRE2_CODE_UNIT_WIDTH == 8- }-#endif-#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */-OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);--OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void check_vspace(compiler_common *common)-{-/* Check whether TMP1 contains a newline character. TMP2 destroyed. */-DEFINE_COMPILER;--sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);--OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);-OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);-OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32-#if PCRE2_CODE_UNIT_WIDTH == 8-if (common->utf)- {-#endif- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);-#if PCRE2_CODE_UNIT_WIDTH == 8- }-#endif-#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */-OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);--OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);-}--static void do_casefulcmp(compiler_common *common)-{-DEFINE_COMPILER;-struct sljit_jump *jump;-struct sljit_label *label;-int char1_reg;-int char2_reg;--if (HAS_VIRTUAL_REGISTERS)- {- char1_reg = STR_END;- char2_reg = STACK_TOP;- }-else- {- char1_reg = TMP3;- char2_reg = RETURN_ADDR;- }--sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);--if (char1_reg == STR_END)- {- OP1(SLJIT_MOV, TMP3, 0, char1_reg, 0);- OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0);- }--if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)- {- label = LABEL();- sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));- sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));- jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);- OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));- JUMPTO(SLJIT_NOT_ZERO, label);-- JUMPHERE(jump);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);- }-else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-- label = LABEL();- sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));- sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));- jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);- OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));- JUMPTO(SLJIT_NOT_ZERO, label);-- JUMPHERE(jump);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- }-else- {- label = LABEL();- OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);- OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);- OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));- JUMPTO(SLJIT_NOT_ZERO, label);-- JUMPHERE(jump);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);- }--if (char1_reg == STR_END)- {- OP1(SLJIT_MOV, char1_reg, 0, TMP3, 0);- OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0);- }--OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);-}--static void do_caselesscmp(compiler_common *common)-{-DEFINE_COMPILER;-struct sljit_jump *jump;-struct sljit_label *label;-int char1_reg = STR_END;-int char2_reg;-int lcc_table;-int opt_type = 0;--if (HAS_VIRTUAL_REGISTERS)- {- char2_reg = STACK_TOP;- lcc_table = STACK_LIMIT;- }-else- {- char2_reg = RETURN_ADDR;- lcc_table = TMP3;- }--if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)- opt_type = 1;-else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)- opt_type = 2;--sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);--OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0);--if (char2_reg == STACK_TOP)- {- OP1(SLJIT_MOV, TMP3, 0, char2_reg, 0);- OP1(SLJIT_MOV, RETURN_ADDR, 0, lcc_table, 0);- }--OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc);--if (opt_type == 1)- {- label = LABEL();- sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));- sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));- }-else if (opt_type == 2)- {- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-- label = LABEL();- sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));- sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));- }-else- {- label = LABEL();- OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);- OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));- }--#if PCRE2_CODE_UNIT_WIDTH != 8-jump = CMP(SLJIT_GREATER, char1_reg, 0, SLJIT_IMM, 255);-#endif-OP1(SLJIT_MOV_U8, char1_reg, 0, SLJIT_MEM2(lcc_table, char1_reg), 0);-#if PCRE2_CODE_UNIT_WIDTH != 8-JUMPHERE(jump);-jump = CMP(SLJIT_GREATER, char2_reg, 0, SLJIT_IMM, 255);-#endif-OP1(SLJIT_MOV_U8, char2_reg, 0, SLJIT_MEM2(lcc_table, char2_reg), 0);-#if PCRE2_CODE_UNIT_WIDTH != 8-JUMPHERE(jump);-#endif--if (opt_type == 0)- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);-OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));-JUMPTO(SLJIT_NOT_ZERO, label);--JUMPHERE(jump);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);--if (opt_type == 2)- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));--if (char2_reg == STACK_TOP)- {- OP1(SLJIT_MOV, char2_reg, 0, TMP3, 0);- OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0);- }--OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);-OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);-}--static PCRE2_SPTR byte_sequence_compare(compiler_common *common, BOOL caseless, PCRE2_SPTR cc,- compare_context *context, jump_list **backtracks)-{-DEFINE_COMPILER;-unsigned int othercasebit = 0;-PCRE2_SPTR othercasechar = NULL;-#ifdef SUPPORT_UNICODE-int utflength;-#endif--if (caseless && char_has_othercase(common, cc))- {- othercasebit = char_get_othercase_bit(common, cc);- SLJIT_ASSERT(othercasebit);- /* Extracting bit difference info. */-#if PCRE2_CODE_UNIT_WIDTH == 8- othercasechar = cc + (othercasebit >> 8);- othercasebit &= 0xff;-#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32- /* Note that this code only handles characters in the BMP. If there- ever are characters outside the BMP whose othercase differs in only one- bit from itself (there currently are none), this code will need to be- revised for PCRE2_CODE_UNIT_WIDTH == 32. */- othercasechar = cc + (othercasebit >> 9);- if ((othercasebit & 0x100) != 0)- othercasebit = (othercasebit & 0xff) << 8;- else- othercasebit &= 0xff;-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */- }--if (context->sourcereg == -1)- {-#if PCRE2_CODE_UNIT_WIDTH == 8-#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED- if (context->length >= 4)- OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);- else if (context->length >= 2)- OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);- else-#endif- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);-#elif PCRE2_CODE_UNIT_WIDTH == 16-#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED- if (context->length >= 4)- 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);-#elif PCRE2_CODE_UNIT_WIDTH == 32- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */- context->sourcereg = TMP2;- }--#ifdef SUPPORT_UNICODE-utflength = 1;-if (common->utf && HAS_EXTRALEN(*cc))- utflength += GET_EXTRALEN(*cc);--do- {-#endif-- context->length -= IN_UCHARS(1);-#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)-- /* Unaligned read is supported. */- if (othercasebit != 0 && othercasechar == cc)- {- context->c.asuchars[context->ucharptr] = *cc | othercasebit;- context->oc.asuchars[context->ucharptr] = othercasebit;- }- else- {- context->c.asuchars[context->ucharptr] = *cc;- context->oc.asuchars[context->ucharptr] = 0;- }- context->ucharptr++;--#if PCRE2_CODE_UNIT_WIDTH == 8- if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1))-#else- if (context->ucharptr >= 2 || context->length == 0)-#endif- {- if (context->length >= 4)- OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);- else if (context->length >= 2)- OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);-#if PCRE2_CODE_UNIT_WIDTH == 8- else if (context->length >= 1)- OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */- context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;-- switch(context->ucharptr)- {- case 4 / sizeof(PCRE2_UCHAR):- if (context->oc.asint != 0)- OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));- break;-- case 2 / sizeof(PCRE2_UCHAR):- if (context->oc.asushort != 0)- OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));- break;--#if PCRE2_CODE_UNIT_WIDTH == 8- case 1:- if (context->oc.asbyte != 0)- OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));- break;-#endif-- default:- SLJIT_UNREACHABLE();- break;- }- context->ucharptr = 0;- }--#else-- /* Unaligned read is unsupported or in 32 bit mode. */- if (context->length >= 1)- OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);-- context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;-- if (othercasebit != 0 && othercasechar == cc)- {- OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));- }- else- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));--#endif-- cc++;-#ifdef SUPPORT_UNICODE- utflength--;- }-while (utflength > 0);-#endif--return cc;-}--#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8--#define SET_TYPE_OFFSET(value) \- if ((value) != typeoffset) \- { \- if ((value) < typeoffset) \- OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \- else \- OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \- } \- typeoffset = (value);--#define SET_CHAR_OFFSET(value) \- if ((value) != charoffset) \- { \- if ((value) < charoffset) \- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(charoffset - (value))); \- else \- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)((value) - charoffset)); \- } \- charoffset = (value);--static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr);--#ifdef SUPPORT_UNICODE-#define XCLASS_SAVE_CHAR 0x001-#define XCLASS_CHAR_SAVED 0x002-#define XCLASS_HAS_TYPE 0x004-#define XCLASS_HAS_SCRIPT 0x008-#define XCLASS_HAS_SCRIPT_EXTENSION 0x010-#define XCLASS_HAS_BOOL 0x020-#define XCLASS_HAS_BIDICL 0x040-#define XCLASS_NEEDS_UCD (XCLASS_HAS_TYPE | XCLASS_HAS_SCRIPT | XCLASS_HAS_SCRIPT_EXTENSION | XCLASS_HAS_BOOL | XCLASS_HAS_BIDICL)-#define XCLASS_SCRIPT_EXTENSION_NOTPROP 0x080-#define XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR 0x100-#define XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0 0x200--#endif /* SUPPORT_UNICODE */--static void compile_xclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)-{-DEFINE_COMPILER;-jump_list *found = NULL;-jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks;-sljit_uw c, charoffset, max = 256, min = READ_CHAR_MAX;-struct sljit_jump *jump = NULL;-PCRE2_SPTR ccbegin;-int compares, invertcmp, numberofcmps;-#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)-BOOL utf = common->utf;-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */--#ifdef SUPPORT_UNICODE-sljit_u32 unicode_status = 0;-int typereg = TMP1;-const sljit_u32 *other_cases;-sljit_uw typeoffset;-#endif /* SUPPORT_UNICODE */--/* Scanning the necessary info. */-cc++;-ccbegin = cc;-compares = 0;--if (cc[-1] & XCL_MAP)- {- min = 0;- cc += 32 / sizeof(PCRE2_UCHAR);- }--while (*cc != XCL_END)- {- compares++;- if (*cc == XCL_SINGLE)- {- cc ++;- GETCHARINCTEST(c, cc);- if (c > max) max = c;- if (c < min) min = c;-#ifdef SUPPORT_UNICODE- unicode_status |= XCLASS_SAVE_CHAR;-#endif /* SUPPORT_UNICODE */- }- else if (*cc == XCL_RANGE)- {- cc ++;- GETCHARINCTEST(c, cc);- if (c < min) min = c;- GETCHARINCTEST(c, cc);- if (c > max) max = c;-#ifdef SUPPORT_UNICODE- unicode_status |= XCLASS_SAVE_CHAR;-#endif /* SUPPORT_UNICODE */- }-#ifdef SUPPORT_UNICODE- else- {- SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);- cc++;- if (*cc == PT_CLIST && cc[-1] == XCL_PROP)- {- other_cases = PRIV(ucd_caseless_sets) + cc[1];- while (*other_cases != NOTACHAR)- {- if (*other_cases > max) max = *other_cases;- if (*other_cases < min) min = *other_cases;- other_cases++;- }- }- else- {- max = READ_CHAR_MAX;- min = 0;- }-- 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:- case PT_GC:- case PT_PC:- case PT_ALNUM:- unicode_status |= XCLASS_HAS_TYPE;- break;-- case PT_SCX:- unicode_status |= XCLASS_HAS_SCRIPT_EXTENSION;- if (cc[-1] == XCL_NOTPROP)- {- unicode_status |= XCLASS_SCRIPT_EXTENSION_NOTPROP;- break;- }- compares++;- /* Fall through */-- case PT_SC:- unicode_status |= XCLASS_HAS_SCRIPT;- break;-- case PT_SPACE:- case PT_PXSPACE:- case PT_WORD:- case PT_PXGRAPH:- case PT_PXPRINT:- case PT_PXPUNCT:- unicode_status |= XCLASS_SAVE_CHAR | XCLASS_HAS_TYPE;- break;-- case PT_CLIST:- case PT_UCNC:- unicode_status |= XCLASS_SAVE_CHAR;- break;-- case PT_BOOL:- unicode_status |= XCLASS_HAS_BOOL;- break;-- case PT_BIDICL:- unicode_status |= XCLASS_HAS_BIDICL;- break;-- default:- SLJIT_UNREACHABLE();- break;- }- cc += 2;- }-#endif /* SUPPORT_UNICODE */- }-SLJIT_ASSERT(compares > 0);--/* We are not necessary in utf mode even in 8 bit mode. */-cc = ccbegin;-if ((cc[-1] & XCL_NOT) != 0)- read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR);-else- {-#ifdef SUPPORT_UNICODE- read_char(common, min, max, (unicode_status & XCLASS_NEEDS_UCD) ? backtracks : NULL, 0);-#else /* !SUPPORT_UNICODE */- read_char(common, min, max, NULL, 0);-#endif /* SUPPORT_UNICODE */- }--if ((cc[-1] & XCL_HASPROP) == 0)- {- if ((cc[-1] & XCL_MAP) != 0)- {- jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);- if (!optimize_class(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_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);- OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);- OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);- add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO));- }-- add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));- JUMPHERE(jump);-- cc += 32 / sizeof(PCRE2_UCHAR);- }- else- {- OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, min);- add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, max - min));- }- }-else if ((cc[-1] & XCL_MAP) != 0)- {- OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);-#ifdef SUPPORT_UNICODE- unicode_status |= XCLASS_CHAR_SAVED;-#endif /* SUPPORT_UNICODE */- if (!optimize_class(common, (const sljit_u8 *)cc, FALSE, TRUE, list))- {-#if PCRE2_CODE_UNIT_WIDTH == 8- jump = NULL;- if (common->utf)-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */- jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);-- OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);- OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);- OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);- OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);- add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO));--#if PCRE2_CODE_UNIT_WIDTH == 8- if (common->utf)-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */- JUMPHERE(jump);- }-- OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);- cc += 32 / sizeof(PCRE2_UCHAR);- }--#ifdef SUPPORT_UNICODE-if (unicode_status & XCLASS_NEEDS_UCD)- {- if ((unicode_status & (XCLASS_SAVE_CHAR | XCLASS_CHAR_SAVED)) == XCLASS_SAVE_CHAR)- OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);--#if PCRE2_CODE_UNIT_WIDTH == 32- if (!common->utf)- {- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);- JUMPHERE(jump);- }-#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */-- OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);- OP1(SLJIT_MOV_U16, 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);- OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3);- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);-- ccbegin = cc;-- if (unicode_status & XCLASS_HAS_BIDICL)- {- OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass));- OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BIDICLASS_SHIFT);-- while (*cc != XCL_END)- {- 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_BIDICL)- {- 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;- }- }-- cc = ccbegin;- }-- if (unicode_status & XCLASS_HAS_BOOL)- {- OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, bprops));- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BPROPS_MASK);- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);-- while (*cc != XCL_END)- {- 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_BOOL)- {- compares--;- invertcmp = (compares == 0 && list != backtracks);- if (cc[-1] == XCL_NOTPROP)- invertcmp ^= 0x1;-- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_boolprop_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)1 << (cc[1] & 0x1f));- add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp));- }- cc += 2;- }- }-- cc = ccbegin;- }-- if (unicode_status & XCLASS_HAS_SCRIPT)- {- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));-- while (*cc != XCL_END)- {- 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++;- switch (*cc)- {- case PT_SCX:- if (cc[-1] == XCL_NOTPROP)- break;- /* Fall through */-- case PT_SC:- compares--;- invertcmp = (compares == 0 && list != backtracks);- if (cc[-1] == XCL_NOTPROP)- invertcmp ^= 0x1;-- add_jump(compiler, compares > 0 ? list : backtracks, CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]));- }- cc += 2;- }- }-- cc = ccbegin;- }-- if (unicode_status & XCLASS_HAS_SCRIPT_EXTENSION)- {- OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass));- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_SCRIPTX_MASK);- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);-- if (unicode_status & XCLASS_SCRIPT_EXTENSION_NOTPROP)- {- if (unicode_status & XCLASS_HAS_TYPE)- {- if (unicode_status & XCLASS_SAVE_CHAR)- {- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP2, 0);- unicode_status |= XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0;- }- else- {- OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0);- unicode_status |= XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR;- }- }- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));- }-- while (*cc != XCL_END)- {- 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_SCX)- {- compares--;- invertcmp = (compares == 0 && list != backtracks);-- jump = NULL;- if (cc[-1] == XCL_NOTPROP)- {- jump = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, (int)cc[1]);- if (invertcmp)- {- add_jump(compiler, backtracks, jump);- jump = NULL;- }- invertcmp ^= 0x1;- }-- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_script_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)1 << (cc[1] & 0x1f));- add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp));-- if (jump != NULL)- JUMPHERE(jump);- }- cc += 2;- }- }-- if (unicode_status & XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);- else if (unicode_status & XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR)- OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0);- cc = ccbegin;- }-- if (unicode_status & XCLASS_SAVE_CHAR)- OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);-- if (unicode_status & XCLASS_HAS_TYPE)- {- if (unicode_status & XCLASS_SAVE_CHAR)- typereg = RETURN_ADDR;-- OP1(SLJIT_MOV_U8, typereg, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));- }- }-#endif /* SUPPORT_UNICODE */--/* Generating code. */-charoffset = 0;-numberofcmps = 0;-#ifdef SUPPORT_UNICODE-typeoffset = 0;-#endif /* SUPPORT_UNICODE */--while (*cc != XCL_END)- {- compares--;- invertcmp = (compares == 0 && list != backtracks);- jump = NULL;-- if (*cc == XCL_SINGLE)- {- cc ++;- GETCHARINCTEST(c, cc);-- if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))- {- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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)- {- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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;- }- else- {- jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));- numberofcmps = 0;- }- }- else if (*cc == XCL_RANGE)- {- cc ++;- GETCHARINCTEST(c, cc);- SET_CHAR_OFFSET(c);- GETCHARINCTEST(c, cc);-- if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))- {- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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)- {- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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;- }- else- {- jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));- numberofcmps = 0;- }- }-#ifdef SUPPORT_UNICODE- else- {- SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);- if (*cc == XCL_NOTPROP)- invertcmp ^= 0x1;- cc++;- switch(*cc)- {- case PT_ANY:- if (!invertcmp)- jump = JUMP(SLJIT_JUMP);- break;-- case PT_LAMP:- OP2U(SLJIT_SUB | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);- OP2U(SLJIT_SUB | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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;-- case PT_GC:- c = PRIV(ucp_typerange)[(int)cc[1] * 2];- SET_TYPE_OFFSET(c);- jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c);- break;-- case PT_PC:- jump = CMP(SLJIT_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);- break;-- case PT_SC:- case PT_SCX:- case PT_BOOL:- case PT_BIDICL:- compares++;- /* Do nothing. */- break;-- case PT_SPACE:- case PT_PXSPACE:- SET_CHAR_OFFSET(9);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xd - 0x9);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);-- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);-- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);-- SET_TYPE_OFFSET(ucp_Zl);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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:- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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;-- case PT_CLIST:- other_cases = PRIV(ucd_caseless_sets) + cc[1];-- /* At least three characters are required.- Otherwise this case would be handled by the normal code path. */- SLJIT_ASSERT(other_cases[0] != NOTACHAR && other_cases[1] != NOTACHAR && other_cases[2] != NOTACHAR);- SLJIT_ASSERT(other_cases[0] < other_cases[1] && other_cases[1] < other_cases[2]);-- /* Optimizing character pairs, if their difference is power of 2. */- if (is_powerof2(other_cases[1] ^ other_cases[0]))- {- if (charoffset == 0)- OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);- else- {- 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]);- }- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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]))- {- if (charoffset == 0)- OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[2] ^ other_cases[1]);- else- {- 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]);- }- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, other_cases[2]);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);-- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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- {- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);- }-- while (*other_cases != NOTACHAR)- {- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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:- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);-- SET_CHAR_OFFSET(0xa0);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);- SET_CHAR_OFFSET(0);- OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, 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);- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, 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);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);-- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);- OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);-- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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);- break;-- case PT_PXPRINT:- /* C and Z groups are the farthest two groups. */- SET_TYPE_OFFSET(ucp_Ll);- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);-- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);-- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);-- SET_CHAR_OFFSET(0);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x7f);- OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL);-- SET_TYPE_OFFSET(ucp_Pc);- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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 /* SUPPORT_UNICODE */-- 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 PCRE2_SPTR compile_simple_assertion_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks)-{-DEFINE_COMPILER;-int length;-struct sljit_jump *jump[4];-#ifdef SUPPORT_UNICODE-struct sljit_label *label;-#endif /* SUPPORT_UNICODE */--switch(type)- {- case OP_SOD:- if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));- }- else- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));- return cc;-- case OP_SOM:- if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));- }- else- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), 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));-#ifdef SUPPORT_UNICODE- if (common->invalid_utf)- {- add_jump(compiler, backtracks, CMP((type == OP_NOT_WORD_BOUNDARY) ? SLJIT_NOT_EQUAL : SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0));- return cc;- }-#endif /* SUPPORT_UNICODE */- 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;-- 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 == PCRE2_JIT_COMPLETE)- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));- else- {- jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0);- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, STR_END, 0);- OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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));- OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, 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, TMP3, 0, STR_PTR, 0);- read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR);- 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, TMP3, 0);- }- JUMPHERE(jump[2]);- JUMPHERE(jump[3]);- }- JUMPHERE(jump[0]);- if (common->mode != PCRE2_JIT_COMPLETE)- check_partial(common, TRUE);- return cc;-- case OP_EOD:- add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));- if (common->mode != PCRE2_JIT_COMPLETE)- check_partial(common, TRUE);- return cc;-- case OP_DOLL:- if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);- }- else- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);- add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));-- 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);- if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);- }- else- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);- add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));- 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 == PCRE2_JIT_COMPLETE)- 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, TMP3, 0, NULL);- check_newlinechar(common, common->nltype, backtracks, FALSE);- }- JUMPHERE(jump[0]);- return cc;-- case OP_CIRC:- if (HAS_VIRTUAL_REGISTERS)- {- 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));- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);- add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));- }- else- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));- add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);- add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));- }- return cc;-- case OP_CIRCM:- /* TMP2 might be used by peek_char_back. */- if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));- jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);- }- else- {- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));- jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);- OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);- }- add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));- jump[0] = JUMP(SLJIT_JUMP);- JUMPHERE(jump[1]);-- if (!common->alt_circumflex)- 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, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, TMP2, 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- {- peek_char_back(common, common->nlmax, backtracks);- check_newlinechar(common, common->nltype, backtracks, FALSE);- }- JUMPHERE(jump[0]);- return cc;-- case OP_REVERSE:- length = GET(cc, 0);- if (length == 0)- return cc + LINK_SIZE;- if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));- }- else- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));-#ifdef SUPPORT_UNICODE- if (common->utf)- {- OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, length);- label = LABEL();- add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0));- move_back(common, backtracks, FALSE);- OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);- JUMPTO(SLJIT_NOT_ZERO, label);- }- else-#endif- {- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));- add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0));- }- check_start_used_ptr(common);- return cc + LINK_SIZE;- }-SLJIT_UNREACHABLE();-return cc;-}--#ifdef SUPPORT_UNICODE--#if PCRE2_CODE_UNIT_WIDTH != 32--static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc)-{-PCRE2_SPTR start_subject = args->begin;-PCRE2_SPTR end_subject = args->end;-int lgb, rgb, ricount;-PCRE2_SPTR prevcc, endcc, bptr;-BOOL first = TRUE;-uint32_t c;--prevcc = cc;-endcc = NULL;-do- {- GETCHARINC(c, cc);- rgb = UCD_GRAPHBREAK(c);-- if (first)- {- lgb = rgb;- endcc = cc;- first = FALSE;- continue;- }-- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)- break;-- /* Not breaking between Regional Indicators is allowed only if there- are an even number of preceding RIs. */-- if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)- {- ricount = 0;- bptr = prevcc;-- /* bptr is pointing to the left-hand character */- while (bptr > start_subject)- {- bptr--;- BACKCHAR(bptr);- GETCHAR(c, bptr);-- if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator)- break;-- ricount++;- }-- if ((ricount & 1) != 0) break; /* Grapheme break required */- }-- /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this- allows any number of them before a following Extended_Pictographic. */-- if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||- lgb != ucp_gbExtended_Pictographic)- lgb = rgb;-- prevcc = endcc;- endcc = cc;- }-while (cc < end_subject);--return endcc;-}--#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */--static PCRE2_SPTR SLJIT_FUNC do_extuni_utf_invalid(jit_arguments *args, PCRE2_SPTR cc)-{-PCRE2_SPTR start_subject = args->begin;-PCRE2_SPTR end_subject = args->end;-int lgb, rgb, ricount;-PCRE2_SPTR prevcc, endcc, bptr;-BOOL first = TRUE;-uint32_t c;--prevcc = cc;-endcc = NULL;-do- {- GETCHARINC_INVALID(c, cc, end_subject, break);- rgb = UCD_GRAPHBREAK(c);-- if (first)- {- lgb = rgb;- endcc = cc;- first = FALSE;- continue;- }-- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)- break;-- /* Not breaking between Regional Indicators is allowed only if there- are an even number of preceding RIs. */-- if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)- {- ricount = 0;- bptr = prevcc;-- /* bptr is pointing to the left-hand character */- while (bptr > start_subject)- {- GETCHARBACK_INVALID(c, bptr, start_subject, break);-- if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator)- break;-- ricount++;- }-- if ((ricount & 1) != 0)- break; /* Grapheme break required */- }-- /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this- allows any number of them before a following Extended_Pictographic. */-- if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||- lgb != ucp_gbExtended_Pictographic)- lgb = rgb;-- prevcc = endcc;- endcc = cc;- }-while (cc < end_subject);--return endcc;-}--static PCRE2_SPTR SLJIT_FUNC do_extuni_no_utf(jit_arguments *args, PCRE2_SPTR cc)-{-PCRE2_SPTR start_subject = args->begin;-PCRE2_SPTR end_subject = args->end;-int lgb, rgb, ricount;-PCRE2_SPTR bptr;-uint32_t c;--/* Patch by PH */-/* GETCHARINC(c, cc); */-c = *cc++;--#if PCRE2_CODE_UNIT_WIDTH == 32-if (c >= 0x110000)- return NULL;-#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */-lgb = UCD_GRAPHBREAK(c);--while (cc < end_subject)- {- c = *cc;-#if PCRE2_CODE_UNIT_WIDTH == 32- if (c >= 0x110000)- break;-#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */- rgb = UCD_GRAPHBREAK(c);-- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)- break;-- /* Not breaking between Regional Indicators is allowed only if there- are an even number of preceding RIs. */-- if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)- {- ricount = 0;- bptr = cc - 1;-- /* bptr is pointing to the left-hand character */- while (bptr > start_subject)- {- bptr--;- c = *bptr;-#if PCRE2_CODE_UNIT_WIDTH == 32- if (c >= 0x110000)- break;-#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */-- if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) break;-- ricount++;- }-- if ((ricount & 1) != 0)- break; /* Grapheme break required */- }-- /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this- allows any number of them before a following Extended_Pictographic. */-- if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||- lgb != ucp_gbExtended_Pictographic)- lgb = rgb;-- cc++;- }--return cc;-}--#endif /* SUPPORT_UNICODE */--static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr)-{-DEFINE_COMPILER;-int length;-unsigned int c, oc, bit;-compare_context context;-struct sljit_jump *jump[3];-jump_list *end_list;-#ifdef SUPPORT_UNICODE-PCRE2_UCHAR propdata[5];-#endif /* SUPPORT_UNICODE */--switch(type)- {- case OP_NOT_DIGIT:- case OP_DIGIT:- /* Digits are usually 0-9, so it is worth to optimize them. */- if (check_str_ptr)- detect_partial_match(common, backtracks);-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8- if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_digit, FALSE))- read_char7_type(common, backtracks, type == OP_NOT_DIGIT);- else-#endif- read_char8_type(common, backtracks, type == OP_NOT_DIGIT);- /* Flip the starting bit in the negative case. */- OP2U(SLJIT_AND | SLJIT_SET_Z, 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:- if (check_str_ptr)- detect_partial_match(common, backtracks);-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8- if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_space, FALSE))- read_char7_type(common, backtracks, type == OP_NOT_WHITESPACE);- else-#endif- read_char8_type(common, backtracks, type == OP_NOT_WHITESPACE);- OP2U(SLJIT_AND | SLJIT_SET_Z, 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:- if (check_str_ptr)- detect_partial_match(common, backtracks);-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8- if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_word, FALSE))- read_char7_type(common, backtracks, type == OP_NOT_WORDCHAR);- else-#endif- read_char8_type(common, backtracks, type == OP_NOT_WORDCHAR);- OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_word);- add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO));- return cc;-- case OP_ANY:- if (check_str_ptr)- detect_partial_match(common, backtracks);- read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR);- if (common->nltype == NLTYPE_FIXED && common->newline > 255)- {- jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);- end_list = NULL;- if (common->mode != PCRE2_JIT_PARTIAL_HARD)- 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);- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));- set_jumps(end_list, LABEL());- JUMPHERE(jump[0]);- }- else- check_newlinechar(common, common->nltype, backtracks, TRUE);- return cc;-- case OP_ALLANY:- if (check_str_ptr)- detect_partial_match(common, backtracks);-#ifdef SUPPORT_UNICODE- if (common->utf)- {- if (common->invalid_utf)- {- read_char(common, 0, READ_CHAR_MAX, backtracks, READ_CHAR_UPDATE_STR_PTR);- return cc;- }--#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-#if PCRE2_CODE_UNIT_WIDTH == 8- jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 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 PCRE2_CODE_UNIT_WIDTH == 16- jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);- OP2U(SLJIT_SUB | SLJIT_SET_Z, 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 /* PCRE2_CODE_UNIT_WIDTH == 8 */- JUMPHERE(jump[0]);- return cc;-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */- }-#endif /* SUPPORT_UNICODE */- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- return cc;-- case OP_ANYBYTE:- 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;--#ifdef SUPPORT_UNICODE- case OP_NOTPROP:- case OP_PROP:- propdata[0] = XCL_HASPROP;- propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;- 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-- case OP_ANYNL:- if (check_str_ptr)- detect_partial_match(common, backtracks);- read_char(common, common->bsr_nlmin, common->bsr_nlmax, NULL, 0);- 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 != PCRE2_JIT_PARTIAL_HARD)- 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:- if (check_str_ptr)- detect_partial_match(common, backtracks);-- if (type == OP_NOT_HSPACE)- read_char(common, 0x9, 0x3000, backtracks, READ_CHAR_UPDATE_STR_PTR);- else- read_char(common, 0x9, 0x3000, NULL, 0);-- 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;-- case OP_NOT_VSPACE:- case OP_VSPACE:- if (check_str_ptr)- detect_partial_match(common, backtracks);-- if (type == OP_NOT_VSPACE)- read_char(common, 0xa, 0x2029, backtracks, READ_CHAR_UPDATE_STR_PTR);- else- read_char(common, 0xa, 0x2029, NULL, 0);-- 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;--#ifdef SUPPORT_UNICODE- case OP_EXTUNI:- if (check_str_ptr)- detect_partial_match(common, backtracks);-- SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);- OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);--#if PCRE2_CODE_UNIT_WIDTH != 32- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM,- common->utf ? (common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_utf)) : SLJIT_FUNC_ADDR(do_extuni_no_utf));- if (common->invalid_utf)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));-#else- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM,- common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_no_utf));- if (!common->utf || common->invalid_utf)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));-#endif-- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);-- if (common->mode == PCRE2_JIT_PARTIAL_HARD)- {- jump[0] = CMP(SLJIT_LESS, SLJIT_RETURN_REG, 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_CHAR:- case OP_CHARI:- length = 1;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);-#endif-- if (check_str_ptr && common->mode != PCRE2_JIT_COMPLETE)- detect_partial_match(common, backtracks);-- if (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));- if (length > 1 || (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE))- add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));-- context.length = IN_UCHARS(length);- context.sourcereg = -1;-#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED- context.ucharptr = 0;-#endif- return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);- }--#ifdef SUPPORT_UNICODE- if (common->utf)- {- GETCHAR(c, cc);- }- else-#endif- c = *cc;-- SLJIT_ASSERT(type == OP_CHARI && char_has_othercase(common, cc));-- if (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE)- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));-- oc = char_othercase(common, c);- read_char(common, c < oc ? c : oc, c > oc ? c : oc, NULL, 0);-- SLJIT_ASSERT(!is_powerof2(c ^ oc));-- if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))- {- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, oc);- CMOV(SLJIT_EQUAL, TMP1, SLJIT_IMM, c);- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));- }- else- {- jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c);- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc));- JUMPHERE(jump[0]);- }- return cc + length;-- case OP_NOT:- case OP_NOTI:- if (check_str_ptr)- detect_partial_match(common, backtracks);-- length = 1;-#ifdef SUPPORT_UNICODE- if (common->utf)- {-#if PCRE2_CODE_UNIT_WIDTH == 8- c = *cc;- if (c < 128 && !common->invalid_utf)- {- 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- {- /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */- OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));- }- /* Skip the variable-length character. */- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);- JUMPHERE(jump[0]);- return cc + 1;- }- else-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */- {- GETCHARLEN(c, cc, length);- }- }- else-#endif /* SUPPORT_UNICODE */- c = *cc;-- if (type == OP_NOT || !char_has_othercase(common, cc))- {- read_char(common, c, c, backtracks, READ_CHAR_UPDATE_STR_PTR);- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));- }- else- {- oc = char_othercase(common, c);- read_char(common, c < oc ? c : oc, c > oc ? c : oc, backtracks, READ_CHAR_UPDATE_STR_PTR);- bit = c ^ oc;- if (is_powerof2(bit))- {- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));- }- else- {- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, oc));- }- }- return cc + length;-- case OP_CLASS:- case OP_NCLASS:- if (check_str_ptr)- detect_partial_match(common, backtracks);--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8- bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255;- if (type == OP_NCLASS)- read_char(common, 0, bit, backtracks, READ_CHAR_UPDATE_STR_PTR);- else- read_char(common, 0, bit, NULL, 0);-#else- if (type == OP_NCLASS)- read_char(common, 0, 255, backtracks, READ_CHAR_UPDATE_STR_PTR);- else- read_char(common, 0, 255, NULL, 0);-#endif-- if (optimize_class(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks))- return cc + 32 / sizeof(PCRE2_UCHAR);--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8- jump[0] = NULL;- if (common->utf)- {- jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, bit);- if (type == OP_CLASS)- {- add_jump(compiler, backtracks, jump[0]);- jump[0] = NULL;- }- }-#elif PCRE2_CODE_UNIT_WIDTH != 8- jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);- if (type == OP_CLASS)- {- add_jump(compiler, backtracks, jump[0]);- jump[0] = NULL;- }-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */-- OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);- OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);- OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);- OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);- add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));--#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8- if (jump[0] != NULL)- JUMPHERE(jump[0]);-#endif- return cc + 32 / sizeof(PCRE2_UCHAR);--#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32- 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- }-SLJIT_UNREACHABLE();-return cc;-}--static SLJIT_INLINE PCRE2_SPTR compile_charn_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, jump_list **backtracks)-{-/* This function consumes at least one input character. */-/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */-DEFINE_COMPILER;-PCRE2_SPTR ccbegin = cc;-compare_context context;-int size;--context.length = 0;-do- {- if (cc >= ccend)- break;-- if (*cc == OP_CHAR)- {- size = 1;-#ifdef SUPPORT_UNICODE- if (common->utf && HAS_EXTRALEN(cc[1]))- size += GET_EXTRALEN(cc[1]);-#endif- }- else if (*cc == OP_CHARI)- {- size = 1;-#ifdef SUPPORT_UNICODE- if (common->utf)- {- if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)- size = 0;- else if (HAS_EXTRALEN(cc[1]))- size += GET_EXTRALEN(cc[1]);- }- else-#endif- if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)- size = 0;- }- else- size = 0;-- cc += 1 + size;- context.length += IN_UCHARS(size);- }-while (size > 0 && context.length <= 128);--cc = ccbegin;-if (context.length > 0)- {- /* We have a fixed-length byte sequence. */- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);- add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));-- context.sourcereg = -1;-#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED- context.ucharptr = 0;-#endif- do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0);- return cc;- }--/* A non-fixed length character will be checked if length == 0. */-return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE);-}--/* Forward definitions. */-static void compile_matchingpath(compiler_common *, PCRE2_SPTR, PCRE2_SPTR, backtrack_common *);-static void compile_backtrackingpath(compiler_common *, struct backtrack_common *);--#define PUSH_BACKTRACK(size, ccstart, error) \- do \- { \- backtrack = sljit_alloc_memory(compiler, (size)); \- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \- return error; \- memset(backtrack, 0, size); \- backtrack->prev = parent->top; \- backtrack->cc = (ccstart); \- parent->top = backtrack; \- } \- while (0)--#define PUSH_BACKTRACK_NOVALUE(size, ccstart) \- do \- { \- backtrack = sljit_alloc_memory(compiler, (size)); \- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \- return; \- memset(backtrack, 0, size); \- backtrack->prev = parent->top; \- backtrack->cc = (ccstart); \- parent->top = backtrack; \- } \- while (0)--#define BACKTRACK_AS(type) ((type *)backtrack)--static void compile_dnref_search(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)-{-/* The OVECTOR offset goes to TMP2. */-DEFINE_COMPILER;-int count = GET2(cc, 1 + IMM2_SIZE);-PCRE2_SPTR slot = common->name_table + GET2(cc, 1) * common->name_entry_size;-unsigned int offset;-jump_list *found = NULL;--SLJIT_ASSERT(*cc == OP_DNREF || *cc == OP_DNREFI);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));--count--;-while (count-- > 0)- {- offset = GET2(slot, 0) << 1;- GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));- add_jump(compiler, &found, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0));- slot += common->name_entry_size;- }--offset = GET2(slot, 0) << 1;-GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));-if (backtracks != NULL && !common->unset_backref)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0));--set_jumps(found, LABEL());-}--static void compile_ref_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)-{-DEFINE_COMPILER;-BOOL ref = (*cc == OP_REF || *cc == OP_REFI);-int offset = 0;-struct sljit_jump *jump = NULL;-struct sljit_jump *partial;-struct sljit_jump *nopartial;-#if defined SUPPORT_UNICODE-struct sljit_label *loop;-struct sljit_label *caseless_loop;-jump_list *no_match = NULL;-int source_reg = COUNT_MATCH;-int source_end_reg = ARGUMENTS;-int char1_reg = STACK_LIMIT;-#endif /* SUPPORT_UNICODE */--if (ref)- {- offset = GET2(cc, 1) << 1;- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));- /* OVECTOR(1) contains the "string begin - 1" constant. */- if (withchecks && !common->unset_backref)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));- }-else- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);--#if defined SUPPORT_UNICODE-if (common->utf && *cc == OP_REFI)- {- SLJIT_ASSERT(common->iref_ptr != 0);-- if (ref)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));- else- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));-- if (withchecks && emptyfail)- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, TMP2, 0));-- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr, source_reg, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw), source_end_reg, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2, char1_reg, 0);-- OP1(SLJIT_MOV, source_reg, 0, TMP1, 0);- OP1(SLJIT_MOV, source_end_reg, 0, TMP2, 0);-- loop = LABEL();- jump = CMP(SLJIT_GREATER_EQUAL, source_reg, 0, source_end_reg, 0);- partial = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-- /* Read original character. It must be a valid UTF character. */- OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);- OP1(SLJIT_MOV, STR_PTR, 0, source_reg, 0);-- read_char(common, 0, READ_CHAR_MAX, NULL, READ_CHAR_UPDATE_STR_PTR | READ_CHAR_VALID_UTF);-- OP1(SLJIT_MOV, source_reg, 0, STR_PTR, 0);- OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);- OP1(SLJIT_MOV, char1_reg, 0, TMP1, 0);-- /* Read second character. */- read_char(common, 0, READ_CHAR_MAX, &no_match, READ_CHAR_UPDATE_STR_PTR);-- CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);-- OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);-- add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));-- OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);-- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records));-- OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(ucd_record, other_case));- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(ucd_record, caseset));- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);- CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);-- add_jump(compiler, &no_match, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0));- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_caseless_sets));-- caseless_loop = LABEL();- OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP2), 0);- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(uint32_t));- OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, TMP1, 0, char1_reg, 0);- JUMPTO(SLJIT_EQUAL, loop);- JUMPTO(SLJIT_LESS, caseless_loop);-- set_jumps(no_match, LABEL());- if (common->mode == PCRE2_JIT_COMPLETE)- JUMPHERE(partial);-- OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);- OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));- OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);- add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));-- if (common->mode != PCRE2_JIT_COMPLETE)- {- JUMPHERE(partial);- OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);- OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));- OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);-- check_partial(common, FALSE);- add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));- }-- JUMPHERE(jump);- OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);- OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));- OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);- return;- }-else-#endif /* SUPPORT_UNICODE */- {- if (ref)- OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);- else- OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);-- if (withchecks)- jump = JUMP(SLJIT_ZERO);-- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);- partial = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);- if (common->mode == PCRE2_JIT_COMPLETE)- add_jump(compiler, backtracks, partial);-- add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));-- if (common->mode != PCRE2_JIT_COMPLETE)- {- nopartial = JUMP(SLJIT_JUMP);- JUMPHERE(partial);- /* TMP2 -= STR_END - STR_PTR */- OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0);- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0);- partial = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0);- OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);- add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));- JUMPHERE(partial);- check_partial(common, FALSE);- add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));- JUMPHERE(nopartial);- }- }--if (jump != NULL)- {- if (emptyfail)- add_jump(compiler, backtracks, jump);- else- JUMPHERE(jump);- }-}--static SLJIT_INLINE PCRE2_SPTR compile_ref_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)-{-DEFINE_COMPILER;-BOOL ref = (*cc == OP_REF || *cc == OP_REFI);-backtrack_common *backtrack;-PCRE2_UCHAR type;-int offset = 0;-struct sljit_label *label;-struct sljit_jump *zerolength;-struct sljit_jump *jump = NULL;-PCRE2_SPTR ccbegin = cc;-int min = 0, max = 0;-BOOL minimize;--PUSH_BACKTRACK(sizeof(ref_iterator_backtrack), cc, NULL);--if (ref)- offset = GET2(cc, 1) << 1;-else- cc += IMM2_SIZE;-type = cc[1 + IMM2_SIZE];--SLJIT_COMPILE_ASSERT((OP_CRSTAR & 0x1) == 0, crstar_opcode_must_be_even);-minimize = (type & 0x1) != 0;-switch(type)- {- case OP_CRSTAR:- case OP_CRMINSTAR:- min = 0;- max = 0;- cc += 1 + IMM2_SIZE + 1;- break;- case OP_CRPLUS:- case OP_CRMINPLUS:- min = 1;- max = 0;- cc += 1 + IMM2_SIZE + 1;- break;- case OP_CRQUERY:- case OP_CRMINQUERY:- min = 0;- max = 1;- cc += 1 + IMM2_SIZE + 1;- break;- case OP_CRRANGE:- case OP_CRMINRANGE:- min = GET2(cc, 1 + IMM2_SIZE + 1);- max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE);- cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;- break;- default:- SLJIT_UNREACHABLE();- break;- }--if (!minimize)- {- if (min == 0)- {- allocate_stack(common, 2);- if (ref)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));- 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_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)- zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));- else- {- compile_dnref_search(common, ccbegin, NULL);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0);- zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));- }- /* Restore if not zero length. */- OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));- }- else- {- allocate_stack(common, 1);- if (ref)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);- if (ref)- {- add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));- zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));- }- else- {- compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0);- zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));- }- }-- if (min > 1 || max > 1)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, 0);-- label = LABEL();- if (!ref)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);- compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE);-- if (min > 1 || max > 1)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0);- if (min > 1)- CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, label);- if (max > 1)- {- jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);- JUMPTO(SLJIT_JUMP, label);- JUMPHERE(jump);- }- }-- if (max == 0)- {- /* Includes min > 1 case as well. */- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);- JUMPTO(SLJIT_JUMP, label);- }-- JUMPHERE(zerolength);- BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();-- count_match(common);- return cc;- }--allocate_stack(common, ref ? 2 : 3);-if (ref)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));-OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);-if (type != OP_CRMINSTAR)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);--if (min == 0)- {- /* 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)- zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));- else- {- compile_dnref_search(common, ccbegin, NULL);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);- zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));- }- /* Length is non-zero, we can match real repeats. */- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);- jump = JUMP(SLJIT_JUMP);- }-else- {- if (ref)- {- add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));- zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));- }- else- {- compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);- zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));- }- }--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));--if (!ref)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));-compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE);-OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);--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(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);--if (jump != NULL)- JUMPHERE(jump);-JUMPHERE(zerolength);--count_match(common);-return cc;-}--static SLJIT_INLINE PCRE2_SPTR compile_recurse_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)-{-DEFINE_COMPILER;-backtrack_common *backtrack;-recurse_entry *entry = common->entries;-recurse_entry *prev = NULL;-sljit_sw start = GET(cc, 1);-PCRE2_SPTR start_cc;-BOOL needs_control_head;--PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);--/* Inlining simple patterns. */-if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head) == no_stack)- {- start_cc = common->start + start;- compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack);- BACKTRACK_AS(recurse_backtrack)->inlined_pattern = TRUE;- return cc + 1 + LINK_SIZE;- }--while (entry != NULL)- {- if (entry->start == start)- break;- prev = entry;- entry = entry->next;- }--if (entry == NULL)- {- entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- return NULL;- entry->next = NULL;- entry->entry_label = NULL;- entry->backtrack_label = NULL;- entry->entry_calls = NULL;- entry->backtrack_calls = NULL;- entry->start = start;-- if (prev != NULL)- prev->next = entry;- else- common->entries = entry;- }--BACKTRACK_AS(recurse_backtrack)->entry = entry;--if (entry->entry_label == NULL)- add_jump(compiler, &entry->entry_calls, JUMP(SLJIT_FAST_CALL));-else- JUMPTO(SLJIT_FAST_CALL, entry->entry_label);-/* Leave if the match is failed. */-add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));-BACKTRACK_AS(recurse_backtrack)->matchingpath = LABEL();-return cc + 1 + LINK_SIZE;-}--static sljit_s32 SLJIT_FUNC do_callout(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector)-{-PCRE2_SPTR begin;-PCRE2_SIZE *ovector;-sljit_u32 oveccount, capture_top;--if (arguments->callout == NULL)- return 0;--SLJIT_COMPILE_ASSERT(sizeof (PCRE2_SIZE) <= sizeof (sljit_sw), pcre2_size_must_be_lower_than_sljit_sw_size);--begin = arguments->begin;-ovector = (PCRE2_SIZE*)(callout_block + 1);-oveccount = callout_block->capture_top;--SLJIT_ASSERT(oveccount >= 1);--callout_block->version = 2;-callout_block->callout_flags = 0;--/* Offsets in subject. */-callout_block->subject_length = arguments->end - arguments->begin;-callout_block->start_match = jit_ovector[0] - begin;-callout_block->current_position = (PCRE2_SPTR)callout_block->offset_vector - begin;-callout_block->subject = begin;--/* Convert and copy the JIT offset vector to the ovector array. */-callout_block->capture_top = 1;-callout_block->offset_vector = ovector;--ovector[0] = PCRE2_UNSET;-ovector[1] = PCRE2_UNSET;-ovector += 2;-jit_ovector += 2;-capture_top = 1;--/* Convert pointers to sizes. */-while (--oveccount != 0)- {- capture_top++;-- ovector[0] = (PCRE2_SIZE)(jit_ovector[0] - begin);- ovector[1] = (PCRE2_SIZE)(jit_ovector[1] - begin);-- if (ovector[0] != PCRE2_UNSET)- callout_block->capture_top = capture_top;-- ovector += 2;- jit_ovector += 2;- }--return (arguments->callout)(callout_block, arguments->callout_data);-}--#define CALLOUT_ARG_OFFSET(arg) \- SLJIT_OFFSETOF(pcre2_callout_block, arg)--static SLJIT_INLINE PCRE2_SPTR compile_callout_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)-{-DEFINE_COMPILER;-backtrack_common *backtrack;-sljit_s32 mov_opcode;-unsigned int callout_length = (*cc == OP_CALLOUT)- ? PRIV(OP_lengths)[OP_CALLOUT] : GET(cc, 1 + 2 * LINK_SIZE);-sljit_sw value1;-sljit_sw value2;-sljit_sw value3;-sljit_uw callout_arg_size = (common->re->top_bracket + 1) * 2 * sizeof(sljit_sw);--PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);--callout_arg_size = (sizeof(pcre2_callout_block) + callout_arg_size + sizeof(sljit_sw) - 1) / sizeof(sljit_sw);--allocate_stack(common, callout_arg_size);--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);-value1 = (*cc == OP_CALLOUT) ? cc[1 + 2 * LINK_SIZE] : 0;-OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, value1);-OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0);-OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_top), SLJIT_IMM, common->re->top_bracket + 1);--/* These pointer sized fields temporarly stores internal variables. */-OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(offset_vector), STR_PTR, 0);--if (common->mark_ptr != 0)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr));-mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;-OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 1));-OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 1 + LINK_SIZE));--if (*cc == OP_CALLOUT)- {- value1 = 0;- value2 = 0;- value3 = 0;- }-else- {- value1 = (sljit_sw) (cc + (1 + 4*LINK_SIZE) + 1);- value2 = (callout_length - (1 + 4*LINK_SIZE + 2));- value3 = (sljit_sw) (GET(cc, 1 + 3*LINK_SIZE));- }--OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string), SLJIT_IMM, value1);-OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_length), SLJIT_IMM, value2);-OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_offset), SLJIT_IMM, value3);-OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0);--SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);--/* Needed to save important temporary registers. */-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);-/* SLJIT_R0 = arguments */-OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0);-GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START);-sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(32, W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_callout));-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);-free_stack(common, callout_arg_size);--/* Check return value. */-OP2U(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);-add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER));-if (common->abort_label == NULL)- add_jump(compiler, &common->abort, JUMP(SLJIT_NOT_EQUAL) /* SIG_LESS */);-else- JUMPTO(SLJIT_NOT_EQUAL /* SIG_LESS */, common->abort_label);-return cc + callout_length;-}--#undef CALLOUT_ARG_SIZE-#undef CALLOUT_ARG_OFFSET--static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(PCRE2_SPTR cc)-{-while (TRUE)- {- switch (*cc)- {- case OP_CALLOUT_STR:- cc += GET(cc, 1 + 2*LINK_SIZE);- break;-- 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 PCRE2_SPTR compile_assert_matchingpath(compiler_common *common, PCRE2_SPTR cc, assert_backtrack *backtrack, BOOL conditional)-{-DEFINE_COMPILER;-int framesize;-int extrasize;-BOOL local_quit_available = FALSE;-BOOL needs_control_head;-int private_data_ptr;-backtrack_common altbacktrack;-PCRE2_SPTR ccbegin;-PCRE2_UCHAR opcode;-PCRE2_UCHAR bra = OP_BRA;-jump_list *tmp = NULL;-jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;-jump_list **found;-/* Saving previous accept variables. */-BOOL save_local_quit_available = common->local_quit_available;-BOOL save_in_positive_assertion = common->in_positive_assertion;-then_trap_backtrack *save_then_trap = common->then_trap;-struct sljit_label *save_quit_label = common->quit_label;-struct sljit_label *save_accept_label = common->accept_label;-jump_list *save_quit = common->quit;-jump_list *save_positive_assertion_quit = common->positive_assertion_quit;-jump_list *save_accept = common->accept;-struct sljit_jump *jump;-struct sljit_jump *brajump = NULL;--/* Assert captures then. */-common->then_trap = NULL;--if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)- {- SLJIT_ASSERT(!conditional);- bra = *cc;- cc++;- }-private_data_ptr = PRIVATE_DATA(cc);-SLJIT_ASSERT(private_data_ptr != 0);-framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);-backtrack->framesize = framesize;-backtrack->private_data_ptr = private_data_ptr;-opcode = *cc;-SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);-found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;-ccbegin = cc;-cc += GET(cc, 1);--if (bra == OP_BRAMINZERO)- {- /* This is a braminzero backtrack path. */- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, 1);- brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);- }--if (framesize < 0)- {- 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);-- if (extrasize > 0)- allocate_stack(common, extrasize);-- if (needs_control_head)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);-- 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);- }- }-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_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);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);- }- else- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);-- init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize);- }--memset(&altbacktrack, 0, sizeof(backtrack_common));-if (conditional || (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT))- {- /* Control verbs cannot escape from these asserts. */- local_quit_available = TRUE;- common->local_quit_available = TRUE;- common->quit_label = NULL;- common->quit = NULL;- }--common->in_positive_assertion = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK);-common->positive_assertion_quit = NULL;--while (1)- {- common->accept_label = NULL;- common->accept = NULL;- altbacktrack.top = NULL;- altbacktrack.topbacktracks = NULL;-- if (*ccbegin == OP_ALT && extrasize > 0)- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));-- altbacktrack.cc = ccbegin;- compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- {- if (local_quit_available)- {- common->local_quit_available = save_local_quit_available;- common->quit_label = save_quit_label;- common->quit = save_quit;- }- common->in_positive_assertion = save_in_positive_assertion;- common->then_trap = save_then_trap;- common->accept_label = save_accept_label;- common->positive_assertion_quit = save_positive_assertion_quit;- common->accept = save_accept;- return NULL;- }- common->accept_label = LABEL();- if (common->accept != NULL)- set_jumps(common->accept, common->accept_label);-- /* Reset stack. */- if (framesize < 0)- {- if (framesize == no_frame)- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- 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), 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_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), 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), STACK(-framesize - 2));- add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw));- }- }-- if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)- {- /* We know that STR_PTR was stored on the top of the stack. */- if (conditional)- {- 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), STACK(-extrasize));- else- {- 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_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), STACK(-framesize - 1));- }- }- add_jump(compiler, found, JUMP(SLJIT_JUMP));-- compile_backtrackingpath(common, altbacktrack.top);- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- {- if (local_quit_available)- {- common->local_quit_available = save_local_quit_available;- common->quit_label = save_quit_label;- common->quit = save_quit;- }- common->in_positive_assertion = save_in_positive_assertion;- common->then_trap = save_then_trap;- common->accept_label = save_accept_label;- common->positive_assertion_quit = save_positive_assertion_quit;- common->accept = save_accept;- return NULL;- }- set_jumps(altbacktrack.topbacktracks, LABEL());-- if (*cc != OP_ALT)- break;-- ccbegin = cc;- cc += GET(cc, 1);- }--if (local_quit_available)- {- SLJIT_ASSERT(common->positive_assertion_quit == NULL);- /* Makes the check less complicated below. */- common->positive_assertion_quit = common->quit;- }--/* None of them matched. */-if (common->positive_assertion_quit != NULL)- {- jump = JUMP(SLJIT_JUMP);- set_jumps(common->positive_assertion_quit, LABEL());- SLJIT_ASSERT(framesize != no_stack);- if (framesize < 0)- 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_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (extrasize + 1) * sizeof(sljit_sw));- }- JUMPHERE(jump);- }--if (needs_control_head)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(1));--if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)- {- /* Assert is failed. */- if ((conditional && extrasize > 0) || bra == OP_BRAZERO)- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));-- if (framesize < 0)- {- /* The topmost item should be 0. */- if (bra == OP_BRAZERO)- {- if (extrasize == 2)- free_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);- }- else if (extrasize > 0)- free_stack(common, extrasize);- }- else- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));- /* The topmost item should be 0. */- if (bra == OP_BRAZERO)- {- free_stack(common, framesize + extrasize - 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);- }- else- free_stack(common, framesize + extrasize);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);- }- jump = JUMP(SLJIT_JUMP);- if (bra != OP_BRAZERO)- add_jump(compiler, target, jump);-- /* Assert is successful. */- set_jumps(tmp, LABEL());- if (framesize < 0)- {- /* We know that STR_PTR was stored on the top of the stack. */- 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_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_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 (bra == OP_BRA)- {- /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */- 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_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));- if (bra == OP_BRAMINZERO)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);- }- else- {- SLJIT_ASSERT(extrasize == 3);- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0);- }- }- }-- if (bra == OP_BRAZERO)- {- backtrack->matchingpath = LABEL();- SET_LABEL(jump, backtrack->matchingpath);- }- else if (bra == OP_BRAMINZERO)- {- JUMPTO(SLJIT_JUMP, backtrack->matchingpath);- JUMPHERE(brajump);- if (framesize >= 0)- {- 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, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);- }- set_jumps(backtrack->common.topbacktracks, LABEL());- }- }-else- {- /* AssertNot is successful. */- if (framesize < 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 if (extrasize > 0)- free_stack(common, extrasize);- }- else- {- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));- /* The topmost item should be 0. */- if (bra != OP_BRA)- {- free_stack(common, framesize + extrasize - 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);- }- else- free_stack(common, framesize + extrasize);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);- }-- if (bra == OP_BRAZERO)- backtrack->matchingpath = LABEL();- else if (bra == OP_BRAMINZERO)- {- JUMPTO(SLJIT_JUMP, backtrack->matchingpath);- JUMPHERE(brajump);- }-- if (bra != OP_BRA)- {- SLJIT_ASSERT(found == &backtrack->common.topbacktracks);- set_jumps(backtrack->common.topbacktracks, LABEL());- backtrack->common.topbacktracks = NULL;- }- }--if (local_quit_available)- {- common->local_quit_available = save_local_quit_available;- common->quit_label = save_quit_label;- common->quit = save_quit;- }-common->in_positive_assertion = save_in_positive_assertion;-common->then_trap = save_then_trap;-common->accept_label = save_accept_label;-common->positive_assertion_quit = save_positive_assertion_quit;-common->accept = save_accept;-return cc + 1 + LINK_SIZE;-}--static SLJIT_INLINE void match_once_common(compiler_common *common, PCRE2_UCHAR ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head)-{-DEFINE_COMPILER;-int stacksize;--if (framesize < 0)- {- if (framesize == no_frame)- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- else- {- stacksize = needs_control_head ? 1 : 0;- if (ket != OP_KET || has_alternatives)- 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) ? 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), 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), STACK(-1));- }- }-else- {- stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1;- 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), STACK(-1));-- if (ket == OP_KETRMAX)- {- /* TMP2 which is set here used by OP_KETRMAX below. */- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- }- }-if (needs_control_head)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0);-}--static SLJIT_INLINE int match_capture_common(compiler_common *common, int stacksize, int offset, int private_data_ptr)-{-DEFINE_COMPILER;--if (common->capture_last_ptr != 0)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);- stacksize++;- }-if (common->optimized_cbracket[offset >> 1] == 0)- {- 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), STACK(stacksize), TMP1, 0);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);- stacksize += 2;- }-return stacksize;-}--static PCRE2_SPTR SLJIT_FUNC do_script_run(PCRE2_SPTR ptr, PCRE2_SPTR endptr)-{- if (PRIV(script_run)(ptr, endptr, FALSE))- return endptr;- return NULL;-}--#ifdef SUPPORT_UNICODE--static PCRE2_SPTR SLJIT_FUNC do_script_run_utf(PCRE2_SPTR ptr, PCRE2_SPTR endptr)-{- if (PRIV(script_run)(ptr, endptr, TRUE))- return endptr;- return NULL;-}--#endif /* SUPPORT_UNICODE */--static SLJIT_INLINE void match_script_run_common(compiler_common *common, int private_data_ptr, backtrack_common *parent)-{-DEFINE_COMPILER;--SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);-#ifdef SUPPORT_UNICODE-sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM,- common->utf ? SLJIT_FUNC_ADDR(do_script_run_utf) : SLJIT_FUNC_ADDR(do_script_run));-#else-sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_script_run));-#endif--OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);-add_jump(compiler, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));-}--/*- Handling bracketed expressions is probably the most complex part.-- Stack layout naming characters:- S - Push the current STR_PTR- 0 - Push a 0 (NULL)- A - Push the current STR_PTR. Needed for restoring the STR_PTR- before the next alternative. Not pushed if there are no alternatives.- M - Any values pushed by the current alternative. Can be empty, or anything.- C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.- L - Push the previous local (pointed by localptr) to the stack- () - opional values stored on the stack- ()* - optonal, can be stored multiple times-- The following list shows the regular expression templates, their PCRE byte codes- and stack layout supported by pcre-sljit.-- (?:) OP_BRA | OP_KET A M- () OP_CBRA | OP_KET C M- (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*- OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*- (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*- OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*- ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*- OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*- ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*- OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*- (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )- (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )- ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )- ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )- (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*- OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*- (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*- OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*- ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*- OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*- ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*- OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*--- Stack layout naming characters:- A - Push the alternative index (starting from 0) on the stack.- Not pushed if there is no alternatives.- M - Any values pushed by the current alternative. Can be empty, or anything.-- The next list shows the possible content of a bracket:- (|) OP_*BRA | OP_ALT ... M A- (?()|) OP_*COND | OP_ALT M A- (?>|) OP_ONCE | OP_ALT ... [stack trace] M A- Or nothing, if trace is unnecessary-*/--static PCRE2_SPTR compile_bracket_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)-{-DEFINE_COMPILER;-backtrack_common *backtrack;-PCRE2_UCHAR opcode;-int private_data_ptr = 0;-int offset = 0;-int i, stacksize;-int repeat_ptr = 0, repeat_length = 0;-int repeat_type = 0, repeat_count = 0;-PCRE2_SPTR ccbegin;-PCRE2_SPTR matchingpath;-PCRE2_SPTR slot;-PCRE2_UCHAR bra = OP_BRA;-PCRE2_UCHAR ket;-assert_backtrack *assert;-BOOL has_alternatives;-BOOL needs_control_head = FALSE;-struct sljit_jump *jump;-struct sljit_jump *skip;-struct sljit_label *rmax_label = NULL;-struct sljit_jump *braminzero = NULL;--PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);--if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)- {- bra = *cc;- cc++;- opcode = *cc;- }--opcode = *cc;-ccbegin = cc;-matchingpath = bracketend(cc) - 1 - LINK_SIZE;-ket = *matchingpath;-if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0)- {- repeat_ptr = PRIVATE_DATA(matchingpath);- repeat_length = PRIVATE_DATA(matchingpath + 1);- repeat_type = PRIVATE_DATA(matchingpath + 2);- repeat_count = PRIVATE_DATA(matchingpath + 3);- SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0);- if (repeat_type == OP_UPTO)- ket = OP_KETRMAX;- if (repeat_type == OP_MINUPTO)- ket = OP_KETRMIN;- }--matchingpath = ccbegin + 1 + LINK_SIZE;-SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);-SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));-cc += GET(cc, 1);--has_alternatives = *cc == OP_ALT;-if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND))- {- SLJIT_COMPILE_ASSERT(OP_DNRREF == OP_RREF + 1 && OP_FALSE == OP_RREF + 2 && OP_TRUE == OP_RREF + 3,- compile_time_checks_must_be_grouped_together);- has_alternatives = ((*matchingpath >= OP_RREF && *matchingpath <= OP_TRUE) || *matchingpath == OP_FAIL) ? FALSE : TRUE;- }--if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))- opcode = OP_SCOND;--if (opcode == OP_CBRA || opcode == OP_SCBRA)- {- /* Capturing brackets has a pre-allocated space. */- offset = GET2(ccbegin, 1 + LINK_SIZE);- if (common->optimized_cbracket[offset] == 0)- {- private_data_ptr = OVECTOR_PRIV(offset);- offset <<= 1;- }- else- {- offset <<= 1;- private_data_ptr = OVECTOR(offset);- }- BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;- matchingpath += IMM2_SIZE;- }-else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_ONCE || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)- {- /* Other brackets simply allocate the next entry. */- private_data_ptr = PRIVATE_DATA(ccbegin);- SLJIT_ASSERT(private_data_ptr != 0);- BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;- if (opcode == OP_ONCE)- BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, NULL, FALSE, &needs_control_head);- }--/* Instructions before the first alternative. */-stacksize = 0;-if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))- stacksize++;-if (bra == OP_BRAZERO)- stacksize++;--if (stacksize > 0)- allocate_stack(common, stacksize);--stacksize = 0;-if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))- {- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);- stacksize++;- }--if (bra == OP_BRAZERO)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);--if (bra == OP_BRAMINZERO)- {- /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- if (ket != OP_KETRMIN)- {- free_stack(common, 1);- braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);- }- else if (opcode == OP_ONCE || opcode >= OP_SBRA)- {- jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));- /* Nothing stored during the first run. */- skip = JUMP(SLJIT_JUMP);- JUMPHERE(jump);- /* Checking zero-length iteration. */- if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)- {- /* When we come from outside, private_data_ptr contains the previous STR_PTR. */- braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- }- else- {- /* 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), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2));- }- JUMPHERE(skip);- }- else- {- jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));- JUMPHERE(jump);- }- }--if (repeat_type != 0)- {- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, repeat_count);- if (repeat_type == OP_EXACT)- rmax_label = LABEL();- }--if (ket == OP_KETRMIN)- BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();--if (ket == OP_KETRMAX)- {- rmax_label = LABEL();- if (has_alternatives && opcode >= OP_BRA && opcode < OP_SBRA && repeat_type == 0)- BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label;- }--/* Handling capturing brackets and alternatives. */-if (opcode == OP_ONCE)- {- stacksize = 0;- if (needs_control_head)- {- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);- stacksize++;- }-- if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)- {- /* Neither capturing brackets nor recursions are found in the block. */- if (ket == OP_KETRMIN)- {- stacksize += 2;- if (!needs_control_head)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- }- else- {- if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);- if (ket == OP_KETRMAX || has_alternatives)- stacksize++;- }-- if (stacksize > 0)- allocate_stack(common, stacksize);-- stacksize = 0;- if (needs_control_head)- {- stacksize++;- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);- }-- if (ket == OP_KETRMIN)- {- if (needs_control_head)- 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_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)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);- }- else- {- if (ket != OP_KET || has_alternatives)- stacksize++;-- stacksize += BACKTRACK_AS(bracket_backtrack)->u.framesize + 1;- allocate_stack(common, stacksize);-- if (needs_control_head)- 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_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));-- stacksize = needs_control_head ? 1 : 0;- if (ket != OP_KET || has_alternatives)- {- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);- stacksize++;- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);- }- else- {- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);- }- init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1);- }- }-else if (opcode == OP_CBRA || opcode == OP_SCBRA)- {- /* Saving the previous values. */- if (common->optimized_cbracket[offset >> 1] != 0)- {- SLJIT_ASSERT(private_data_ptr == OVECTOR(offset));- allocate_stack(common, 2);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);- }- else- {- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);- }- }-else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)- {- /* Saving the previous value. */- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);- }-else if (has_alternatives)- {- /* Pushing the starting string pointer. */- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);- }--/* Generating code for the first alternative. */-if (opcode == OP_COND || opcode == OP_SCOND)- {- if (*matchingpath == OP_CREF)- {- SLJIT_ASSERT(has_alternatives);- add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed),- CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));- matchingpath += 1 + IMM2_SIZE;- }- else if (*matchingpath == OP_DNCREF)- {- SLJIT_ASSERT(has_alternatives);-- i = GET2(matchingpath, 1 + IMM2_SIZE);- 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_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_Z, TMP2, 0, TMP2, 0, STR_PTR, 0);- slot += common->name_entry_size;- }- OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);- add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_ZERO));- matchingpath += 1 + 2 * IMM2_SIZE;- }- else if ((*matchingpath >= OP_RREF && *matchingpath <= OP_TRUE) || *matchingpath == OP_FAIL)- {- /* Never has other case. */- BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;- SLJIT_ASSERT(!has_alternatives);-- if (*matchingpath == OP_TRUE)- {- stacksize = 1;- matchingpath++;- }- else if (*matchingpath == OP_FALSE || *matchingpath == OP_FAIL)- stacksize = 0;- else if (*matchingpath == OP_RREF)- {- stacksize = GET2(matchingpath, 1);- if (common->currententry == NULL)- stacksize = 0;- else if (stacksize == RREF_ANY)- stacksize = 1;- else if (common->currententry->start == 0)- stacksize = stacksize == 0;- else- stacksize = stacksize == (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);-- if (stacksize != 0)- matchingpath += 1 + IMM2_SIZE;- }- else- {- if (common->currententry == NULL || common->currententry->start == 0)- stacksize = 0;- else- {- stacksize = GET2(matchingpath, 1 + IMM2_SIZE);- slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;- i = (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);- while (stacksize > 0)- {- if ((int)GET2(slot, 0) == i)- break;- slot += common->name_entry_size;- stacksize--;- }- }-- if (stacksize != 0)- matchingpath += 1 + 2 * IMM2_SIZE;- }-- /* The stacksize == 0 is a common "else" case. */- if (stacksize == 0)- {- if (*cc == OP_ALT)- {- matchingpath = cc + 1 + LINK_SIZE;- cc += GET(cc, 1);- }- else- matchingpath = cc;- }- }- else- {- SLJIT_ASSERT(has_alternatives && *matchingpath >= OP_ASSERT && *matchingpath <= OP_ASSERTBACK_NOT);- /* Similar code as PUSH_BACKTRACK macro. */- assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack));- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- return NULL;- memset(assert, 0, sizeof(assert_backtrack));- assert->common.cc = matchingpath;- BACKTRACK_AS(bracket_backtrack)->u.assert = assert;- matchingpath = compile_assert_matchingpath(common, matchingpath, assert, TRUE);- }- }--compile_matchingpath(common, matchingpath, cc, backtrack);-if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- return NULL;--if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA)- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);--if (opcode == OP_ONCE)- match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);--if (opcode == OP_SCRIPT_RUN)- match_script_run_common(common, private_data_ptr, backtrack);--stacksize = 0;-if (repeat_type == OP_MINUPTO)- {- /* We need to preserve the counter. TMP2 will be used below. */- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);- stacksize++;- }-if (ket != OP_KET || bra != OP_BRA)- stacksize++;-if (offset != 0)- {- if (common->capture_last_ptr != 0)- stacksize++;- if (common->optimized_cbracket[offset >> 1] == 0)- stacksize += 2;- }-if (has_alternatives && opcode != OP_ONCE)- stacksize++;--if (stacksize > 0)- allocate_stack(common, stacksize);--stacksize = 0;-if (repeat_type == OP_MINUPTO)- {- /* TMP2 was set above. */- OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);- stacksize++;- }--if (ket != OP_KET || bra != OP_BRA)- {- if (ket != OP_KET)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);- else- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);- stacksize++;- }--if (offset != 0)- stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);--/* Skip and count the other alternatives. */-i = 1;-while (*cc == OP_ALT)- {- cc += GET(cc, 1);- i++;- }--if (has_alternatives)- {- if (opcode != OP_ONCE)- {- if (i <= 3)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);- else- BACKTRACK_AS(bracket_backtrack)->u.matching_put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));- }- if (ket != OP_KETRMAX)- BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();- }--/* Must be after the matchingpath label. */-if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0)- {- SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);- }--if (ket == OP_KETRMAX)- {- if (repeat_type != 0)- {- if (has_alternatives)- BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();- 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)- free_stack(common, 1);- }- else if (opcode < OP_BRA || opcode >= OP_SBRA)- {- if (has_alternatives)- BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();-- /* Checking zero-length iteration. */- if (opcode != OP_ONCE)- {- /* This case includes opcodes such as OP_SCRIPT_RUN. */- CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0, rmax_label);- /* Drop STR_PTR for greedy plus quantifier. */- if (bra != OP_BRAZERO)- free_stack(common, 1);- }- else- /* TMP2 must contain the starting STR_PTR. */- CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label);- }- else- JUMPTO(SLJIT_JUMP, rmax_label);- BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();- }--if (repeat_type == OP_EXACT)- {- count_match(common);- 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)- {- /* We need to preserve the counter. */- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);- }--if (bra == OP_BRAZERO)- BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();--if (bra == OP_BRAMINZERO)- {- /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */- JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath);- if (braminzero != NULL)- {- JUMPHERE(braminzero);- /* We need to release the end pointer to perform the- backtrack for the zero-length iteration. When- framesize is < 0, OP_ONCE will do the release itself. */- if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0)- {- 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, (BACKTRACK_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw));- }- else if (ket == OP_KETRMIN && opcode != OP_ONCE)- free_stack(common, 1);- }- /* Continue to the normal backtrack. */- }--if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)- count_match(common);--cc += 1 + LINK_SIZE;--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 = (int)((unsigned)BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);- }-return cc + repeat_length;-}--static PCRE2_SPTR compile_bracketpos_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)-{-DEFINE_COMPILER;-backtrack_common *backtrack;-PCRE2_UCHAR opcode;-int private_data_ptr;-int cbraprivptr = 0;-BOOL needs_control_head;-int framesize;-int stacksize;-int offset = 0;-BOOL zero = FALSE;-PCRE2_SPTR ccbegin = NULL;-int stack; /* Also contains the offset of control head. */-struct sljit_label *loop = NULL;-struct jump_list *emptymatch = NULL;--PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL);-if (*cc == OP_BRAPOSZERO)- {- zero = TRUE;- cc++;- }--opcode = *cc;-private_data_ptr = PRIVATE_DATA(cc);-SLJIT_ASSERT(private_data_ptr != 0);-BACKTRACK_AS(bracketpos_backtrack)->private_data_ptr = private_data_ptr;-switch(opcode)- {- case OP_BRAPOS:- case OP_SBRAPOS:- ccbegin = cc + 1 + LINK_SIZE;- break;-- case OP_CBRAPOS:- case OP_SCBRAPOS:- offset = GET2(cc, 1 + LINK_SIZE);- /* This case cannot be optimized in the same was as- normal capturing brackets. */- SLJIT_ASSERT(common->optimized_cbracket[offset] == 0);- cbraprivptr = OVECTOR_PRIV(offset);- offset <<= 1;- ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;- break;-- default:- SLJIT_UNREACHABLE();- break;- }--framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);-BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize;-if (framesize < 0)- {- if (offset != 0)- {- stacksize = 2;- if (common->capture_last_ptr != 0)- stacksize++;- }- else- stacksize = 1;-- if (needs_control_head)- stacksize++;- if (!zero)- stacksize++;-- BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;- allocate_stack(common, stacksize);- if (framesize == no_frame)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);-- stack = 0;- if (offset != 0)- {- stack = 2;- 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), STACK(0), TMP1, 0);- if (common->capture_last_ptr != 0)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);- if (needs_control_head)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);- if (common->capture_last_ptr != 0)- {- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);- stack = 3;- }- }- else- {- 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);- stack = 1;- }-- if (needs_control_head)- stack++;- if (!zero)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), SLJIT_IMM, 1);- if (needs_control_head)- {- stack--;- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);- }- }-else- {- stacksize = framesize + 1;- if (!zero)- stacksize++;- if (needs_control_head)- stacksize++;- if (offset == 0)- stacksize++;- BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;-- allocate_stack(common, stacksize);- 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_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));-- stack = 0;- if (!zero)- {- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);- stack = 1;- }- if (needs_control_head)- {- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);- stack++;- }- if (offset == 0)- {- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);- stack++;- }- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);- init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize);- stack -= 1 + (offset == 0);- }--if (offset != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);--loop = LABEL();-while (*cc != OP_KETRPOS)- {- backtrack->top = NULL;- backtrack->topbacktracks = NULL;- cc += GET(cc, 1);-- compile_matchingpath(common, ccbegin, cc, backtrack);- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- return NULL;-- if (framesize < 0)- {- if (framesize == no_frame)- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);-- if (offset != 0)- {- 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);- if (common->capture_last_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);- }- else- {- if (opcode == OP_SBRAPOS)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);- }-- /* Even if the match is empty, we need to reset the control head. */- if (needs_control_head)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));-- if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)- add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));-- if (!zero)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);- }- else- {- if (offset != 0)- {- 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);- if (common->capture_last_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);- }- else- {- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- 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), 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. */- if (needs_control_head)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));-- if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)- add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));-- if (!zero)- {- if (framesize < 0)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);- else- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);- }- }-- JUMPTO(SLJIT_JUMP, loop);- flush_stubs(common);-- compile_backtrackingpath(common, backtrack->top);- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- return NULL;- set_jumps(backtrack->topbacktracks, LABEL());-- if (framesize < 0)- {- if (offset != 0)- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);- else- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- }- else- {- if (offset != 0)- {- /* Last alternative. */- if (*cc == OP_KETRPOS)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);- }- else- {- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));- }- }-- if (*cc == OP_KETRPOS)- break;- ccbegin = cc + 1 + LINK_SIZE;- }--/* We don't have to restore the control head in case of a failed match. */--backtrack->topbacktracks = NULL;-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), STACK(-stacksize), SLJIT_IMM, 0));- }--/* None of them matched. */-set_jumps(emptymatch, LABEL());-count_match(common);-return cc + 1 + LINK_SIZE;-}--static SLJIT_INLINE PCRE2_SPTR get_iterator_parameters(compiler_common *common, PCRE2_SPTR cc, PCRE2_UCHAR *opcode, PCRE2_UCHAR *type, sljit_u32 *max, sljit_u32 *exact, PCRE2_SPTR *end)-{-int class_len;--*opcode = *cc;-*exact = 0;--if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)- {- cc++;- *type = OP_CHAR;- }-else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI)- {- cc++;- *type = OP_CHARI;- *opcode -= OP_STARI - OP_STAR;- }-else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO)- {- cc++;- *type = OP_NOT;- *opcode -= OP_NOTSTAR - OP_STAR;- }-else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI)- {- cc++;- *type = OP_NOTI;- *opcode -= OP_NOTSTARI - OP_STAR;- }-else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)- {- cc++;- *opcode -= OP_TYPESTAR - OP_STAR;- *type = OP_END;- }-else- {- SLJIT_ASSERT(*opcode == OP_CLASS || *opcode == OP_NCLASS || *opcode == OP_XCLASS);- *type = *opcode;- cc++;- class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(PCRE2_UCHAR))) : GET(cc, 0);- *opcode = cc[class_len - 1];-- if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)- {- *opcode -= OP_CRSTAR - OP_STAR;- *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;- *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));- *exact = GET2(cc, class_len);-- if (*max == 0)- {- if (*opcode == OP_CRPOSRANGE)- *opcode = OP_POSSTAR;- else- *opcode -= OP_CRRANGE - OP_STAR;- }- 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;- }--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 == OP_END)- {- *type = *cc;- *end = next_opcode(common, cc);- cc++;- return cc;- }--*end = cc + 1;-#ifdef SUPPORT_UNICODE-if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);-#endif-return cc;-}--static PCRE2_SPTR compile_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)-{-DEFINE_COMPILER;-backtrack_common *backtrack;-PCRE2_UCHAR opcode;-PCRE2_UCHAR type;-sljit_u32 max = 0, exact;-sljit_s32 early_fail_ptr = PRIVATE_DATA(cc + 1);-sljit_s32 early_fail_type;-BOOL charpos_enabled;-PCRE2_UCHAR charpos_char;-unsigned int charpos_othercasebit;-PCRE2_SPTR 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;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-BOOL use_tmp;-#endif--PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL);--early_fail_type = (early_fail_ptr & 0x7);-early_fail_ptr >>= 3;--/* During recursion, these optimizations are disabled. */-if (common->early_fail_start_ptr == 0 && common->fast_forward_bc_ptr == NULL)- {- early_fail_ptr = 0;- early_fail_type = type_skip;- }--SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || early_fail_ptr == 0- || (early_fail_ptr >= common->early_fail_start_ptr && early_fail_ptr <= common->early_fail_end_ptr));--if (early_fail_type == type_fail)- add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), early_fail_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;- }--/* Handle fixed part first. */-if (exact > 1)- {- SLJIT_ASSERT(early_fail_ptr == 0);-- if (common->mode == PCRE2_JIT_COMPLETE-#ifdef SUPPORT_UNICODE- && !common->utf-#endif- && type != OP_ANYNL && type != OP_EXTUNI)- {- 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);-- if (early_fail_type == type_fail_range)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + (int)sizeof(sljit_sw));- OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, TMP2, 0);- OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, TMP2, 0);- add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, TMP2, 0, TMP1, 0));-- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + (int)sizeof(sljit_sw), STR_PTR, 0);- }- }--switch(opcode)- {- case OP_STAR:- case OP_UPTO:- SLJIT_ASSERT(early_fail_ptr == 0 || opcode == OP_STAR);-- if (type == OP_ANYNL || type == OP_EXTUNI)- {- SLJIT_ASSERT(private_data_ptr == 0);- SLJIT_ASSERT(early_fail_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)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, max);-- label = LABEL();- 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_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);- }-- /* We cannot use TMP3 because of allocate_stack. */- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);- JUMPTO(SLJIT_JUMP, label);- if (jump != NULL)- JUMPHERE(jump);- BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();- break;- }-#ifdef SUPPORT_UNICODE- else if (type == OP_ALLANY && !common->invalid_utf)-#else- else if (type == OP_ALLANY)-#endif- {- if (opcode == OP_STAR)- {- if (private_data_ptr == 0)- allocate_stack(common, 2);-- OP1(SLJIT_MOV, base, offset0, STR_END, 0);- OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);-- OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);- process_partial_match(common);-- if (early_fail_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_END, 0);- BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();- break;- }-#ifdef SUPPORT_UNICODE- else if (!common->utf)-#else- else-#endif- {- if (private_data_ptr == 0)- allocate_stack(common, 2);-- OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));-- if (common->mode == PCRE2_JIT_COMPLETE)- {- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);- CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);- }- else- {- jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);- process_partial_match(common);- JUMPHERE(jump);- }-- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);-- if (early_fail_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);- BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();- break;- }- }-- charpos_enabled = FALSE;- charpos_char = 0;- charpos_othercasebit = 0;-- if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))- {-#ifdef SUPPORT_UNICODE- charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);-#else- charpos_enabled = TRUE;-#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];- /* Consume the OP_CHAR opcode. */- end += 2;-#if PCRE2_CODE_UNIT_WIDTH == 8- SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);-#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32- 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 (early_fail_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_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);-- 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 (early_fail_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_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);- JUMPTO(SLJIT_JUMP, label);- }- else- {- jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char);- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);- JUMPHERE(jump);- 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());- OP2(SLJIT_ADD, STR_PTR, 0, base, offset0, SLJIT_IMM, IN_UCHARS(1));- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);- }- else- {- if (private_data_ptr == 0)- allocate_stack(common, 2);-- OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- use_tmp = (!HAS_VIRTUAL_REGISTERS && opcode == OP_STAR);- SLJIT_ASSERT(!use_tmp || tmp_base == TMP3);-- if (common->utf)- OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0);-#endif- if (opcode == OP_UPTO)- OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);-- detect_partial_match(common, &no_match);- label = LABEL();- compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf)- OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0);-#endif-- 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));- }-- detect_partial_match_to(common, label);- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));-- set_jumps(no_char1_match, LABEL());-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf)- {- set_jumps(no_match, LABEL());- if (use_tmp)- {- OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);- OP1(SLJIT_MOV, base, offset0, TMP3, 0);- }- else- OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);- }- else-#endif- {- 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 (early_fail_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);- }-- BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();- break;-- case OP_MINSTAR:- if (private_data_ptr == 0)- allocate_stack(common, 1);- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);- BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();- if (early_fail_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);- break;-- case OP_MINUPTO:- SLJIT_ASSERT(early_fail_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, max + 1);- BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();- break;-- case OP_QUERY:- case OP_MINQUERY:- SLJIT_ASSERT(early_fail_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_AS(char_iterator_backtrack)->u.backtracks, TRUE);- BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();- break;-- case OP_EXACT:- break;-- case OP_POSSTAR:-#if defined SUPPORT_UNICODE- if (type == OP_ALLANY && !common->invalid_utf)-#else- if (type == OP_ALLANY)-#endif- {- OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);- process_partial_match(common);- if (early_fail_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_END, 0);- break;- }--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf)- {- OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);- detect_partial_match(common, &no_match);- label = LABEL();- compile_char1_matchingpath(common, type, cc, &no_match, FALSE);- OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);- detect_partial_match_to(common, label);-- set_jumps(no_match, LABEL());- OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);- if (early_fail_ptr != 0)- {- if (!HAS_VIRTUAL_REGISTERS && tmp_base == TMP3)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, TMP3, 0);- else- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);- }- break;- }-#endif-- detect_partial_match(common, &no_match);- label = LABEL();- compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);- detect_partial_match_to(common, 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());- if (early_fail_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);- break;-- case OP_POSUPTO:- SLJIT_ASSERT(early_fail_ptr == 0);-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf)- {- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);- OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);-- detect_partial_match(common, &no_match);- label = LABEL();- compile_char1_matchingpath(common, type, cc, &no_match, FALSE);- 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);- add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));- detect_partial_match_to(common, label);-- set_jumps(no_match, LABEL());- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);- break;- }-#endif-- if (type == OP_ALLANY)- {- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));-- if (common->mode == PCRE2_JIT_COMPLETE)- {- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);- CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);- }- else- {- jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);- process_partial_match(common);- JUMPHERE(jump);- }- break;- }-- OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);-- detect_partial_match(common, &no_match);- label = LABEL();- 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);- add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));- detect_partial_match_to(common, 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;-- case OP_POSQUERY:- SLJIT_ASSERT(early_fail_ptr == 0);- OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);- compile_char1_matchingpath(common, type, cc, &no_match, TRUE);- OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);- set_jumps(no_match, LABEL());- OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);- break;-- default:- SLJIT_UNREACHABLE();- break;- }--count_match(common);-return end;-}--static SLJIT_INLINE PCRE2_SPTR compile_fail_accept_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)-{-DEFINE_COMPILER;-backtrack_common *backtrack;--PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);--if (*cc == OP_FAIL)- {- add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));- return cc + 1;- }--if (*cc == OP_ACCEPT && common->currententry == NULL && (common->re->overall_options & PCRE2_ENDANCHORED) != 0)- add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0));--if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL || !common->might_be_empty)- {- /* No need to check notempty conditions. */- if (common->accept_label == NULL)- add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));- else- JUMPTO(SLJIT_JUMP, common->accept_label);- return cc + 1;- }--if (common->accept_label == NULL)- add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)));-else- CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label);--if (HAS_VIRTUAL_REGISTERS)- {- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));- }-else- OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options));--OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);-add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_NOT_ZERO));-OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);-if (common->accept_label == NULL)- add_jump(compiler, &common->accept, JUMP(SLJIT_ZERO));-else- JUMPTO(SLJIT_ZERO, common->accept_label);--OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));-if (common->accept_label == NULL)- add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0));-else- CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->accept_label);-add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));-return cc + 1;-}--static SLJIT_INLINE PCRE2_SPTR compile_close_matchingpath(compiler_common *common, PCRE2_SPTR cc)-{-DEFINE_COMPILER;-int offset = GET2(cc, 1);-BOOL optimized_cbracket = common->optimized_cbracket[offset] != 0;--/* Data will be discarded anyway... */-if (common->currententry != NULL)- return cc + 1 + IMM2_SIZE;--if (!optimized_cbracket)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR_PRIV(offset));-offset <<= 1;-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);-if (!optimized_cbracket)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);-return cc + 1 + IMM2_SIZE;-}--static SLJIT_INLINE PCRE2_SPTR compile_control_verb_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)-{-DEFINE_COMPILER;-backtrack_common *backtrack;-PCRE2_UCHAR opcode = *cc;-PCRE2_SPTR ccend = cc + 1;--if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG ||- opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)- ccend += 2 + cc[1];--PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);--if (opcode == OP_SKIP)- {- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);- return ccend;- }--if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)- {- if (HAS_VIRTUAL_REGISTERS)- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);- }--return ccend;-}--static PCRE2_UCHAR then_trap_opcode[1] = { OP_THEN_TRAP };--static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, backtrack_common *parent)-{-DEFINE_COMPILER;-backtrack_common *backtrack;-BOOL needs_control_head;-int size;--PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);-common->then_trap = BACKTRACK_AS(then_trap_backtrack);-BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;-BACKTRACK_AS(then_trap_backtrack)->start = (sljit_sw)(cc - common->start);-BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head);--size = BACKTRACK_AS(then_trap_backtrack)->framesize;-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_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);-OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap);-OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0);--size = BACKTRACK_AS(then_trap_backtrack)->framesize;-if (size >= 0)- init_frame(common, cc, ccend, size - 1, 0);-}--static void compile_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, backtrack_common *parent)-{-DEFINE_COMPILER;-backtrack_common *backtrack;-BOOL has_then_trap = FALSE;-then_trap_backtrack *save_then_trap = NULL;--SLJIT_ASSERT(*ccend == OP_END || (*ccend >= OP_ALT && *ccend <= OP_KETRPOS));--if (common->has_then && common->then_offsets[cc - common->start] != 0)- {- SLJIT_ASSERT(*ccend != OP_END && common->control_head_ptr != 0);- has_then_trap = TRUE;- save_then_trap = common->then_trap;- /* Tail item on backtrack. */- compile_then_trap_matchingpath(common, cc, ccend, parent);- }--while (cc < ccend)- {- switch(*cc)- {- case OP_SOD:- 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:- case OP_WHITESPACE:- case OP_NOT_WORDCHAR:- case OP_WORDCHAR:- case OP_ANY:- case OP_ALLANY:- case OP_ANYBYTE:- case OP_NOTPROP:- case OP_PROP:- case OP_ANYNL:- case OP_NOT_HSPACE:- case OP_HSPACE:- case OP_NOT_VSPACE:- case OP_VSPACE:- case OP_EXTUNI:- case OP_NOT:- case OP_NOTI:- cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);- break;-- case OP_SET_SOM:- PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);- cc++;- break;-- case OP_CHAR:- case OP_CHARI:- if (common->mode == PCRE2_JIT_COMPLETE)- 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, TRUE);- break;-- case OP_STAR:- case OP_MINSTAR:- case OP_PLUS:- case OP_MINPLUS:- case OP_QUERY:- case OP_MINQUERY:- case OP_UPTO:- case OP_MINUPTO:- case OP_EXACT:- case OP_POSSTAR:- case OP_POSPLUS:- case OP_POSQUERY:- case OP_POSUPTO:- case OP_STARI:- case OP_MINSTARI:- case OP_PLUSI:- case OP_MINPLUSI:- case OP_QUERYI:- case OP_MINQUERYI:- case OP_UPTOI:- case OP_MINUPTOI:- case OP_EXACTI:- case OP_POSSTARI:- case OP_POSPLUSI:- case OP_POSQUERYI:- case OP_POSUPTOI:- case OP_NOTSTAR:- case OP_NOTMINSTAR:- case OP_NOTPLUS:- case OP_NOTMINPLUS:- case OP_NOTQUERY:- case OP_NOTMINQUERY:- case OP_NOTUPTO:- case OP_NOTMINUPTO:- case OP_NOTEXACT:- case OP_NOTPOSSTAR:- case OP_NOTPOSPLUS:- case OP_NOTPOSQUERY:- case OP_NOTPOSUPTO:- case OP_NOTSTARI:- case OP_NOTMINSTARI:- case OP_NOTPLUSI:- case OP_NOTMINPLUSI:- case OP_NOTQUERYI:- case OP_NOTMINQUERYI:- case OP_NOTUPTOI:- case OP_NOTMINUPTOI:- case OP_NOTEXACTI:- case OP_NOTPOSSTARI:- case OP_NOTPOSPLUSI:- case OP_NOTPOSQUERYI:- case OP_NOTPOSUPTOI:- case OP_TYPESTAR:- case OP_TYPEMINSTAR:- case OP_TYPEPLUS:- case OP_TYPEMINPLUS:- case OP_TYPEQUERY:- case OP_TYPEMINQUERY:- case OP_TYPEUPTO:- case OP_TYPEMINUPTO:- case OP_TYPEEXACT:- case OP_TYPEPOSSTAR:- case OP_TYPEPOSPLUS:- case OP_TYPEPOSQUERY:- case OP_TYPEPOSUPTO:- cc = compile_iterator_matchingpath(common, cc, parent);- break;-- case OP_CLASS:- case OP_NCLASS:- if (cc[1 + (32 / sizeof(PCRE2_UCHAR))] >= OP_CRSTAR && cc[1 + (32 / sizeof(PCRE2_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, TRUE);- break;--#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32- case OP_XCLASS:- 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, TRUE);- break;-#endif-- case OP_REF:- case OP_REFI:- if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRPOSRANGE)- cc = compile_ref_iterator_matchingpath(common, cc, parent);- else- {- compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);- cc += 1 + IMM2_SIZE;- }- break;-- case OP_DNREF:- case OP_DNREFI:- if (cc[1 + 2 * IMM2_SIZE] >= OP_CRSTAR && cc[1 + 2 * IMM2_SIZE] <= OP_CRPOSRANGE)- cc = compile_ref_iterator_matchingpath(common, cc, parent);- else- {- compile_dnref_search(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);- compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);- cc += 1 + 2 * IMM2_SIZE;- }- break;-- case OP_RECURSE:- cc = compile_recurse_matchingpath(common, cc, parent);- break;-- case OP_CALLOUT:- case OP_CALLOUT_STR:- cc = compile_callout_matchingpath(common, cc, parent);- break;-- case OP_ASSERT:- case OP_ASSERT_NOT:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT:- PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);- cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);- break;-- case OP_BRAMINZERO:- PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc);- cc = bracketend(cc + 1);- if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)- {- allocate_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);- }- else- {- allocate_stack(common, 2);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);- }- BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL();- count_match(common);- break;-- case OP_ASSERT_NA:- case OP_ASSERTBACK_NA:- case OP_ONCE:- case OP_SCRIPT_RUN:- case OP_BRA:- case OP_CBRA:- case OP_COND:- case OP_SBRA:- case OP_SCBRA:- case OP_SCOND:- cc = compile_bracket_matchingpath(common, cc, parent);- break;-- case OP_BRAZERO:- if (cc[1] > OP_ASSERTBACK_NOT)- cc = compile_bracket_matchingpath(common, cc, parent);- else- {- PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);- cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);- }- break;-- case OP_BRAPOS:- case OP_CBRAPOS:- case OP_SBRAPOS:- case OP_SCBRAPOS:- case OP_BRAPOSZERO:- cc = compile_bracketpos_matchingpath(common, cc, parent);- break;-- case OP_MARK:- PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);- SLJIT_ASSERT(common->mark_ptr != 0);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);- allocate_stack(common, common->has_skip_arg ? 5 : 1);- if (HAS_VIRTUAL_REGISTERS)- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);- if (common->has_skip_arg)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2));- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);- }- cc += 1 + 2 + cc[1];- break;-- case OP_PRUNE:- case OP_PRUNE_ARG:- case OP_SKIP:- case OP_SKIP_ARG:- case OP_THEN:- case OP_THEN_ARG:- case OP_COMMIT:- case OP_COMMIT_ARG:- cc = compile_control_verb_matchingpath(common, cc, parent);- break;-- case OP_FAIL:- case OP_ACCEPT:- case OP_ASSERT_ACCEPT:- cc = compile_fail_accept_matchingpath(common, cc, parent);- break;-- case OP_CLOSE:- cc = compile_close_matchingpath(common, cc);- break;-- case OP_SKIPZERO:- cc = bracketend(cc + 1);- break;-- default:- SLJIT_UNREACHABLE();- return;- }- if (cc == NULL)- return;- }--if (has_then_trap)- {- /* Head item on backtrack. */- PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);- BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;- BACKTRACK_AS(then_trap_backtrack)->then_trap = common->then_trap;- common->then_trap = save_then_trap;- }-SLJIT_ASSERT(cc == ccend);-}--#undef PUSH_BACKTRACK-#undef PUSH_BACKTRACK_NOVALUE-#undef BACKTRACK_AS--#define COMPILE_BACKTRACKINGPATH(current) \- do \- { \- compile_backtrackingpath(common, (current)); \- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \- return; \- } \- while (0)--#define CURRENT_AS(type) ((type *)current)--static void compile_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-DEFINE_COMPILER;-PCRE2_SPTR cc = current->cc;-PCRE2_UCHAR opcode;-PCRE2_UCHAR type;-sljit_u32 max = 0, exact;-struct sljit_label *label = NULL;-struct sljit_jump *jump = NULL;-jump_list *jumplist = NULL;-PCRE2_SPTR 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, &exact, &end);--switch(opcode)- {- case OP_STAR:- case OP_UPTO:- if (type == OP_ANYNL || type == OP_EXTUNI)- {- SLJIT_ASSERT(private_data_ptr == 0);- 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(char_iterator_backtrack)->matchingpath);- }- else- {- if (CURRENT_AS(char_iterator_backtrack)->u.charpos.enabled)- {- OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);- 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);- move_back(common, NULL, TRUE);- CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP2, 0, label);- }- else- {- OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);- jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1);- move_back(common, NULL, TRUE);- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);- JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);- }- JUMPHERE(jump);- if (private_data_ptr == 0)- free_stack(common, 2);- }- break;-- case OP_MINSTAR:- OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);- 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)- free_stack(common, 1);- break;-- case OP_MINUPTO:- OP1(SLJIT_MOV, TMP1, 0, base, offset1);- OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);- OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);- add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO));-- OP1(SLJIT_MOV, base, offset1, TMP1, 0);- 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)- free_stack(common, 2);- break;-- 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(char_iterator_backtrack)->matchingpath);- jump = JUMP(SLJIT_JUMP);- 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(char_iterator_backtrack)->matchingpath);- JUMPHERE(jump);- if (private_data_ptr == 0)- free_stack(common, 1);- break;-- case OP_MINQUERY:- 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, TRUE);- JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);- set_jumps(jumplist, LABEL());- JUMPHERE(jump);- if (private_data_ptr == 0)- free_stack(common, 1);- break;-- case OP_EXACT:- case OP_POSSTAR:- case OP_POSQUERY:- case OP_POSUPTO:- break;-- default:- SLJIT_UNREACHABLE();- break;- }--set_jumps(current->topbacktracks, LABEL());-}--static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-DEFINE_COMPILER;-PCRE2_SPTR cc = current->cc;-BOOL ref = (*cc == OP_REF || *cc == OP_REFI);-PCRE2_UCHAR type;--type = cc[ref ? 1 + IMM2_SIZE : 1 + 2 * IMM2_SIZE];--if ((type & 0x1) == 0)- {- /* Maximize case. */- 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(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(ref_iterator_backtrack)->matchingpath);-set_jumps(current->topbacktracks, LABEL());-free_stack(common, ref ? 2 : 3);-}--static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-DEFINE_COMPILER;-recurse_entry *entry;--if (!CURRENT_AS(recurse_backtrack)->inlined_pattern)- {- entry = CURRENT_AS(recurse_backtrack)->entry;- if (entry->backtrack_label == NULL)- add_jump(compiler, &entry->backtrack_calls, JUMP(SLJIT_FAST_CALL));- else- JUMPTO(SLJIT_FAST_CALL, entry->backtrack_label);- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(recurse_backtrack)->matchingpath);- }-else- compile_backtrackingpath(common, current->top);--set_jumps(current->topbacktracks, LABEL());-}--static void compile_assert_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-DEFINE_COMPILER;-PCRE2_SPTR cc = current->cc;-PCRE2_UCHAR bra = OP_BRA;-struct sljit_jump *brajump = NULL;--SLJIT_ASSERT(*cc != OP_BRAMINZERO);-if (*cc == OP_BRAZERO)- {- bra = *cc;- cc++;- }--if (bra == OP_BRAZERO)- {- SLJIT_ASSERT(current->topbacktracks == NULL);- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- }--if (CURRENT_AS(assert_backtrack)->framesize < 0)- {- set_jumps(current->topbacktracks, LABEL());-- if (bra == OP_BRAZERO)- {- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);- CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);- free_stack(common, 1);- }- return;- }--if (bra == OP_BRAZERO)- {- if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)- {- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);- CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);- free_stack(common, 1);- return;- }- free_stack(common, 1);- brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);- }--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, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(assert_backtrack)->framesize - 1) * sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, TMP1, 0);-- set_jumps(current->topbacktracks, LABEL());- }-else- set_jumps(current->topbacktracks, LABEL());--if (bra == OP_BRAZERO)- {- /* We know there is enough place on the stack. */- 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);- }-}--static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-DEFINE_COMPILER;-int opcode, stacksize, alt_count, alt_max;-int offset = 0;-int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;-int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;-PCRE2_SPTR cc = current->cc;-PCRE2_SPTR ccbegin;-PCRE2_SPTR ccprev;-PCRE2_UCHAR bra = OP_BRA;-PCRE2_UCHAR ket;-assert_backtrack *assert;-BOOL has_alternatives;-BOOL needs_control_head = FALSE;-struct sljit_jump *brazero = NULL;-struct sljit_jump *next_alt = NULL;-struct sljit_jump *once = NULL;-struct sljit_jump *cond = NULL;-struct sljit_label *rmin_label = NULL;-struct sljit_label *exact_label = NULL;-struct sljit_put_label *put_label = NULL;--if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)- {- bra = *cc;- cc++;- }--opcode = *cc;-ccbegin = bracketend(cc) - 1 - LINK_SIZE;-ket = *ccbegin;-if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0)- {- repeat_ptr = PRIVATE_DATA(ccbegin);- repeat_type = PRIVATE_DATA(ccbegin + 2);- repeat_count = PRIVATE_DATA(ccbegin + 3);- SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0);- if (repeat_type == OP_UPTO)- ket = OP_KETRMAX;- if (repeat_type == OP_MINUPTO)- ket = OP_KETRMIN;- }-ccbegin = cc;-cc += GET(cc, 1);-has_alternatives = *cc == OP_ALT;-if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))- has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL;-if (opcode == OP_CBRA || opcode == OP_SCBRA)- offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;-if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))- opcode = OP_SCOND;--alt_max = has_alternatives ? no_alternatives(ccbegin) : 0;--/* Decoding the needs_control_head in framesize. */-if (opcode == OP_ONCE)- {- needs_control_head = (CURRENT_AS(bracket_backtrack)->u.framesize & 0x1) != 0;- CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;- }--if (ket != OP_KET && repeat_type != 0)- {- /* TMP1 is used in OP_KETRMIN below. */- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, 1);- if (repeat_type == OP_UPTO)- OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0, SLJIT_IMM, 1);- else- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0);- }--if (ket == OP_KETRMAX)- {- if (bra == OP_BRAZERO)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, 1);- brazero = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0);- }- }-else if (ket == OP_KETRMIN)- {- if (bra != OP_BRAMINZERO)- {- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- if (repeat_type != 0)- {- /* TMP1 was set a few lines above. */- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);- /* Drop STR_PTR for non-greedy plus quantifier. */- if (opcode != OP_ONCE)- free_stack(common, 1);- }- else if (opcode >= OP_SBRA || opcode == OP_ONCE)- {- /* Checking zero-length iteration. */- if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)- CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);- else- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- 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)- free_stack(common, 1);- }- else- JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);- }- rmin_label = LABEL();- if (repeat_type != 0)- OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);- }-else if (bra == OP_BRAZERO)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, 1);- brazero = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);- }-else if (repeat_type == OP_EXACT)- {- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);- exact_label = LABEL();- }--if (offset != 0)- {- if (common->capture_last_ptr != 0)- {- SLJIT_ASSERT(common->optimized_cbracket[offset >> 1] == 0);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));- free_stack(common, 3);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP2, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);- }- else if (common->optimized_cbracket[offset >> 1] == 0)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));- free_stack(common, 2);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);- }- }--if (SLJIT_UNLIKELY(opcode == OP_ONCE))- {- if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)- {- 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, (CURRENT_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw));- }- once = JUMP(SLJIT_JUMP);- }-else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))- {- if (has_alternatives)- {- /* Always exactly one alternative. */- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, 1);-- alt_max = 2;- next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);- }- }-else if (has_alternatives)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, 1);-- if (alt_max > 3)- {- sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);-- SLJIT_ASSERT(CURRENT_AS(bracket_backtrack)->u.matching_put_label);- sljit_set_put_label(CURRENT_AS(bracket_backtrack)->u.matching_put_label, LABEL());- sljit_emit_op0(compiler, SLJIT_ENDBR);- }- else- next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);- }--COMPILE_BACKTRACKINGPATH(current->top);-if (current->topbacktracks)- set_jumps(current->topbacktracks, LABEL());--if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))- {- /* Conditional block always has at most one alternative. */- if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)- {- SLJIT_ASSERT(has_alternatives);- assert = CURRENT_AS(bracket_backtrack)->u.assert;- if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))- {- 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, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0);- }- cond = JUMP(SLJIT_JUMP);- set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());- }- else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL)- {- SLJIT_ASSERT(has_alternatives);- cond = JUMP(SLJIT_JUMP);- set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL());- }- else- SLJIT_ASSERT(!has_alternatives);- }--if (has_alternatives)- {- alt_count = 1;- do- {- current->top = NULL;- current->topbacktracks = NULL;- current->nextbacktracks = NULL;- /* Conditional blocks always have an additional alternative, even if it is empty. */- if (*cc == OP_ALT)- {- ccprev = cc + 1 + LINK_SIZE;- cc += GET(cc, 1);- if (opcode != OP_COND && opcode != OP_SCOND)- {- if (opcode != OP_ONCE)- {- if (private_data_ptr != 0)- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);- else- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- }- else- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0));- }- compile_matchingpath(common, ccprev, cc, current);- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- return;-- if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA)- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);-- if (opcode == OP_SCRIPT_RUN)- match_script_run_common(common, private_data_ptr, current);- }-- /* Instructions after the current alternative is successfully matched. */- /* There is a similar code in compile_bracket_matchingpath. */- if (opcode == OP_ONCE)- match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);-- stacksize = 0;- if (repeat_type == OP_MINUPTO)- {- /* We need to preserve the counter. TMP2 will be used below. */- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);- stacksize++;- }- if (ket != OP_KET || bra != OP_BRA)- stacksize++;- if (offset != 0)- {- if (common->capture_last_ptr != 0)- stacksize++;- if (common->optimized_cbracket[offset >> 1] == 0)- stacksize += 2;- }- if (opcode != OP_ONCE)- stacksize++;-- if (stacksize > 0)- allocate_stack(common, stacksize);-- stacksize = 0;- if (repeat_type == OP_MINUPTO)- {- /* TMP2 was set above. */- OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);- stacksize++;- }-- if (ket != OP_KET || bra != OP_BRA)- {- if (ket != OP_KET)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);- else- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);- stacksize++;- }-- if (offset != 0)- stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);-- if (opcode != OP_ONCE)- {- if (alt_max <= 3)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);- else- put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));- }-- if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0)- {- /* If ket is not OP_KETRMAX, this code path is executed after the jump to alternative_matchingpath. */- SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);- }-- JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alternative_matchingpath);-- if (opcode != OP_ONCE)- {- if (alt_max <= 3)- {- JUMPHERE(next_alt);- alt_count++;- if (alt_count < alt_max)- {- SLJIT_ASSERT(alt_count == 2 && alt_max == 3);- next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);- }- }- else- {- sljit_set_put_label(put_label, LABEL());- sljit_emit_op0(compiler, SLJIT_ENDBR);- }- }-- COMPILE_BACKTRACKINGPATH(current->top);- if (current->topbacktracks)- set_jumps(current->topbacktracks, LABEL());- SLJIT_ASSERT(!current->nextbacktracks);- }- while (*cc == OP_ALT);-- if (cond != NULL)- {- SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);- assert = CURRENT_AS(bracket_backtrack)->u.assert;- if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)- {- 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, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0);- }- JUMPHERE(cond);- }-- /* Free the STR_PTR. */- if (private_data_ptr == 0)- free_stack(common, 1);- }--if (offset != 0)- {- /* Using both tmp register is better for instruction scheduling. */- if (common->optimized_cbracket[offset >> 1] != 0)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));- free_stack(common, 2);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);- }- else- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);- }- }-else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)- {- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, 1);- }-else if (opcode == OP_ONCE)- {- cc = ccbegin + GET(ccbegin, 1);- stacksize = needs_control_head ? 1 : 0;-- if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)- {- /* Reset head and drop saved frame. */- stacksize += CURRENT_AS(bracket_backtrack)->u.framesize + ((ket != OP_KET || *cc == OP_ALT) ? 2 : 1);- }- else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))- {- /* The STR_PTR must be released. */- 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), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 1));- else if (ket == OP_KETRMIN)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));- /* See the comment below. */- free_stack(common, 2);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);- }- }--if (repeat_type == OP_EXACT)- {- OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0);- CMPTO(SLJIT_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label);- }-else if (ket == OP_KETRMAX)- {- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- if (bra != OP_BRAZERO)- free_stack(common, 1);-- CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);- if (bra == OP_BRAZERO)- {- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));- JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);- JUMPHERE(brazero);- free_stack(common, 1);- }- }-else if (ket == OP_KETRMIN)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));-- /* OP_ONCE removes everything in case of a backtrack, so we don't- need to explicitly release the STR_PTR. The extra release would- affect badly the free_stack(2) above. */- if (opcode != OP_ONCE)- free_stack(common, 1);- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label);- if (opcode == OP_ONCE)- free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);- else if (bra == OP_BRAMINZERO)- free_stack(common, 1);- }-else if (bra == OP_BRAZERO)- {- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);- JUMPHERE(brazero);- }-}--static SLJIT_INLINE void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-DEFINE_COMPILER;-int offset;-struct sljit_jump *jump;--if (CURRENT_AS(bracketpos_backtrack)->framesize < 0)- {- if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)- {- offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1;- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);- if (common->capture_last_ptr != 0)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);- if (common->capture_last_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0);- }- set_jumps(current->topbacktracks, LABEL());- free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);- return;- }--OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr);-add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));-OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(bracketpos_backtrack)->framesize - 1) * sizeof(sljit_sw));--if (current->topbacktracks)- {- jump = JUMP(SLJIT_JUMP);- set_jumps(current->topbacktracks, LABEL());- /* Drop the stack frame. */- 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), STACK(-CURRENT_AS(bracketpos_backtrack)->framesize - 1));-}--static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-assert_backtrack backtrack;--current->top = NULL;-current->topbacktracks = NULL;-current->nextbacktracks = NULL;-if (current->cc[1] > OP_ASSERTBACK_NOT)- {- /* Manual call of compile_bracket_matchingpath and compile_bracket_backtrackingpath. */- compile_bracket_matchingpath(common, current->cc, current);- compile_bracket_backtrackingpath(common, current->top);- }-else- {- memset(&backtrack, 0, sizeof(backtrack));- backtrack.common.cc = current->cc;- backtrack.matchingpath = CURRENT_AS(braminzero_backtrack)->matchingpath;- /* Manual call of compile_assert_matchingpath. */- compile_assert_matchingpath(common, current->cc, &backtrack, FALSE);- }-SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks);-}--static SLJIT_INLINE void compile_control_verb_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-DEFINE_COMPILER;-PCRE2_UCHAR opcode = *current->cc;-struct sljit_label *loop;-struct sljit_jump *jump;--if (opcode == OP_THEN || opcode == OP_THEN_ARG)- {- if (common->then_trap != NULL)- {- SLJIT_ASSERT(common->control_head_ptr != 0);-- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start);- jump = JUMP(SLJIT_JUMP);-- loop = LABEL();- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- JUMPHERE(jump);- 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;- }- else if (!common->local_quit_available && common->in_positive_assertion)- {- add_jump(compiler, &common->positive_assertion_quit, JUMP(SLJIT_JUMP));- return;- }- }--if (common->local_quit_available)- {- /* Abort match with a fail. */- if (common->quit_label == NULL)- add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));- else- JUMPTO(SLJIT_JUMP, common->quit_label);- return;- }--if (opcode == OP_SKIP_ARG)- {- SLJIT_ASSERT(common->control_head_ptr != 0 && TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);- OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_search_mark));-- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_R0, 0);- add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0));- return;- }--if (opcode == OP_SKIP)- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));-else- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0);-add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP));-}--static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-DEFINE_COMPILER;-struct sljit_jump *jump;-int size;--if (CURRENT_AS(then_trap_backtrack)->then_trap)- {- common->then_trap = CURRENT_AS(then_trap_backtrack)->then_trap;- return;- }--size = CURRENT_AS(then_trap_backtrack)->framesize;-size = 3 + (size < 0 ? 0 : size);--OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(size - 3));-free_stack(common, size);-jump = JUMP(SLJIT_JUMP);--set_jumps(CURRENT_AS(then_trap_backtrack)->quit, LABEL());-/* STACK_TOP is set by THEN. */-if (CURRENT_AS(then_trap_backtrack)->framesize >= 0)- {- add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));- OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(then_trap_backtrack)->framesize - 1) * sizeof(sljit_sw));- }-OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));-free_stack(common, 3);--JUMPHERE(jump);-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0);-}--static void compile_backtrackingpath(compiler_common *common, struct backtrack_common *current)-{-DEFINE_COMPILER;-then_trap_backtrack *save_then_trap = common->then_trap;--while (current)- {- if (current->nextbacktracks != NULL)- set_jumps(current->nextbacktracks, LABEL());- switch(*current->cc)- {- case OP_SET_SOM:- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP1, 0);- break;-- case OP_STAR:- case OP_MINSTAR:- case OP_PLUS:- case OP_MINPLUS:- case OP_QUERY:- case OP_MINQUERY:- case OP_UPTO:- case OP_MINUPTO:- case OP_EXACT:- case OP_POSSTAR:- case OP_POSPLUS:- case OP_POSQUERY:- case OP_POSUPTO:- case OP_STARI:- case OP_MINSTARI:- case OP_PLUSI:- case OP_MINPLUSI:- case OP_QUERYI:- case OP_MINQUERYI:- case OP_UPTOI:- case OP_MINUPTOI:- case OP_EXACTI:- case OP_POSSTARI:- case OP_POSPLUSI:- case OP_POSQUERYI:- case OP_POSUPTOI:- case OP_NOTSTAR:- case OP_NOTMINSTAR:- case OP_NOTPLUS:- case OP_NOTMINPLUS:- case OP_NOTQUERY:- case OP_NOTMINQUERY:- case OP_NOTUPTO:- case OP_NOTMINUPTO:- case OP_NOTEXACT:- case OP_NOTPOSSTAR:- case OP_NOTPOSPLUS:- case OP_NOTPOSQUERY:- case OP_NOTPOSUPTO:- case OP_NOTSTARI:- case OP_NOTMINSTARI:- case OP_NOTPLUSI:- case OP_NOTMINPLUSI:- case OP_NOTQUERYI:- case OP_NOTMINQUERYI:- case OP_NOTUPTOI:- case OP_NOTMINUPTOI:- case OP_NOTEXACTI:- case OP_NOTPOSSTARI:- case OP_NOTPOSPLUSI:- case OP_NOTPOSQUERYI:- case OP_NOTPOSUPTOI:- case OP_TYPESTAR:- case OP_TYPEMINSTAR:- case OP_TYPEPLUS:- case OP_TYPEMINPLUS:- case OP_TYPEQUERY:- case OP_TYPEMINQUERY:- case OP_TYPEUPTO:- case OP_TYPEMINUPTO:- case OP_TYPEEXACT:- case OP_TYPEPOSSTAR:- case OP_TYPEPOSPLUS:- case OP_TYPEPOSQUERY:- case OP_TYPEPOSUPTO:- case OP_CLASS:- case OP_NCLASS:-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8- case OP_XCLASS:-#endif- compile_iterator_backtrackingpath(common, current);- break;-- case OP_REF:- case OP_REFI:- case OP_DNREF:- case OP_DNREFI:- compile_ref_iterator_backtrackingpath(common, current);- break;-- case OP_RECURSE:- compile_recurse_backtrackingpath(common, current);- break;-- case OP_ASSERT:- case OP_ASSERT_NOT:- case OP_ASSERTBACK:- case OP_ASSERTBACK_NOT:- compile_assert_backtrackingpath(common, current);- break;-- case OP_ASSERT_NA:- case OP_ASSERTBACK_NA:- case OP_ONCE:- case OP_SCRIPT_RUN:- case OP_BRA:- case OP_CBRA:- case OP_COND:- case OP_SBRA:- case OP_SCBRA:- case OP_SCOND:- compile_bracket_backtrackingpath(common, current);- break;-- case OP_BRAZERO:- if (current->cc[1] > OP_ASSERTBACK_NOT)- compile_bracket_backtrackingpath(common, current);- else- compile_assert_backtrackingpath(common, current);- break;-- case OP_BRAPOS:- case OP_CBRAPOS:- case OP_SBRAPOS:- case OP_SCBRAPOS:- case OP_BRAPOSZERO:- compile_bracketpos_backtrackingpath(common, current);- break;-- case OP_BRAMINZERO:- compile_braminzero_backtrackingpath(common, current);- break;-- case OP_MARK:- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0));- if (common->has_skip_arg)- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- free_stack(common, common->has_skip_arg ? 5 : 1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0);- if (common->has_skip_arg)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0);- break;-- case OP_THEN:- case OP_THEN_ARG:- case OP_PRUNE:- case OP_PRUNE_ARG:- case OP_SKIP:- case OP_SKIP_ARG:- compile_control_verb_backtrackingpath(common, current);- break;-- case OP_COMMIT:- case OP_COMMIT_ARG:- if (!common->local_quit_available)- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);- if (common->quit_label == NULL)- add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));- else- JUMPTO(SLJIT_JUMP, common->quit_label);- break;-- case OP_CALLOUT:- case OP_CALLOUT_STR:- case OP_FAIL:- case OP_ACCEPT:- case OP_ASSERT_ACCEPT:- set_jumps(current->topbacktracks, LABEL());- break;-- case OP_THEN_TRAP:- /* A virtual opcode for then traps. */- compile_then_trap_backtrackingpath(common, current);- break;-- default:- SLJIT_UNREACHABLE();- break;- }- current = current->prev;- }-common->then_trap = save_then_trap;-}--static SLJIT_INLINE void compile_recurse(compiler_common *common)-{-DEFINE_COMPILER;-PCRE2_SPTR cc = common->start + common->currententry->start;-PCRE2_SPTR ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);-PCRE2_SPTR ccend = bracketend(cc) - (1 + LINK_SIZE);-uint32_t recurse_flags = 0;-int private_data_size = get_recurse_data_length(common, ccbegin, ccend, &recurse_flags);-int alt_count, alt_max, local_size;-backtrack_common altbacktrack;-jump_list *match = NULL;-struct sljit_jump *next_alt = NULL;-struct sljit_jump *accept_exit = NULL;-struct sljit_label *quit;-struct sljit_put_label *put_label = NULL;--/* Recurse captures then. */-common->then_trap = NULL;--SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);--alt_max = no_alternatives(cc);-alt_count = 0;--/* Matching path. */-SLJIT_ASSERT(common->currententry->entry_label == NULL && common->recursive_head_ptr != 0);-common->currententry->entry_label = LABEL();-set_jumps(common->currententry->entry_calls, common->currententry->entry_label);--sljit_emit_fast_enter(compiler, TMP2, 0);-count_match(common);--local_size = (alt_max > 1) ? 2 : 1;--/* (Reversed) stack layout:- [private data][return address][optional: str ptr] ... [optional: alternative index][recursive_head_ptr] */--allocate_stack(common, private_data_size + local_size);-/* Save return address. */-OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP2, 0);--copy_recurse_data(common, ccbegin, ccend, recurse_copy_from_global, local_size, private_data_size + local_size, recurse_flags);--/* This variable is saved and restored all time when we enter or exit from a recursive context. */-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0);--if (recurse_flags & recurse_flag_control_head_found)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);--if (alt_max > 1)- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);--memset(&altbacktrack, 0, sizeof(backtrack_common));-common->quit_label = NULL;-common->accept_label = NULL;-common->quit = NULL;-common->accept = NULL;-altbacktrack.cc = ccbegin;-cc += GET(cc, 1);-while (1)- {- altbacktrack.top = NULL;- altbacktrack.topbacktracks = NULL;-- if (altbacktrack.cc != ccbegin)- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));-- compile_matchingpath(common, altbacktrack.cc, cc, &altbacktrack);- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- return;-- allocate_stack(common, (alt_max > 1 || (recurse_flags & recurse_flag_accept_found)) ? 2 : 1);- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);-- if (alt_max > 1 || (recurse_flags & recurse_flag_accept_found))- {- if (alt_max > 3)- put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(1));- else- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);- }-- add_jump(compiler, &match, JUMP(SLJIT_JUMP));-- if (alt_count == 0)- {- /* Backtracking path entry. */- SLJIT_ASSERT(common->currententry->backtrack_label == NULL);- common->currententry->backtrack_label = LABEL();- set_jumps(common->currententry->backtrack_calls, common->currententry->backtrack_label);-- sljit_emit_fast_enter(compiler, TMP1, 0);-- if (recurse_flags & recurse_flag_accept_found)- accept_exit = CMP(SLJIT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);-- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));- /* Save return address. */- OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(local_size - 1), TMP1, 0);-- copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, recurse_flags);-- if (alt_max > 1)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));- free_stack(common, 2);-- if (alt_max > 3)- {- sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);- sljit_set_put_label(put_label, LABEL());- sljit_emit_op0(compiler, SLJIT_ENDBR);- }- else- next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);- }- else- free_stack(common, (recurse_flags & recurse_flag_accept_found) ? 2 : 1);- }- else if (alt_max > 3)- {- sljit_set_put_label(put_label, LABEL());- sljit_emit_op0(compiler, SLJIT_ENDBR);- }- else- {- JUMPHERE(next_alt);- if (alt_count + 1 < alt_max)- {- SLJIT_ASSERT(alt_count == 1 && alt_max == 3);- next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);- }- }-- alt_count++;-- compile_backtrackingpath(common, altbacktrack.top);- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- return;- set_jumps(altbacktrack.topbacktracks, LABEL());-- if (*cc != OP_ALT)- break;-- altbacktrack.cc = cc + 1 + LINK_SIZE;- cc += GET(cc, 1);- }--/* No alternative is matched. */--quit = LABEL();--copy_recurse_data(common, ccbegin, ccend, recurse_copy_private_to_global, local_size, private_data_size + local_size, recurse_flags);--OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1));-free_stack(common, private_data_size + local_size);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);-OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);--if (common->quit != NULL)- {- SLJIT_ASSERT(recurse_flags & recurse_flag_quit_found);-- set_jumps(common->quit, LABEL());- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);- copy_recurse_data(common, ccbegin, ccend, recurse_copy_shared_to_global, local_size, private_data_size + local_size, recurse_flags);- JUMPTO(SLJIT_JUMP, quit);- }--if (recurse_flags & recurse_flag_accept_found)- {- JUMPHERE(accept_exit);- free_stack(common, 2);-- /* Save return address. */- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP1, 0);-- copy_recurse_data(common, ccbegin, ccend, recurse_copy_kept_shared_to_global, local_size, private_data_size + local_size, recurse_flags);-- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1));- free_stack(common, private_data_size + local_size);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);- OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);- }--if (common->accept != NULL)- {- SLJIT_ASSERT(recurse_flags & recurse_flag_accept_found);-- set_jumps(common->accept, LABEL());-- OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);- OP1(SLJIT_MOV, TMP2, 0, STACK_TOP, 0);-- allocate_stack(common, 2);- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);- }--set_jumps(match, LABEL());--OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);--copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, recurse_flags);--OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), STACK(local_size - 1));-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);-OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);-}--#undef COMPILE_BACKTRACKINGPATH-#undef CURRENT_AS--#define PUBLIC_JIT_COMPILE_CONFIGURATION_OPTIONS \- (PCRE2_JIT_INVALID_UTF)--static int jit_compile(pcre2_code *code, sljit_u32 mode)-{-pcre2_real_code *re = (pcre2_real_code *)code;-struct sljit_compiler *compiler;-backtrack_common rootbacktrack;-compiler_common common_data;-compiler_common *common = &common_data;-const sljit_u8 *tables = re->tables;-void *allocator_data = &re->memctl;-int private_data_size;-PCRE2_SPTR ccend;-executable_functions *functions;-void *executable_func;-sljit_uw executable_size;-sljit_uw total_length;-struct sljit_label *mainloop_label = NULL;-struct sljit_label *continue_match_label;-struct sljit_label *empty_match_found_label = NULL;-struct sljit_label *empty_match_backtrack_label = NULL;-struct sljit_label *reset_match_label;-struct sljit_label *quit_label;-struct sljit_jump *jump;-struct sljit_jump *minlength_check_failed = NULL;-struct sljit_jump *empty_match = NULL;-struct sljit_jump *end_anchor_failed = NULL;-jump_list *reqcu_not_found = NULL;--SLJIT_ASSERT(tables);--#if HAS_VIRTUAL_REGISTERS == 1-SLJIT_ASSERT(sljit_get_register_index(TMP3) < 0 && sljit_get_register_index(ARGUMENTS) < 0 && sljit_get_register_index(RETURN_ADDR) < 0);-#elif HAS_VIRTUAL_REGISTERS == 0-SLJIT_ASSERT(sljit_get_register_index(TMP3) >= 0 && sljit_get_register_index(ARGUMENTS) >= 0 && sljit_get_register_index(RETURN_ADDR) >= 0);-#else-#error "Invalid value for HAS_VIRTUAL_REGISTERS"-#endif--memset(&rootbacktrack, 0, sizeof(backtrack_common));-memset(common, 0, sizeof(compiler_common));-common->re = re;-common->name_table = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));-rootbacktrack.cc = common->name_table + re->name_count * re->name_entry_size;--#ifdef SUPPORT_UNICODE-common->invalid_utf = (mode & PCRE2_JIT_INVALID_UTF) != 0;-#endif /* SUPPORT_UNICODE */-mode &= ~PUBLIC_JIT_COMPILE_CONFIGURATION_OPTIONS;--common->start = rootbacktrack.cc;-common->read_only_data_head = NULL;-common->fcc = tables + fcc_offset;-common->lcc = (sljit_sw)(tables + lcc_offset);-common->mode = mode;-common->might_be_empty = (re->minlength == 0) || (re->flags & PCRE2_MATCH_EMPTY);-common->allow_empty_partial = (re->max_lookbehind > 0) || (re->flags & PCRE2_MATCH_EMPTY);-common->nltype = NLTYPE_FIXED;-switch(re->newline_convention)- {- case PCRE2_NEWLINE_CR: common->newline = CHAR_CR; break;- case PCRE2_NEWLINE_LF: common->newline = CHAR_NL; break;- case PCRE2_NEWLINE_CRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;- case PCRE2_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;- case PCRE2_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;- case PCRE2_NEWLINE_NUL: common->newline = CHAR_NUL; break;- default: return PCRE2_ERROR_INTERNAL;- }-common->nlmax = READ_CHAR_MAX;-common->nlmin = 0;-if (re->bsr_convention == PCRE2_BSR_UNICODE)- common->bsr_nltype = NLTYPE_ANY;-else if (re->bsr_convention == PCRE2_BSR_ANYCRLF)- common->bsr_nltype = NLTYPE_ANYCRLF;-else- {-#ifdef BSR_ANYCRLF- common->bsr_nltype = NLTYPE_ANYCRLF;-#else- common->bsr_nltype = NLTYPE_ANY;-#endif- }-common->bsr_nlmax = READ_CHAR_MAX;-common->bsr_nlmin = 0;-common->endonly = (re->overall_options & PCRE2_DOLLAR_ENDONLY) != 0;-common->ctypes = (sljit_sw)(tables + ctypes_offset);-common->name_count = re->name_count;-common->name_entry_size = re->name_entry_size;-common->unset_backref = (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) != 0;-common->alt_circumflex = (re->overall_options & PCRE2_ALT_CIRCUMFLEX) != 0;-#ifdef SUPPORT_UNICODE-/* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */-common->utf = (re->overall_options & PCRE2_UTF) != 0;-common->ucp = (re->overall_options & PCRE2_UCP) != 0;-if (common->utf)- {- if (common->nltype == NLTYPE_ANY)- common->nlmax = 0x2029;- else if (common->nltype == NLTYPE_ANYCRLF)- common->nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;- else- {- /* We only care about the first newline character. */- common->nlmax = common->newline & 0xff;- }-- if (common->nltype == NLTYPE_FIXED)- common->nlmin = common->newline & 0xff;- else- common->nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;-- if (common->bsr_nltype == NLTYPE_ANY)- common->bsr_nlmax = 0x2029;- else- common->bsr_nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;- common->bsr_nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;- }-else- common->invalid_utf = FALSE;-#endif /* SUPPORT_UNICODE */-ccend = bracketend(common->start);--/* Calculate the local space size on the stack. */-common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw);-common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, allocator_data);-if (!common->optimized_cbracket)- return PCRE2_ERROR_NOMEMORY;-#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1-memset(common->optimized_cbracket, 0, re->top_bracket + 1);-#else-memset(common->optimized_cbracket, 1, re->top_bracket + 1);-#endif--SLJIT_ASSERT(*common->start == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);-#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 2-common->capture_last_ptr = common->ovector_start;-common->ovector_start += sizeof(sljit_sw);-#endif-if (!check_opcode_types(common, common->start, ccend))- {- SLJIT_FREE(common->optimized_cbracket, allocator_data);- return PCRE2_ERROR_NOMEMORY;- }--/* Checking flags and updating ovector_start. */-if (mode == PCRE2_JIT_COMPLETE && (re->flags & PCRE2_LASTSET) != 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)- {- common->req_char_ptr = common->ovector_start;- common->ovector_start += sizeof(sljit_sw);- }-if (mode != PCRE2_JIT_COMPLETE)- {- common->start_used_ptr = common->ovector_start;- common->ovector_start += sizeof(sljit_sw);- if (mode == PCRE2_JIT_PARTIAL_SOFT)- {- common->hit_start = common->ovector_start;- common->ovector_start += sizeof(sljit_sw);- }- }-if ((re->overall_options & (PCRE2_FIRSTLINE | PCRE2_USE_OFFSET_LIMIT)) != 0)- {- common->match_end_ptr = common->ovector_start;- common->ovector_start += sizeof(sljit_sw);- }-#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD-common->control_head_ptr = 1;-#endif-if (common->control_head_ptr != 0)- {- common->control_head_ptr = common->ovector_start;- common->ovector_start += sizeof(sljit_sw);- }-if (common->has_set_som)- {- /* Saving the real start pointer is necessary. */- common->start_ptr = common->ovector_start;- common->ovector_start += sizeof(sljit_sw);- }--/* Aligning ovector to even number of sljit words. */-if ((common->ovector_start & sizeof(sljit_sw)) != 0)- common->ovector_start += sizeof(sljit_sw);--if (common->start_ptr == 0)- common->start_ptr = OVECTOR(0);--/* Capturing brackets cannot be optimized if callouts are allowed. */-if (common->capture_last_ptr != 0)- memset(common->optimized_cbracket, 0, re->top_bracket + 1);--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_s32*)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data);-if (!common->private_data_ptrs)- {- SLJIT_FREE(common->optimized_cbracket, allocator_data);- return PCRE2_ERROR_NOMEMORY;- }-memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32));--private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);--if ((re->overall_options & PCRE2_ANCHORED) == 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 && !common->has_skip_in_assert_back)- detect_early_fail(common, common->start, &private_data_size, 0, 0, TRUE);--set_private_data_ptrs(common, &private_data_size, ccend);--SLJIT_ASSERT(common->early_fail_start_ptr <= common->early_fail_end_ptr);--if (private_data_size > SLJIT_MAX_LOCAL_SIZE)- {- SLJIT_FREE(common->private_data_ptrs, allocator_data);- SLJIT_FREE(common->optimized_cbracket, allocator_data);- return PCRE2_ERROR_NOMEMORY;- }--if (common->has_then)- {- 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);- }--compiler = sljit_create_compiler(allocator_data, NULL);-if (!compiler)- {- SLJIT_FREE(common->optimized_cbracket, allocator_data);- SLJIT_FREE(common->private_data_ptrs, allocator_data);- return PCRE2_ERROR_NOMEMORY;- }-common->compiler = compiler;--/* Main pcre2_jit_exec entry. */-SLJIT_ASSERT((private_data_size & (sizeof(sljit_sw) - 1)) == 0);-sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 5, 5, 0, 0, private_data_size);--/* Register init. */-reset_ovector(common, (re->top_bracket + 1) * 2);-if (common->req_char_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, SLJIT_R0, 0);--OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_S0, 0);-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_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, end));-OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, start));-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);--if (common->early_fail_start_ptr < common->early_fail_end_ptr)- reset_early_fail(common);--if (mode == PCRE2_JIT_PARTIAL_SOFT)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);-if (common->mark_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);-if (common->control_head_ptr != 0)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);--/* Main part of the matching */-if ((re->overall_options & PCRE2_ANCHORED) == 0)- {- mainloop_label = mainloop_entry(common);- continue_match_label = LABEL();- /* Forward search if possible. */- if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)- {- if (mode == PCRE2_JIT_COMPLETE && fast_forward_first_n_chars(common))- ;- else if ((re->flags & PCRE2_FIRSTSET) != 0)- fast_forward_first_char(common);- else if ((re->flags & PCRE2_STARTLINE) != 0)- fast_forward_newline(common);- else if ((re->flags & PCRE2_FIRSTMAPSET) != 0)- fast_forward_start_bits(common);- }- }-else- continue_match_label = LABEL();--if (mode == PCRE2_JIT_COMPLETE && re->minlength > 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)- {- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);- OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(re->minlength));- minlength_check_failed = CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0);- }-if (common->req_char_ptr != 0)- reqcu_not_found = search_requested_char(common, (PCRE2_UCHAR)(re->last_codeunit), (re->flags & PCRE2_LASTCASELESS) != 0, (re->flags & PCRE2_FIRSTSET) != 0);--/* Store the current STR_PTR in OVECTOR(0). */-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);-/* Copy the limit of allowed recursions. */-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, 0);-if (common->fast_forward_bc_ptr != NULL)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1) >> 3, STR_PTR, 0);--if (common->start_ptr != OVECTOR(0))- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0);--/* Copy the beginning of the string. */-if (mode == PCRE2_JIT_PARTIAL_SOFT)- {- jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);- JUMPHERE(jump);- }-else if (mode == PCRE2_JIT_PARTIAL_HARD)- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);--compile_matchingpath(common, common->start, ccend, &rootbacktrack);-if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- {- sljit_free_compiler(compiler);- SLJIT_FREE(common->optimized_cbracket, allocator_data);- SLJIT_FREE(common->private_data_ptrs, allocator_data);- PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);- return PCRE2_ERROR_NOMEMORY;- }--if ((re->overall_options & PCRE2_ENDANCHORED) != 0)- end_anchor_failed = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0);--if (common->might_be_empty)- {- empty_match = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));- empty_match_found_label = LABEL();- }--common->accept_label = LABEL();-if (common->accept != NULL)- set_jumps(common->accept, common->accept_label);--/* This means we have a match. Update the ovector. */-copy_ovector(common, re->top_bracket + 1);-common->quit_label = common->abort_label = LABEL();-if (common->quit != NULL)- set_jumps(common->quit, common->quit_label);-if (common->abort != NULL)- set_jumps(common->abort, common->abort_label);-if (minlength_check_failed != NULL)- SET_LABEL(minlength_check_failed, common->abort_label);--sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN);-sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);--if (common->failed_match != NULL)- {- SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);- set_jumps(common->failed_match, LABEL());- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);- JUMPTO(SLJIT_JUMP, common->abort_label);- }--if ((re->overall_options & PCRE2_ENDANCHORED) != 0)- JUMPHERE(end_anchor_failed);--if (mode != PCRE2_JIT_COMPLETE)- {- common->partialmatchlabel = LABEL();- set_jumps(common->partialmatch, common->partialmatchlabel);- return_with_partial_match(common, common->quit_label);- }--if (common->might_be_empty)- empty_match_backtrack_label = LABEL();-compile_backtrackingpath(common, rootbacktrack.top);-if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- {- sljit_free_compiler(compiler);- SLJIT_FREE(common->optimized_cbracket, allocator_data);- SLJIT_FREE(common->private_data_ptrs, allocator_data);- PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);- return PCRE2_ERROR_NOMEMORY;- }--SLJIT_ASSERT(rootbacktrack.prev == NULL);-reset_match_label = LABEL();--if (mode == PCRE2_JIT_PARTIAL_SOFT)- {- /* Update hit_start only in the first time. */- jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, TMP1, 0);- JUMPHERE(jump);- }--/* Check we have remaining characters. */-if ((re->overall_options & PCRE2_ANCHORED) == 0 && 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->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1) >> 3) : common->start_ptr);--if ((re->overall_options & PCRE2_ANCHORED) == 0)- {- if (common->ff_newline_shortcut != NULL)- {- /* There cannot be more newlines if PCRE2_FIRSTLINE is set. */- if ((re->overall_options & PCRE2_FIRSTLINE) == 0)- {- if (common->match_end_ptr != 0)- {- OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);- OP1(SLJIT_MOV, STR_END, 0, TMP1, 0);- CMPTO(SLJIT_LESS, STR_PTR, 0, TMP1, 0, common->ff_newline_shortcut);- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);- }- else- CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut);- }- }- else- CMPTO(SLJIT_LESS, STR_PTR, 0, (common->match_end_ptr == 0) ? STR_END : TMP1, 0, mainloop_label);- }--/* No more remaining characters. */-if (reqcu_not_found != NULL)- set_jumps(reqcu_not_found, LABEL());--if (mode == PCRE2_JIT_PARTIAL_SOFT)- CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel);--OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);-JUMPTO(SLJIT_JUMP, common->quit_label);--flush_stubs(common);--if (common->might_be_empty)- {- JUMPHERE(empty_match);- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);- OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));- OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);- JUMPTO(SLJIT_NOT_ZERO, empty_match_backtrack_label);- OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);- JUMPTO(SLJIT_ZERO, 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->early_fail_start_ptr = 0;-common->early_fail_end_ptr = 0;-common->currententry = common->entries;-common->local_quit_available = TRUE;-quit_label = common->quit_label;-if (common->currententry != NULL)- {- /* A free bit for each private data. */- common->recurse_bitset_size = ((private_data_size / (int)sizeof(sljit_sw)) + 7) >> 3;- SLJIT_ASSERT(common->recurse_bitset_size > 0);- common->recurse_bitset = (sljit_u8*)SLJIT_MALLOC(common->recurse_bitset_size, allocator_data);;-- if (common->recurse_bitset != NULL)- {- do- {- /* Might add new entries. */- compile_recurse(common);- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))- break;- flush_stubs(common);- common->currententry = common->currententry->next;- }- while (common->currententry != NULL);-- SLJIT_FREE(common->recurse_bitset, allocator_data);- }-- if (common->currententry != NULL)- {- /* The common->recurse_bitset has been freed. */- SLJIT_ASSERT(sljit_get_compiler_error(compiler) || common->recurse_bitset == NULL);-- sljit_free_compiler(compiler);- SLJIT_FREE(common->optimized_cbracket, allocator_data);- SLJIT_FREE(common->private_data_ptrs, allocator_data);- PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);- return PCRE2_ERROR_NOMEMORY;- }- }-common->local_quit_available = FALSE;-common->quit_label = quit_label;--/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */-/* This is a (really) rare case. */-set_jumps(common->stackalloc, LABEL());-/* RETURN_ADDR is not a saved register. */-sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);--SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);--OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0);-OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);-OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE);-OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack));-OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0);--sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_stack_resize));--jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);-OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0);-OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);-OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);--/* Allocation failed. */-JUMPHERE(jump);-/* We break the return address cache here, but this is a really rare case. */-OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_JIT_STACKLIMIT);-JUMPTO(SLJIT_JUMP, common->quit_label);--/* Call limit reached. */-set_jumps(common->calllimit, LABEL());-OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_MATCHLIMIT);-JUMPTO(SLJIT_JUMP, common->quit_label);--if (common->revertframes != NULL)- {- set_jumps(common->revertframes, LABEL());- do_revertframes(common);- }-if (common->wordboundary != NULL)- {- set_jumps(common->wordboundary, LABEL());- check_wordboundary(common);- }-if (common->anynewline != NULL)- {- set_jumps(common->anynewline, LABEL());- check_anynewline(common);- }-if (common->hspace != NULL)- {- set_jumps(common->hspace, LABEL());- check_hspace(common);- }-if (common->vspace != NULL)- {- set_jumps(common->vspace, LABEL());- check_vspace(common);- }-if (common->casefulcmp != NULL)- {- set_jumps(common->casefulcmp, LABEL());- do_casefulcmp(common);- }-if (common->caselesscmp != NULL)- {- set_jumps(common->caselesscmp, LABEL());- do_caselesscmp(common);- }-if (common->reset_match != NULL)- {- set_jumps(common->reset_match, LABEL());- do_reset_match(common, (re->top_bracket + 1) * 2);- CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP1, 0, continue_match_label);- OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);- JUMPTO(SLJIT_JUMP, reset_match_label);- }-#ifdef SUPPORT_UNICODE-#if PCRE2_CODE_UNIT_WIDTH == 8-if (common->utfreadchar != NULL)- {- set_jumps(common->utfreadchar, LABEL());- do_utfreadchar(common);- }-if (common->utfreadtype8 != NULL)- {- set_jumps(common->utfreadtype8, LABEL());- do_utfreadtype8(common);- }-if (common->utfpeakcharback != NULL)- {- set_jumps(common->utfpeakcharback, LABEL());- do_utfpeakcharback(common);- }-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */-#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16-if (common->utfreadchar_invalid != NULL)- {- set_jumps(common->utfreadchar_invalid, LABEL());- do_utfreadchar_invalid(common);- }-if (common->utfreadnewline_invalid != NULL)- {- set_jumps(common->utfreadnewline_invalid, LABEL());- do_utfreadnewline_invalid(common);- }-if (common->utfmoveback_invalid)- {- set_jumps(common->utfmoveback_invalid, LABEL());- do_utfmoveback_invalid(common);- }-if (common->utfpeakcharback_invalid)- {- set_jumps(common->utfpeakcharback_invalid, LABEL());- do_utfpeakcharback_invalid(common);- }-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16 */-if (common->getucd != NULL)- {- set_jumps(common->getucd, LABEL());- do_getucd(common);- }-if (common->getucdtype != NULL)- {- set_jumps(common->getucdtype, LABEL());- do_getucdtype(common);- }-#endif /* SUPPORT_UNICODE */--SLJIT_FREE(common->optimized_cbracket, allocator_data);-SLJIT_FREE(common->private_data_ptrs, allocator_data);--executable_func = sljit_generate_code(compiler);-executable_size = sljit_get_generated_code_size(compiler);-sljit_free_compiler(compiler);--if (executable_func == NULL)- {- PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);- return PCRE2_ERROR_NOMEMORY;- }--/* Reuse the function descriptor if possible. */-if (re->executable_jit != NULL)- functions = (executable_functions *)re->executable_jit;-else- {- functions = SLJIT_MALLOC(sizeof(executable_functions), allocator_data);- if (functions == NULL)- {- /* This case is highly unlikely since we just recently- freed a lot of memory. Not impossible though. */- sljit_free_code(executable_func, NULL);- PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);- return PCRE2_ERROR_NOMEMORY;- }- memset(functions, 0, sizeof(executable_functions));- functions->top_bracket = re->top_bracket + 1;- functions->limit_match = re->limit_match;- re->executable_jit = functions;- }--/* Turn mode into an index. */-if (mode == PCRE2_JIT_COMPLETE)- mode = 0;-else- mode = (mode == PCRE2_JIT_PARTIAL_SOFT) ? 1 : 2;--SLJIT_ASSERT(mode < JIT_NUMBER_OF_COMPILE_MODES);-functions->executable_funcs[mode] = executable_func;-functions->read_only_data_heads[mode] = common->read_only_data_head;-functions->executable_sizes[mode] = executable_size;-return 0;-}--#endif--/*************************************************-* JIT compile a Regular Expression *-*************************************************/--/* This function used JIT to convert a previously-compiled pattern into machine-code.--Arguments:- code a compiled pattern- options JIT option bits--Returns: 0: success or (*NOJIT) was used- <0: an error code-*/--#define PUBLIC_JIT_COMPILE_OPTIONS \- (PCRE2_JIT_COMPLETE|PCRE2_JIT_PARTIAL_SOFT|PCRE2_JIT_PARTIAL_HARD|PCRE2_JIT_INVALID_UTF)--PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION-pcre2_jit_compile(pcre2_code *code, uint32_t options)-{-pcre2_real_code *re = (pcre2_real_code *)code;-#ifdef SUPPORT_JIT-executable_functions *functions;-static int executable_allocator_is_working = 0;-#endif--if (code == NULL)- return PCRE2_ERROR_NULL;--if ((options & ~PUBLIC_JIT_COMPILE_OPTIONS) != 0)- return PCRE2_ERROR_JIT_BADOPTION;--/* Support for invalid UTF was first introduced in JIT, with the option-PCRE2_JIT_INVALID_UTF. Later, support was added to the interpreter, and the-compile-time option PCRE2_MATCH_INVALID_UTF was created. This is now the-preferred feature, with the earlier option deprecated. However, for backward-compatibility, if the earlier option is set, it forces the new option so that-if JIT matching falls back to the interpreter, there is still support for-invalid UTF. However, if this function has already been successfully called-without PCRE2_JIT_INVALID_UTF and without PCRE2_MATCH_INVALID_UTF (meaning that-non-invalid-supporting JIT code was compiled), give an error.--If in the future support for PCRE2_JIT_INVALID_UTF is withdrawn, the following-actions are needed:-- 1. Remove the definition from pcre2.h.in and from the list in- PUBLIC_JIT_COMPILE_OPTIONS above.-- 2. Replace PCRE2_JIT_INVALID_UTF with a local flag in this module.-- 3. Replace PCRE2_JIT_INVALID_UTF in pcre2_jit_test.c.-- 4. Delete the following short block of code. The setting of "re" and- "functions" can be moved into the JIT-only block below, but if that is- done, (void)re and (void)functions will be needed in the non-JIT case, to- avoid compiler warnings.-*/--#ifdef SUPPORT_JIT-functions = (executable_functions *)re->executable_jit;-#endif--if ((options & PCRE2_JIT_INVALID_UTF) != 0)- {- if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) == 0)- {-#ifdef SUPPORT_JIT- if (functions != NULL) return PCRE2_ERROR_JIT_BADOPTION;-#endif- re->overall_options |= PCRE2_MATCH_INVALID_UTF;- }- }--/* The above tests are run with and without JIT support. This means that-PCRE2_JIT_INVALID_UTF propagates back into the regex options (ensuring-interpreter support) even in the absence of JIT. But now, if there is no JIT-support, give an error return. */--#ifndef SUPPORT_JIT-return PCRE2_ERROR_JIT_BADOPTION;-#else /* SUPPORT_JIT */--/* There is JIT support. Do the necessary. */--if ((re->flags & PCRE2_NOJIT) != 0) return 0;--if (executable_allocator_is_working == 0)- {- /* Checks whether the executable allocator is working. This check- might run multiple times in multi-threaded environments, but the- result should not be affected by it. */- void *ptr = SLJIT_MALLOC_EXEC(32, NULL);-- executable_allocator_is_working = -1;-- if (ptr != NULL)- {- SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr), NULL);- executable_allocator_is_working = 1;- }- }--if (executable_allocator_is_working < 0)+ New API code Copyright (c) 2016-2024 University of Cambridge++-----------------------------------------------------------------------------+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright notice,+ this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++ * Neither the name of the University of Cambridge nor the names of its+ contributors may be used to endorse or promote products derived from+ this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.+-----------------------------------------------------------------------------+*/++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#if defined(__has_feature)+#if __has_feature(memory_sanitizer)+#include <sanitizer/msan_interface.h>+#endif /* __has_feature(memory_sanitizer) */+#endif /* defined(__has_feature) */++#include "pcre2_internal.h"++#ifdef SUPPORT_JIT++/* All-in-one: Since we use the JIT compiler only from here,+we just include it. This way we don't need to touch the build+system files. */++#define SLJIT_CONFIG_AUTO 1+#define SLJIT_CONFIG_STATIC 1+#define SLJIT_VERBOSE 0++#ifdef PCRE2_DEBUG+#define SLJIT_DEBUG 1+#else+#define SLJIT_DEBUG 0+#endif++#define SLJIT_MALLOC(size, allocator_data) pcre2_jit_malloc(size, allocator_data)+#define SLJIT_FREE(ptr, allocator_data) pcre2_jit_free(ptr, allocator_data)++static void * pcre2_jit_malloc(size_t size, void *allocator_data)+{+pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);+return allocator->malloc(size, allocator->memory_data);+}++static void pcre2_jit_free(void *ptr, void *allocator_data)+{+pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);+allocator->free(ptr, allocator->memory_data);+}++#include "sljit/sljitLir.c"++#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED+#error Unsupported architecture+#endif++/* Defines for debugging purposes. */++/* 1 - Use unoptimized capturing brackets.+ 2 - Enable capture_last_ptr (includes option 1). */+/* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */++/* 1 - Always have a control head. */+/* #define DEBUG_FORCE_CONTROL_HEAD 1 */++/* Allocate memory for the regex stack on the real machine stack.+Fast, but limited size. */+#define MACHINE_STACK_SIZE 32768++/* Growth rate for stack allocated by the OS. Should be the multiply+of page size. */+#define STACK_GROWTH_RATE 8192++/* Enable to check that the allocation could destroy temporaries. */+#if defined SLJIT_DEBUG && SLJIT_DEBUG+#define DESTROY_REGISTERS 1+#endif++/*+Short summary about the backtracking mechanism empolyed by the jit code generator:++The code generator follows the recursive nature of the PERL compatible regular+expressions. The basic blocks of regular expressions are condition checkers+whose execute different commands depending on the result of the condition check.+The relationship between the operators can be horizontal (concatenation) and+vertical (sub-expression) (See struct backtrack_common for more details).++ 'ab' - 'a' and 'b' regexps are concatenated+ 'a+' - 'a' is the sub-expression of the '+' operator++The condition checkers are boolean (true/false) checkers. Machine code is generated+for the checker itself and for the actions depending on the result of the checker.+The 'true' case is called as the matching path (expected path), and the other is called as+the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken+branches on the matching path.++ Greedy star operator (*) :+ Matching path: match happens.+ Backtrack path: match failed.+ Non-greedy star operator (*?) :+ Matching path: no need to perform a match.+ Backtrack path: match is required.++The following example shows how the code generated for a capturing bracket+with two alternatives. Let A, B, C, D are arbirary regular expressions, and+we have the following regular expression:++ A(B|C)D++The generated code will be the following:++ A matching path+ '(' matching path (pushing arguments to the stack)+ B matching path+ ')' matching path (pushing arguments to the stack)+ D matching path+ return with successful match++ D backtrack path+ ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")+ B backtrack path+ C expected path+ jump to D matching path+ C backtrack path+ A backtrack path++ Notice, that the order of backtrack code paths are the opposite of the fast+ code paths. In this way the topmost value on the stack is always belong+ to the current backtrack code path. The backtrack path must check+ whether there is a next alternative. If so, it needs to jump back to+ the matching path eventually. Otherwise it needs to clear out its own stack+ frame and continue the execution on the backtrack code paths.+*/++/*+Saved stack frames:++Atomic blocks and asserts require reloading the values of private data+when the backtrack mechanism performed. Because of OP_RECURSE, the data+are not necessarly known in compile time, thus we need a dynamic restore+mechanism.++The stack frames are stored in a chain list, and have the following format:+([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]++Thus we can restore the private data to a particular point in the stack.+*/++typedef struct jit_arguments {+ /* Pointers first. */+ struct sljit_stack *stack;+ PCRE2_SPTR str;+ PCRE2_SPTR begin;+ PCRE2_SPTR end;+ pcre2_match_data *match_data;+ PCRE2_SPTR startchar_ptr;+ PCRE2_UCHAR *mark_ptr;+ int (*callout)(pcre2_callout_block *, void *);+ void *callout_data;+ /* Everything else after. */+ sljit_uw offset_limit;+ sljit_u32 limit_match;+ sljit_u32 oveccount;+ sljit_u32 options;+} jit_arguments;++#define JIT_NUMBER_OF_COMPILE_MODES 3++typedef struct executable_functions {+ void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];+ void *read_only_data_heads[JIT_NUMBER_OF_COMPILE_MODES];+ sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];+ sljit_u32 top_bracket;+ sljit_u32 limit_match;+} executable_functions;++typedef struct jump_list {+ struct sljit_jump *jump;+ struct jump_list *next;+} jump_list;++typedef struct stub_list {+ struct sljit_jump *start;+ struct sljit_label *quit;+ struct stub_list *next;+} stub_list;++enum frame_types {+ no_frame = -1,+ no_stack = -2+};++enum control_types {+ type_mark = 0,+ type_then_trap = 1+};++enum early_fail_types {+ type_skip = 0,+ type_fail = 1,+ type_fail_range = 2+};++typedef int (SLJIT_FUNC *jit_function)(jit_arguments *args);++/* The following structure is the key data type for the recursive+code generator. It is allocated by compile_matchingpath, and contains+the arguments for compile_backtrackingpath. Must be the first member+of its descendants. */+typedef struct backtrack_common {+ /* Backtracking path of an opcode, which falls back+ to our opcode, if it cannot resume matching. */+ struct backtrack_common *prev;+ /* Backtracks for opcodes without backtracking path.+ These opcodes are between 'prev' and the current+ opcode, and they never resume the match. */+ jump_list *simple_backtracks;+ /* Internal backtracking list for block constructs+ which contains other opcodes, such as brackets,+ asserts, conditionals, etc. */+ struct backtrack_common *top;+ /* Backtracks used internally by the opcode. For component+ opcodes, this list is also used by those opcodes without+ backtracking path which follows the 'top' backtrack. */+ jump_list *own_backtracks;+ /* Opcode pointer. */+ PCRE2_SPTR cc;+} backtrack_common;++typedef struct assert_backtrack {+ backtrack_common common;+ jump_list *condfailed;+ /* Less than 0 if a frame is not needed. */+ int framesize;+ /* Points to our private memory word on the stack. */+ int private_data_ptr;+ /* For iterators. */+ struct sljit_label *matchingpath;+} assert_backtrack;++typedef struct bracket_backtrack {+ backtrack_common common;+ /* Where to coninue if an alternative is successfully matched. */+ struct sljit_label *alternative_matchingpath;+ /* For rmin and rmax iterators. */+ struct sljit_label *recursive_matchingpath;+ /* For greedy ? operator. */+ struct sljit_label *zero_matchingpath;+ /* Contains the branches of a failed condition. */+ union {+ /* Both for OP_COND, OP_SCOND. */+ jump_list *condfailed;+ assert_backtrack *assert;+ /* For OP_ONCE. Less than 0 if not needed. */+ int framesize;+ /* For brackets with >3 alternatives. */+ struct sljit_jump *matching_mov_addr;+ } u;+ /* Points to our private memory word on the stack. */+ int private_data_ptr;+} bracket_backtrack;++typedef struct bracketpos_backtrack {+ backtrack_common common;+ /* Points to our private memory word on the stack. */+ int private_data_ptr;+ /* Reverting stack is needed. */+ int framesize;+ /* Allocated stack size. */+ int stacksize;+} bracketpos_backtrack;++typedef struct braminzero_backtrack {+ backtrack_common common;+ struct sljit_label *matchingpath;+} braminzero_backtrack;++typedef struct char_iterator_backtrack {+ backtrack_common common;+ /* Next iteration. */+ struct sljit_label *matchingpath;+ union {+ jump_list *backtracks;+ struct {+ unsigned int othercasebit;+ PCRE2_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;+ /* Contains the function entry label. */+ struct sljit_label *entry_label;+ /* Contains the function entry label. */+ struct sljit_label *backtrack_label;+ /* Collects the entry calls until the function is not created. */+ jump_list *entry_calls;+ /* Collects the backtrack calls until the function is not created. */+ jump_list *backtrack_calls;+ /* Points to the starting opcode. */+ sljit_sw start;+} recurse_entry;++typedef struct recurse_backtrack {+ backtrack_common common;+ /* Return to the matching path. */+ struct sljit_label *matchingpath;+ /* Recursive pattern. */+ recurse_entry *entry;+ /* Pattern is inlined. */+ BOOL inlined_pattern;+} recurse_backtrack;++typedef struct vreverse_backtrack {+ backtrack_common common;+ /* Return to the matching path. */+ struct sljit_label *matchingpath;+} vreverse_backtrack;++#define OP_THEN_TRAP OP_TABLE_LENGTH++typedef struct then_trap_backtrack {+ backtrack_common common;+ /* If then_trap is not NULL, this structure contains the real+ then_trap for the backtracking path. */+ struct then_trap_backtrack *then_trap;+ /* Points to the starting opcode. */+ sljit_sw start;+ /* Exit point for the then opcodes of this alternative. */+ jump_list *quit;+ /* Frame size of the current alternative. */+ int framesize;+} then_trap_backtrack;++#define MAX_N_CHARS 12+#define MAX_DIFF_CHARS 5++typedef struct fast_forward_char_data {+ /* Number of characters in the chars array, 255 for any character. */+ sljit_u8 count;+ /* Number of last UTF-8 characters in the chars array. */+ sljit_u8 last_count;+ /* Available characters in the current position. */+ PCRE2_UCHAR chars[MAX_DIFF_CHARS];+} fast_forward_char_data;++#define MAX_CLASS_RANGE_SIZE 4+#define MAX_CLASS_CHARS_SIZE 3++typedef struct compiler_common {+ /* The sljit ceneric compiler. */+ struct sljit_compiler *compiler;+ /* Compiled regular expression. */+ pcre2_real_code *re;+ /* First byte code. */+ PCRE2_SPTR start;+ /* Maps private data offset to each opcode. */+ sljit_s32 *private_data_ptrs;+ /* Chain list of read-only data ptrs. */+ void *read_only_data_head;+ /* Tells whether the capturing bracket is optimized. */+ sljit_u8 *optimized_cbracket;+ /* Tells whether the starting offset is a target of then. */+ sljit_u8 *then_offsets;+ /* Current position where a THEN must jump. */+ then_trap_backtrack *then_trap;+ /* Starting offset of private data for capturing brackets. */+ sljit_s32 cbra_ptr;+ /* Output vector starting point. Must be divisible by 2. */+ sljit_s32 ovector_start;+ /* Points to the starting character of the current match. */+ sljit_s32 start_ptr;+ /* Last known position of the requested byte. */+ sljit_s32 req_char_ptr;+ /* Head of the last recursion. */+ 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. */+ sljit_s32 hit_start;+ /* Pointer of the match end position. */+ sljit_s32 match_end_ptr;+ /* Points to the marked string. */+ sljit_s32 mark_ptr;+ /* Head of the recursive control verb management chain.+ Each item must have a previous offset and type+ (see control_types) values. See do_search_mark. */+ sljit_s32 control_head_ptr;+ /* Points to the last matched capture block index. */+ sljit_s32 capture_last_ptr;+ /* Fast forward skipping byte code pointer. */+ PCRE2_SPTR fast_forward_bc_ptr;+ /* Locals used by fast fail optimization. */+ sljit_s32 early_fail_start_ptr;+ sljit_s32 early_fail_end_ptr;+ /* Variables used by recursive call generator. */+ sljit_s32 recurse_bitset_size;+ uint8_t *recurse_bitset;++ /* Flipped and lower case tables. */+ const sljit_u8 *fcc;+ sljit_sw lcc;+ /* Mode can be PCRE2_JIT_COMPLETE and others. */+ int mode;+ /* TRUE, when empty match is accepted for partial matching. */+ BOOL allow_empty_partial;+ /* TRUE, when minlength is greater than 0. */+ BOOL might_be_empty;+ /* \K is found in the pattern. */+ BOOL has_set_som;+ /* (*SKIP:arg) is found in the pattern. */+ BOOL has_skip_arg;+ /* (*THEN) is found in the pattern. */+ BOOL has_then;+ /* (*SKIP) or (*SKIP:arg) is found in lookbehind assertion. */+ BOOL has_skip_in_assert_back;+ /* Quit is redirected by recurse, negative assertion, or positive assertion in conditional block. */+ BOOL local_quit_available;+ /* Currently in a positive assertion. */+ BOOL in_positive_assertion;+ /* Newline control. */+ int nltype;+ sljit_u32 nlmax;+ sljit_u32 nlmin;+ int newline;+ int bsr_nltype;+ sljit_u32 bsr_nlmax;+ sljit_u32 bsr_nlmin;+ /* Dollar endonly. */+ int endonly;+ /* Tables. */+ sljit_sw ctypes;+ /* Named capturing brackets. */+ PCRE2_SPTR name_table;+ sljit_sw name_count;+ sljit_sw name_entry_size;++ /* Labels and jump lists. */+ struct sljit_label *partialmatchlabel;+ struct sljit_label *quit_label;+ struct sljit_label *abort_label;+ struct sljit_label *accept_label;+ struct sljit_label *ff_newline_shortcut;+ stub_list *stubs;+ recurse_entry *entries;+ recurse_entry *currententry;+ jump_list *partialmatch;+ jump_list *quit;+ jump_list *positive_assertion_quit;+ jump_list *abort;+ jump_list *failed_match;+ jump_list *accept;+ jump_list *calllimit;+ jump_list *stackalloc;+ jump_list *revertframes;+ jump_list *wordboundary;+ jump_list *ucp_wordboundary;+ jump_list *anynewline;+ jump_list *hspace;+ jump_list *vspace;+ jump_list *casefulcmp;+ jump_list *caselesscmp;+ jump_list *reset_match;+ /* Same as reset_match, but resets the STR_PTR as well. */+ jump_list *restart_match;+ BOOL unset_backref;+ BOOL alt_circumflex;+#ifdef SUPPORT_UNICODE+ BOOL utf;+ BOOL invalid_utf;+ BOOL ucp;+ /* Points to saving area for iref. */+ sljit_s32 iref_ptr;+ jump_list *getucd;+ jump_list *getucdtype;+#if PCRE2_CODE_UNIT_WIDTH == 8+ jump_list *utfreadchar;+ jump_list *utfreadtype8;+ jump_list *utfpeakcharback;+#endif+#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16+ jump_list *utfreadchar_invalid;+ jump_list *utfreadnewline_invalid;+ jump_list *utfmoveback_invalid;+ jump_list *utfpeakcharback_invalid;+#endif+#endif /* SUPPORT_UNICODE */+} compiler_common;++/* For byte_sequence_compare. */++typedef struct compare_context {+ int length;+ int sourcereg;+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ int ucharptr;+ union {+ sljit_s32 asint;+ sljit_u16 asushort;+#if PCRE2_CODE_UNIT_WIDTH == 8+ sljit_u8 asbyte;+ sljit_u8 asuchars[4];+#elif PCRE2_CODE_UNIT_WIDTH == 16+ sljit_u16 asuchars[2];+#elif PCRE2_CODE_UNIT_WIDTH == 32+ sljit_u32 asuchars[1];+#endif+ } c;+ union {+ sljit_s32 asint;+ sljit_u16 asushort;+#if PCRE2_CODE_UNIT_WIDTH == 8+ sljit_u8 asbyte;+ sljit_u8 asuchars[4];+#elif PCRE2_CODE_UNIT_WIDTH == 16+ sljit_u16 asuchars[2];+#elif PCRE2_CODE_UNIT_WIDTH == 32+ sljit_u32 asuchars[1];+#endif+ } oc;+#endif+} compare_context;++/* Undefine sljit macros. */+#undef CMP++/* Used for accessing the elements of the stack. */+#define STACK(i) ((i) * SSIZE_OF(sw))++#ifdef SLJIT_PREF_SHIFT_REG+#if SLJIT_PREF_SHIFT_REG == SLJIT_R2+/* Nothing. */+#elif SLJIT_PREF_SHIFT_REG == SLJIT_R3+#define SHIFT_REG_IS_R3+#else+#error "Unsupported shift register"+#endif+#endif++#define TMP1 SLJIT_R0+#ifdef SHIFT_REG_IS_R3+#define TMP2 SLJIT_R3+#define TMP3 SLJIT_R2+#else+#define TMP2 SLJIT_R2+#define TMP3 SLJIT_R3+#endif+#define STR_PTR SLJIT_R1+#define STR_END SLJIT_S0+#define STACK_TOP SLJIT_S1+#define STACK_LIMIT SLJIT_S2+#define COUNT_MATCH SLJIT_S3+#define ARGUMENTS SLJIT_S4+#define RETURN_ADDR SLJIT_R4++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+#define HAS_VIRTUAL_REGISTERS 1+#else+#define HAS_VIRTUAL_REGISTERS 0+#endif++/* Local space layout. */+/* These two locals can be used by the current opcode. */+#define LOCALS0 (0 * sizeof(sljit_sw))+#define LOCALS1 (1 * sizeof(sljit_sw))+/* Two local variables for possessive quantifiers (char1 cannot use them). */+#define POSSESSIVE0 (2 * sizeof(sljit_sw))+#define POSSESSIVE1 (3 * sizeof(sljit_sw))+/* Max limit of recursions. */+#define LIMIT_MATCH (4 * sizeof(sljit_sw))+/* The output vector is stored on the stack, and contains pointers+to characters. The vector data is divided into two groups: the first+group contains the start / end character pointers, and the second is+the start pointers when the end of the capturing group has not yet reached. */+#define OVECTOR_START (common->ovector_start)+#define OVECTOR(i) (OVECTOR_START + (i) * SSIZE_OF(sw))+#define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * SSIZE_OF(sw))+#define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])++#if PCRE2_CODE_UNIT_WIDTH == 8+#define MOV_UCHAR SLJIT_MOV_U8+#define IN_UCHARS(x) (x)+#elif PCRE2_CODE_UNIT_WIDTH == 16+#define MOV_UCHAR SLJIT_MOV_U16+#define UCHAR_SHIFT (1)+#define IN_UCHARS(x) ((x) * 2)+#elif PCRE2_CODE_UNIT_WIDTH == 32+#define MOV_UCHAR SLJIT_MOV_U32+#define UCHAR_SHIFT (2)+#define IN_UCHARS(x) ((x) * 4)+#else+#error Unsupported compiling mode+#endif++/* Shortcuts. */+#define DEFINE_COMPILER \+ struct sljit_compiler *compiler = common->compiler+#define OP1(op, dst, dstw, src, srcw) \+ sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))+#define OP2(op, dst, dstw, src1, src1w, src2, src2w) \+ sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))+#define OP2U(op, src1, src1w, src2, src2w) \+ sljit_emit_op2u(compiler, (op), (src1), (src1w), (src2), (src2w))+#define OP_SRC(op, src, srcw) \+ sljit_emit_op_src(compiler, (op), (src), (srcw))+#define LABEL() \+ sljit_emit_label(compiler)+#define JUMP(type) \+ sljit_emit_jump(compiler, (type))+#define JUMPTO(type, label) \+ sljit_set_label(sljit_emit_jump(compiler, (type)), (label))+#define JUMPHERE(jump) \+ sljit_set_label((jump), sljit_emit_label(compiler))+#define SET_LABEL(jump, label) \+ sljit_set_label((jump), (label))+#define CMP(type, src1, src1w, src2, src2w) \+ 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, type) \+ sljit_emit_op_flags(compiler, (op), (dst), (dstw), (type))+#define SELECT(type, dst_reg, src1, src1w, src2_reg) \+ sljit_emit_select(compiler, (type), (dst_reg), (src1), (src1w), (src2_reg))+#define GET_LOCAL_BASE(dst, dstw, offset) \+ sljit_get_local_base(compiler, (dst), (dstw), (offset))++#define READ_CHAR_MAX 0x7fffffff++#define INVALID_UTF_CHAR -1+#define UNASSIGNED_UTF_CHAR 888++#if defined SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8++#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \+ { \+ if (ptr[0] <= 0x7f) \+ c = *ptr++; \+ else if (ptr + 1 < end && ptr[1] >= 0x80 && ptr[1] < 0xc0) \+ { \+ c = ptr[1] - 0x80; \+ \+ if (ptr[0] >= 0xc2 && ptr[0] <= 0xdf) \+ { \+ c |= (ptr[0] - 0xc0) << 6; \+ ptr += 2; \+ } \+ else if (ptr + 2 < end && ptr[2] >= 0x80 && ptr[2] < 0xc0) \+ { \+ c = c << 6 | (ptr[2] - 0x80); \+ \+ if (ptr[0] >= 0xe0 && ptr[0] <= 0xef) \+ { \+ c |= (ptr[0] - 0xe0) << 12; \+ ptr += 3; \+ \+ if (c < 0x800 || (c >= 0xd800 && c < 0xe000)) \+ { \+ invalid_action; \+ } \+ } \+ else if (ptr + 3 < end && ptr[3] >= 0x80 && ptr[3] < 0xc0) \+ { \+ c = c << 6 | (ptr[3] - 0x80); \+ \+ if (ptr[0] >= 0xf0 && ptr[0] <= 0xf4) \+ { \+ c |= (ptr[0] - 0xf0) << 18; \+ ptr += 4; \+ \+ if (c >= 0x110000 || c < 0x10000) \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ }++#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \+ { \+ c = ptr[-1]; \+ if (c <= 0x7f) \+ ptr--; \+ else if (ptr - 1 > start && ptr[-1] >= 0x80 && ptr[-1] < 0xc0) \+ { \+ c -= 0x80; \+ \+ if (ptr[-2] >= 0xc2 && ptr[-2] <= 0xdf) \+ { \+ c |= (ptr[-2] - 0xc0) << 6; \+ ptr -= 2; \+ } \+ else if (ptr - 2 > start && ptr[-2] >= 0x80 && ptr[-2] < 0xc0) \+ { \+ c = c << 6 | (ptr[-2] - 0x80); \+ \+ if (ptr[-3] >= 0xe0 && ptr[-3] <= 0xef) \+ { \+ c |= (ptr[-3] - 0xe0) << 12; \+ ptr -= 3; \+ \+ if (c < 0x800 || (c >= 0xd800 && c < 0xe000)) \+ { \+ invalid_action; \+ } \+ } \+ else if (ptr - 3 > start && ptr[-3] >= 0x80 && ptr[-3] < 0xc0) \+ { \+ c = c << 6 | (ptr[-3] - 0x80); \+ \+ if (ptr[-4] >= 0xf0 && ptr[-4] <= 0xf4) \+ { \+ c |= (ptr[-4] - 0xf0) << 18; \+ ptr -= 4; \+ \+ if (c >= 0x110000 || c < 0x10000) \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ }++#elif PCRE2_CODE_UNIT_WIDTH == 16++#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \+ { \+ if (ptr[0] < 0xd800 || ptr[0] >= 0xe000) \+ c = *ptr++; \+ else if (ptr[0] < 0xdc00 && ptr + 1 < end && ptr[1] >= 0xdc00 && ptr[1] < 0xe000) \+ { \+ c = (((ptr[0] - 0xd800) << 10) | (ptr[1] - 0xdc00)) + 0x10000; \+ ptr += 2; \+ } \+ else \+ { \+ invalid_action; \+ } \+ }++#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \+ { \+ c = ptr[-1]; \+ if (c < 0xd800 || c >= 0xe000) \+ ptr--; \+ else if (c >= 0xdc00 && ptr - 1 > start && ptr[-2] >= 0xd800 && ptr[-2] < 0xdc00) \+ { \+ c = (((ptr[-2] - 0xd800) << 10) | (c - 0xdc00)) + 0x10000; \+ ptr -= 2; \+ } \+ else \+ { \+ invalid_action; \+ } \+ }+++#elif PCRE2_CODE_UNIT_WIDTH == 32++#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \+ { \+ if (ptr[0] < 0xd800 || (ptr[0] >= 0xe000 && ptr[0] < 0x110000)) \+ c = *ptr++; \+ else \+ { \+ invalid_action; \+ } \+ }++#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \+ { \+ c = ptr[-1]; \+ if (ptr[-1] < 0xd800 || (ptr[-1] >= 0xe000 && ptr[-1] < 0x110000)) \+ ptr--; \+ else \+ { \+ invalid_action; \+ } \+ }++#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */++static PCRE2_SPTR bracketend(PCRE2_SPTR cc)+{+SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND));+do cc += GET(cc, 1); while (*cc == OP_ALT);+SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);+cc += 1 + LINK_SIZE;+return cc;+}++static int no_alternatives(PCRE2_SPTR cc)+{+int count = 0;+SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND));+do+ {+ cc += GET(cc, 1);+ count++;+ }+while (*cc == OP_ALT);+SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);+return count;+}++static BOOL find_vreverse(PCRE2_SPTR cc)+{+ SLJIT_ASSERT(*cc == OP_ASSERTBACK || *cc == OP_ASSERTBACK_NOT || *cc == OP_ASSERTBACK_NA);++ do+ {+ if (cc[1 + LINK_SIZE] == OP_VREVERSE)+ return TRUE;+ cc += GET(cc, 1);+ }+ while (*cc == OP_ALT);++ return FALSE;+}++/* Functions whose might need modification for all new supported opcodes:+ next_opcode+ check_opcode_types+ set_private_data_ptrs+ get_framesize+ init_frame+ get_recurse_data_length+ copy_recurse_data+ compile_matchingpath+ compile_backtrackingpath+*/++static PCRE2_SPTR next_opcode(compiler_common *common, PCRE2_SPTR cc)+{+SLJIT_UNUSED_ARG(common);+switch(*cc)+ {+ case OP_SOD:+ case OP_SOM:+ case OP_SET_SOM:+ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ 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_NOTPROP:+ case OP_PROP:+ case OP_ANYNL:+ case OP_NOT_HSPACE:+ case OP_HSPACE:+ 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_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRPLUS:+ case OP_CRMINPLUS:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSSTAR:+ case OP_CRPOSPLUS:+ case OP_CRPOSQUERY:+ case OP_CRPOSRANGE:+ case OP_CLASS:+ case OP_NCLASS:+ case OP_REF:+ case OP_REFI:+ case OP_DNREF:+ case OP_DNREFI:+ case OP_RECURSE:+ case OP_CALLOUT:+ case OP_ALT:+ case OP_KET:+ case OP_KETRMAX:+ case OP_KETRMIN:+ case OP_KETRPOS:+ case OP_REVERSE:+ case OP_VREVERSE:+ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRA:+ case OP_BRAPOS:+ case OP_CBRA:+ case OP_CBRAPOS:+ case OP_COND:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_SCBRA:+ case OP_SCBRAPOS:+ case OP_SCOND:+ case OP_CREF:+ case OP_DNCREF:+ case OP_RREF:+ case OP_DNRREF:+ case OP_FALSE:+ case OP_TRUE:+ case OP_BRAZERO:+ case OP_BRAMINZERO:+ case OP_BRAPOSZERO:+ case OP_PRUNE:+ case OP_SKIP:+ case OP_THEN:+ case OP_COMMIT:+ case OP_FAIL:+ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ case OP_CLOSE:+ case OP_SKIPZERO:+ case OP_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:+ return cc + PRIV(OP_lengths)[*cc];++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_STAR:+ case OP_MINSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:+ case OP_STARI:+ case OP_MINSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:+ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:+ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:+ cc += PRIV(OP_lengths)[*cc];+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ return cc;++ /* Special cases. */+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ case OP_TYPEPOSUPTO:+ return cc + PRIV(OP_lengths)[*cc] - 1;++ case OP_ANYBYTE:+#ifdef SUPPORT_UNICODE+ if (common->utf) return NULL;+#endif+ return cc + 1;++ case OP_CALLOUT_STR:+ return cc + GET(cc, 1 + 2*LINK_SIZE);++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ return cc + GET(cc, 1);+#endif++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ return cc + 1 + 2 + cc[1];++ default:+ SLJIT_UNREACHABLE();+ return NULL;+ }+}++static BOOL check_opcode_types(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend)+{+int count;+PCRE2_SPTR slot;+PCRE2_SPTR assert_back_end = cc - 1;+PCRE2_SPTR assert_na_end = cc - 1;++/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */+while (cc < ccend)+ {+ switch(*cc)+ {+ case OP_SET_SOM:+ common->has_set_som = TRUE;+ common->might_be_empty = TRUE;+ cc += 1;+ break;++ case OP_REFI:+#ifdef SUPPORT_UNICODE+ if (common->iref_ptr == 0)+ {+ common->iref_ptr = common->ovector_start;+ common->ovector_start += 3 * sizeof(sljit_sw);+ }+#endif /* SUPPORT_UNICODE */+ /* Fall through. */+ case OP_REF:+ common->optimized_cbracket[GET2(cc, 1)] = 0;+ cc += 1 + IMM2_SIZE;+ break;++ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ slot = bracketend(cc);+ if (slot > assert_na_end)+ assert_na_end = slot;+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;+ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_COND:+ case OP_SCOND:+ /* Only AUTO_CALLOUT can insert this opcode. We do+ not intend to support this case. */+ if (cc[1 + LINK_SIZE] == OP_CALLOUT || cc[1 + LINK_SIZE] == OP_CALLOUT_STR)+ return FALSE;+ cc += 1 + LINK_SIZE;+ break;++ case OP_CREF:+ common->optimized_cbracket[GET2(cc, 1)] = 0;+ cc += 1 + IMM2_SIZE;+ break;++ case OP_DNREF:+ case OP_DNREFI:+ case OP_DNCREF:+ count = GET2(cc, 1 + IMM2_SIZE);+ slot = common->name_table + GET2(cc, 1) * common->name_entry_size;+ while (count-- > 0)+ {+ common->optimized_cbracket[GET2(slot, 0)] = 0;+ slot += common->name_entry_size;+ }+ cc += 1 + 2 * IMM2_SIZE;+ break;++ case OP_RECURSE:+ /* Set its value only once. */+ if (common->recursive_head_ptr == 0)+ {+ common->recursive_head_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_CALLOUT:+ case OP_CALLOUT_STR:+ if (common->capture_last_ptr == 0)+ {+ common->capture_last_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+ cc += (*cc == OP_CALLOUT) ? PRIV(OP_lengths)[OP_CALLOUT] : GET(cc, 1 + 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_COMMIT_ARG:+ case OP_PRUNE_ARG:+ if (cc < assert_na_end)+ return FALSE;+ /* Fall through */+ case OP_MARK:+ if (common->mark_ptr == 0)+ {+ common->mark_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+ cc += 1 + 2 + cc[1];+ break;++ case OP_THEN:+ common->has_then = TRUE;+ common->control_head_ptr = 1;+ cc += 1;+ break;++ case OP_SKIP:+ if (cc < assert_back_end)+ common->has_skip_in_assert_back = TRUE;+ if (cc < assert_na_end)+ return FALSE;+ 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;+ if (cc < assert_na_end)+ return FALSE;+ cc += 1 + 2 + cc[1];+ break;++ case OP_PRUNE:+ case OP_COMMIT:+ case OP_ASSERT_ACCEPT:+ if (cc < assert_na_end)+ return FALSE;+ cc++;+ break;++ default:+ cc = next_opcode(common, cc);+ if (cc == NULL)+ return FALSE;+ break;+ }+ }+return TRUE;+}++#define EARLY_FAIL_ENHANCE_MAX (3 + 3)++/*+ Start represent the number of allowed early fail enhancements++ The 0-2 values has a special meaning:+ 0 - skip is allowed for all iterators+ 1 - fail is allowed for all iterators+ 2 - fail is allowed for greedy iterators+ 3 - only ranged early fail is allowed+ >3 - (start - 3) number of remaining ranged early fails allowed++return: the updated value of start+*/+static int detect_early_fail(compiler_common *common, PCRE2_SPTR cc,+ int *private_data_start, sljit_s32 depth, int start)+{+PCRE2_SPTR begin = cc;+PCRE2_SPTR next_alt;+PCRE2_SPTR end;+PCRE2_SPTR accelerated_start;+int result = 0;+int count, prev_count;++SLJIT_ASSERT(*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA);+SLJIT_ASSERT(*cc != OP_CBRA || common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] != 0);+SLJIT_ASSERT(start < EARLY_FAIL_ENHANCE_MAX);++next_alt = cc + GET(cc, 1);+if (*next_alt == OP_ALT && start < 1)+ start = 1;++do+ {+ count = start;+ cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0);++ while (TRUE)+ {+ accelerated_start = NULL;++ 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:+ case OP_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:+ /* Zero width assertions. */+ cc++;+ continue;++ 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_NOT_HSPACE:+ case OP_HSPACE:+ case OP_NOT_VSPACE:+ case OP_VSPACE:+ if (count < 1)+ count = 1;+ cc++;+ continue;++ case OP_ANYNL:+ case OP_EXTUNI:+ if (count < 3)+ count = 3;+ cc++;+ continue;++ case OP_NOTPROP:+ case OP_PROP:+ if (count < 1)+ count = 1;+ cc += 1 + 2;+ continue;++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ if (count < 1)+ count = 1;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ continue;++ case OP_TYPEMINSTAR:+ case OP_TYPEMINPLUS:+ if (count == 2)+ count = 3;+ /* Fall through */++ case OP_TYPESTAR:+ case OP_TYPEPLUS:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ /* The type or prop opcode is skipped in the next iteration. */+ cc += 1;++ if (cc[0] != OP_ANYNL && cc[0] != OP_EXTUNI)+ {+ accelerated_start = cc - 1;+ break;+ }++ if (count < 3)+ count = 3;+ continue;++ case OP_TYPEEXACT:+ if (count < 1)+ count = 1;+ cc += 1 + IMM2_SIZE;+ continue;++ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEPOSUPTO:+ cc += IMM2_SIZE;+ /* Fall through */++ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSQUERY:+ /* The type or prop opcode is skipped in the next iteration. */+ if (count < 3)+ count = 3;+ cc += 1;+ continue;++ case OP_MINSTAR:+ case OP_MINPLUS:+ case OP_MINSTARI:+ case OP_MINPLUSI:+ case OP_NOTMINSTAR:+ case OP_NOTMINPLUS:+ case OP_NOTMINSTARI:+ case OP_NOTMINPLUSI:+ if (count == 2)+ count = 3;+ /* Fall through */++ case OP_STAR:+ case OP_PLUS:+ case OP_POSSTAR:+ case OP_POSPLUS:++ case OP_STARI:+ case OP_PLUSI:+ case OP_POSSTARI:+ case OP_POSPLUSI:++ case OP_NOTSTAR:+ case OP_NOTPLUS:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:++ case OP_NOTSTARI:+ case OP_NOTPLUSI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ accelerated_start = cc;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ case OP_EXACT:+ if (count < 1)+ count = 1;+ cc += 2 + IMM2_SIZE;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ continue;++ case OP_UPTO:+ case OP_MINUPTO:+ case OP_POSUPTO:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSUPTOI:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSUPTO:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSUPTOI:+ cc += IMM2_SIZE;+ /* Fall through */++ case OP_QUERY:+ case OP_MINQUERY:+ case OP_POSQUERY:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_POSQUERYI:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTPOSQUERY:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTPOSQUERYI:+ if (count < 3)+ count = 3;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ continue;++ case OP_CLASS:+ case OP_NCLASS:+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ accelerated_start = cc;+ cc += ((*cc == OP_XCLASS) ? GET(cc, 1) : (unsigned int)(1 + (32 / sizeof(PCRE2_UCHAR))));+#else+ accelerated_start = cc;+ cc += (1 + (32 / sizeof(PCRE2_UCHAR)));+#endif++ switch (*cc)+ {+ case OP_CRMINSTAR:+ case OP_CRMINPLUS:+ if (count == 2)+ count = 3;+ /* Fall through */++ case OP_CRSTAR:+ case OP_CRPLUS:+ case OP_CRPOSSTAR:+ case OP_CRPOSPLUS:+ cc++;+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE))+ {+ /* Exact repeat. */+ cc += 1 + 2 * IMM2_SIZE;+ if (count < 1)+ count = 1;+ continue;+ }++ cc += 2 * IMM2_SIZE;+ /* Fall through */+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSQUERY:+ cc++;+ if (count < 3)+ count = 3;+ continue;++ default:+ /* No repeat. */+ if (count < 1)+ count = 1;+ continue;+ }+ break;++ case OP_BRA:+ case OP_CBRA:+ prev_count = count;+ if (count < 1)+ count = 1;++ if (depth >= 4)+ break;++ if (count < 3 && cc[GET(cc, 1)] == OP_ALT)+ count = 3;++ end = bracketend(cc);+ if (end[-1 - LINK_SIZE] != OP_KET || (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0))+ break;++ prev_count = detect_early_fail(common, cc, private_data_start, depth + 1, prev_count);++ if (prev_count > count)+ count = prev_count;++ if (PRIVATE_DATA(cc) != 0)+ common->private_data_ptrs[begin - common->start] = 1;++ if (count < EARLY_FAIL_ENHANCE_MAX)+ {+ cc = end;+ continue;+ }+ break;++ case OP_KET:+ SLJIT_ASSERT(PRIVATE_DATA(cc) == 0);+ if (cc >= next_alt)+ break;+ cc += 1 + LINK_SIZE;+ continue;+ }++ if (accelerated_start == NULL)+ break;++ if (count == 0)+ {+ common->fast_forward_bc_ptr = accelerated_start;+ common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_skip;+ *private_data_start += sizeof(sljit_sw);+ count = 4;+ }+ else if (count < 3)+ {+ common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_fail;++ if (common->early_fail_start_ptr == 0)+ common->early_fail_start_ptr = *private_data_start;++ *private_data_start += sizeof(sljit_sw);+ common->early_fail_end_ptr = *private_data_start;++ if (*private_data_start > SLJIT_MAX_LOCAL_SIZE)+ return EARLY_FAIL_ENHANCE_MAX;++ count = 4;+ }+ else+ {+ common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_fail_range;++ if (common->early_fail_start_ptr == 0)+ common->early_fail_start_ptr = *private_data_start;++ *private_data_start += 2 * sizeof(sljit_sw);+ common->early_fail_end_ptr = *private_data_start;++ if (*private_data_start > SLJIT_MAX_LOCAL_SIZE)+ return EARLY_FAIL_ENHANCE_MAX;++ count++;+ }++ /* Cannot be part of a repeat. */+ common->private_data_ptrs[begin - common->start] = 1;++ if (count >= EARLY_FAIL_ENHANCE_MAX)+ break;+ }++ if (*cc != OP_ALT && *cc != OP_KET)+ result = EARLY_FAIL_ENHANCE_MAX;+ else if (result < count)+ result = count;++ cc = next_alt;+ next_alt = cc + GET(cc, 1);+ }+while (*cc == OP_ALT);++return result;+}++static int get_class_iterator_size(PCRE2_SPTR cc)+{+sljit_u32 min;+sljit_u32 max;+switch(*cc)+ {+ case OP_CRSTAR:+ case OP_CRPLUS:+ return 2;++ case OP_CRMINSTAR:+ case OP_CRMINPLUS:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ return 1;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ 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;+ }+}++static BOOL detect_repeat(compiler_common *common, PCRE2_SPTR begin)+{+PCRE2_SPTR end = bracketend(begin);+PCRE2_SPTR next;+PCRE2_SPTR next_end;+PCRE2_SPTR max_end;+PCRE2_UCHAR type;+sljit_sw length = end - begin;+sljit_s32 min, max, i;++/* Detect fixed iterations first. */+if (end[-(1 + LINK_SIZE)] != OP_KET || PRIVATE_DATA(begin) != 0)+ return FALSE;++/* /(?:AB){4,6}/ is currently converted to /(?:AB){3}(?AB){1,3}/+ * Skip the check of the second part. */+if (PRIVATE_DATA(end - LINK_SIZE) != 0)+ return TRUE;++next = end;+min = 1;+while (1)+ {+ if (*next != *begin)+ break;+ next_end = bracketend(next);+ if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0)+ break;+ next = next_end;+ min++;+ }++if (min == 2)+ return FALSE;++max = 0;+max_end = next;+if (*next == OP_BRAZERO || *next == OP_BRAMINZERO)+ {+ type = *next;+ while (1)+ {+ if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin)+ break;+ next_end = bracketend(next + 2 + LINK_SIZE);+ if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0)+ break;+ next = next_end;+ max++;+ }++ if (next[0] == type && next[1] == *begin && max >= 1)+ {+ next_end = bracketend(next + 1);+ if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0)+ {+ for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE)+ if (*next_end != OP_KET)+ break;++ if (i == max)+ {+ common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end;+ common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO;+ /* +2 the original and the last. */+ common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2;+ if (min == 1)+ return TRUE;+ min--;+ max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE);+ }+ }+ }+ }++if (min >= 3)+ {+ common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end;+ common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT;+ common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min;+ return TRUE;+ }++return FALSE;+}++#define CASE_ITERATOR_PRIVATE_DATA_1 \+ case OP_MINSTAR: \+ case OP_MINPLUS: \+ case OP_QUERY: \+ case OP_MINQUERY: \+ case OP_MINSTARI: \+ case OP_MINPLUSI: \+ case OP_QUERYI: \+ case OP_MINQUERYI: \+ case OP_NOTMINSTAR: \+ case OP_NOTMINPLUS: \+ case OP_NOTQUERY: \+ case OP_NOTMINQUERY: \+ case OP_NOTMINSTARI: \+ case OP_NOTMINPLUSI: \+ case OP_NOTQUERYI: \+ case OP_NOTMINQUERYI:++#define CASE_ITERATOR_PRIVATE_DATA_2A \+ case OP_STAR: \+ case OP_PLUS: \+ case OP_STARI: \+ case OP_PLUSI: \+ case OP_NOTSTAR: \+ case OP_NOTPLUS: \+ case OP_NOTSTARI: \+ case OP_NOTPLUSI:++#define CASE_ITERATOR_PRIVATE_DATA_2B \+ case OP_UPTO: \+ case OP_MINUPTO: \+ case OP_UPTOI: \+ case OP_MINUPTOI: \+ case OP_NOTUPTO: \+ case OP_NOTMINUPTO: \+ case OP_NOTUPTOI: \+ case OP_NOTMINUPTOI:++#define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \+ case OP_TYPEMINSTAR: \+ case OP_TYPEMINPLUS: \+ case OP_TYPEQUERY: \+ case OP_TYPEMINQUERY:++#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \+ case OP_TYPESTAR: \+ case OP_TYPEPLUS:++#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \+ case OP_TYPEUPTO: \+ case OP_TYPEMINUPTO:++static void set_private_data_ptrs(compiler_common *common, int *private_data_start, PCRE2_SPTR ccend)+{+PCRE2_SPTR cc = common->start;+PCRE2_SPTR alternative;+PCRE2_SPTR end = NULL;+int private_data_ptr = *private_data_start;+int space, size, bracketlen;+BOOL repeat_check = TRUE;++while (cc < ccend)+ {+ space = 0;+ size = 0;+ bracketlen = 0;+ if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE)+ break;++ /* When the bracket is prefixed by a zero iteration, skip the repeat check (at this point). */+ if (repeat_check && (*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND))+ {+ if (detect_repeat(common, cc))+ {+ /* These brackets are converted to repeats, so no global+ based single character repeat is allowed. */+ if (cc >= end)+ end = bracketend(cc);+ }+ }+ repeat_check = TRUE;++ switch(*cc)+ {+ case OP_KET:+ if (common->private_data_ptrs[cc + 1 - common->start] != 0)+ {+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw);+ cc += common->private_data_ptrs[cc + 1 - common->start];+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRAPOS:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_SCOND:+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw);+ bracketlen = 1 + LINK_SIZE;+ break;++ case OP_ASSERTBACK_NA:+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw);++ if (find_vreverse(cc))+ {+ common->private_data_ptrs[cc + 1 - common->start] = 1;+ private_data_ptr += sizeof(sljit_sw);+ }++ bracketlen = 1 + LINK_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw);+ bracketlen = 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_COND:+ /* Might be a hidden SCOND. */+ common->private_data_ptrs[cc - common->start] = 0;+ alternative = cc + GET(cc, 1);+ if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)+ {+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw);+ }+ bracketlen = 1 + LINK_SIZE;+ break;++ case OP_BRA:+ bracketlen = 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_SCBRA:+ bracketlen = 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_BRAZERO:+ case OP_BRAMINZERO:+ case OP_BRAPOSZERO:+ size = 1;+ repeat_check = FALSE;+ break;++ CASE_ITERATOR_PRIVATE_DATA_1+ size = -2;+ space = 1;+ break;++ CASE_ITERATOR_PRIVATE_DATA_2A+ size = -2;+ space = 2;+ break;++ CASE_ITERATOR_PRIVATE_DATA_2B+ size = -(2 + IMM2_SIZE);+ space = 2;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_1+ size = 1;+ space = 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A+ size = 1;+ if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI)+ space = 2;+ break;++ case OP_TYPEUPTO:+ size = 1 + IMM2_SIZE;+ if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI)+ space = 2;+ break;++ case OP_TYPEMINUPTO:+ size = 1 + IMM2_SIZE;+ space = 2;+ break;++ case OP_CLASS:+ case OP_NCLASS:+ size = 1 + 32 / sizeof(PCRE2_UCHAR);+ space = get_class_iterator_size(cc + size);+ break;++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ size = GET(cc, 1);+ space = get_class_iterator_size(cc + size);+ break;+#endif++ default:+ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ break;+ }++ /* Character iterators, which are not inside a repeated bracket,+ gets a private slot instead of allocating it on the stack. */+ if (space > 0 && cc >= end)+ {+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw) * space;+ }++ if (size != 0)+ {+ if (size < 0)+ {+ cc += -size;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ }+ else+ cc += size;+ }++ if (bracketlen > 0)+ {+ if (cc >= end)+ {+ end = bracketend(cc);+ if (end[-1 - LINK_SIZE] == OP_KET)+ end = NULL;+ }+ cc += bracketlen;+ }+ }+*private_data_start = private_data_ptr;+}++/* Returns with a frame_types (always < 0) if no need for frame. */+static int get_framesize(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, BOOL recursive, BOOL *needs_control_head)+{+int length = 0;+int possessive = 0;+BOOL stack_restore = FALSE;+BOOL setsom_found = recursive;+BOOL setmark_found = recursive;+/* The last capture is a local variable even for recursions. */+BOOL capture_last_found = FALSE;++#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+SLJIT_ASSERT(common->control_head_ptr != 0);+*needs_control_head = TRUE;+#else+*needs_control_head = FALSE;+#endif++if (ccend == NULL)+ {+ ccend = bracketend(cc) - (1 + LINK_SIZE);+ if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))+ {+ possessive = length = (common->capture_last_ptr != 0) ? 5 : 3;+ /* This is correct regardless of common->capture_last_ptr. */+ capture_last_found = TRUE;+ }+ cc = next_opcode(common, cc);+ }++SLJIT_ASSERT(cc != NULL);+while (cc < ccend)+ switch(*cc)+ {+ case OP_SET_SOM:+ SLJIT_ASSERT(common->has_set_som);+ stack_restore = TRUE;+ if (!setsom_found)+ {+ length += 2;+ setsom_found = TRUE;+ }+ cc += 1;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_THEN_ARG:+ SLJIT_ASSERT(common->mark_ptr != 0);+ stack_restore = TRUE;+ if (!setmark_found)+ {+ length += 2;+ setmark_found = TRUE;+ }+ if (common->control_head_ptr != 0)+ *needs_control_head = TRUE;+ cc += 1 + 2 + cc[1];+ break;++ case OP_RECURSE:+ stack_restore = TRUE;+ if (common->has_set_som && !setsom_found)+ {+ length += 2;+ setsom_found = TRUE;+ }+ if (common->mark_ptr != 0 && !setmark_found)+ {+ length += 2;+ setmark_found = TRUE;+ }+ if (common->capture_last_ptr != 0 && !capture_last_found)+ {+ length += 2;+ capture_last_found = TRUE;+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_CBRAPOS:+ case OP_SCBRA:+ case OP_SCBRAPOS:+ stack_restore = TRUE;+ if (common->capture_last_ptr != 0 && !capture_last_found)+ {+ length += 2;+ capture_last_found = TRUE;+ }+ length += 3;+ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_THEN:+ stack_restore = TRUE;+ if (common->control_head_ptr != 0)+ *needs_control_head = TRUE;+ cc ++;+ break;++ default:+ stack_restore = TRUE;+ /* Fall through. */++ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ 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_NOTPROP:+ case OP_PROP:+ case OP_ANYNL:+ case OP_NOT_HSPACE:+ case OP_HSPACE:+ 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_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:++ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:++ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:++ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:++ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:++ case OP_TYPEEXACT:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ case OP_TYPEPOSUPTO:++ case OP_CLASS:+ case OP_NCLASS:+ case OP_XCLASS:++ case OP_CALLOUT:+ case OP_CALLOUT_STR:++ case OP_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:++ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ break;+ }++/* Possessive quantifiers can use a special case. */+if (SLJIT_UNLIKELY(possessive == length))+ return stack_restore ? no_frame : no_stack;++if (length > 0)+ return length + 1;+return stack_restore ? no_frame : no_stack;+}++static void init_frame(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, int stackpos, int stacktop)+{+DEFINE_COMPILER;+BOOL setsom_found = FALSE;+BOOL setmark_found = FALSE;+/* The last capture is a local variable even for recursions. */+BOOL capture_last_found = FALSE;+int offset;++/* >= 1 + shortest item size (2) */+SLJIT_UNUSED_ARG(stacktop);+SLJIT_ASSERT(stackpos >= stacktop + 2);++stackpos = STACK(stackpos);+if (ccend == NULL)+ {+ ccend = bracketend(cc) - (1 + LINK_SIZE);+ if (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)+ cc = next_opcode(common, cc);+ }++SLJIT_ASSERT(cc != NULL);+while (cc < ccend)+ switch(*cc)+ {+ case OP_SET_SOM:+ SLJIT_ASSERT(common->has_set_som);+ if (!setsom_found)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));+ stackpos -= SSIZE_OF(sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= SSIZE_OF(sw);+ setsom_found = TRUE;+ }+ cc += 1;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_THEN_ARG:+ SLJIT_ASSERT(common->mark_ptr != 0);+ if (!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 -= SSIZE_OF(sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= SSIZE_OF(sw);+ setmark_found = TRUE;+ }+ cc += 1 + 2 + cc[1];+ break;++ case OP_RECURSE:+ if (common->has_set_som && !setsom_found)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));+ stackpos -= SSIZE_OF(sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= SSIZE_OF(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 -= SSIZE_OF(sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= SSIZE_OF(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 -= SSIZE_OF(sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= SSIZE_OF(sw);+ capture_last_found = TRUE;+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_CBRAPOS:+ case OP_SCBRA:+ case OP_SCBRAPOS:+ 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 -= SSIZE_OF(sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= SSIZE_OF(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 -= SSIZE_OF(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 -= SSIZE_OF(sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);+ stackpos -= SSIZE_OF(sw);++ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ default:+ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ break;+ }++OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, 0);+SLJIT_ASSERT(stackpos == STACK(stacktop));+}++#define RECURSE_TMP_REG_COUNT 3++typedef struct delayed_mem_copy_status {+ struct sljit_compiler *compiler;+ int store_bases[RECURSE_TMP_REG_COUNT];+ int store_offsets[RECURSE_TMP_REG_COUNT];+ int tmp_regs[RECURSE_TMP_REG_COUNT];+ int saved_tmp_regs[RECURSE_TMP_REG_COUNT];+ int next_tmp_reg;+} delayed_mem_copy_status;++static void delayed_mem_copy_init(delayed_mem_copy_status *status, compiler_common *common)+{+int i;++for (i = 0; i < RECURSE_TMP_REG_COUNT; i++)+ {+ SLJIT_ASSERT(status->tmp_regs[i] >= 0);+ SLJIT_ASSERT(sljit_get_register_index(SLJIT_GP_REGISTER, status->saved_tmp_regs[i]) < 0 || status->tmp_regs[i] == status->saved_tmp_regs[i]);++ status->store_bases[i] = -1;+ }+status->next_tmp_reg = 0;+status->compiler = common->compiler;+}++static void delayed_mem_copy_move(delayed_mem_copy_status *status, int load_base, sljit_sw load_offset,+ int store_base, sljit_sw store_offset)+{+struct sljit_compiler *compiler = status->compiler;+int next_tmp_reg = status->next_tmp_reg;+int tmp_reg = status->tmp_regs[next_tmp_reg];++SLJIT_ASSERT(load_base > 0 && store_base > 0);++if (status->store_bases[next_tmp_reg] == -1)+ {+ /* Preserve virtual registers. */+ if (sljit_get_register_index(SLJIT_GP_REGISTER, status->saved_tmp_regs[next_tmp_reg]) < 0)+ OP1(SLJIT_MOV, status->saved_tmp_regs[next_tmp_reg], 0, tmp_reg, 0);+ }+else+ OP1(SLJIT_MOV, SLJIT_MEM1(status->store_bases[next_tmp_reg]), status->store_offsets[next_tmp_reg], tmp_reg, 0);++OP1(SLJIT_MOV, tmp_reg, 0, SLJIT_MEM1(load_base), load_offset);+status->store_bases[next_tmp_reg] = store_base;+status->store_offsets[next_tmp_reg] = store_offset;++status->next_tmp_reg = (next_tmp_reg + 1) % RECURSE_TMP_REG_COUNT;+}++static void delayed_mem_copy_finish(delayed_mem_copy_status *status)+{+struct sljit_compiler *compiler = status->compiler;+int next_tmp_reg = status->next_tmp_reg;+int tmp_reg, saved_tmp_reg, i;++for (i = 0; i < RECURSE_TMP_REG_COUNT; i++)+ {+ if (status->store_bases[next_tmp_reg] != -1)+ {+ tmp_reg = status->tmp_regs[next_tmp_reg];+ saved_tmp_reg = status->saved_tmp_regs[next_tmp_reg];++ OP1(SLJIT_MOV, SLJIT_MEM1(status->store_bases[next_tmp_reg]), status->store_offsets[next_tmp_reg], tmp_reg, 0);++ /* Restore virtual registers. */+ if (sljit_get_register_index(SLJIT_GP_REGISTER, saved_tmp_reg) < 0)+ OP1(SLJIT_MOV, tmp_reg, 0, saved_tmp_reg, 0);+ }++ next_tmp_reg = (next_tmp_reg + 1) % RECURSE_TMP_REG_COUNT;+ }+}++#undef RECURSE_TMP_REG_COUNT++static BOOL recurse_check_bit(compiler_common *common, sljit_sw bit_index)+{+uint8_t *byte;+uint8_t mask;++SLJIT_ASSERT((bit_index & (sizeof(sljit_sw) - 1)) == 0);++bit_index >>= SLJIT_WORD_SHIFT;++SLJIT_ASSERT((bit_index >> 3) < common->recurse_bitset_size);++mask = 1 << (bit_index & 0x7);+byte = common->recurse_bitset + (bit_index >> 3);++if (*byte & mask)+ return FALSE;++*byte |= mask;+return TRUE;+}++enum get_recurse_flags {+ recurse_flag_quit_found = (1 << 0),+ recurse_flag_accept_found = (1 << 1),+ recurse_flag_setsom_found = (1 << 2),+ recurse_flag_setmark_found = (1 << 3),+ recurse_flag_control_head_found = (1 << 4),+};++static int get_recurse_data_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, uint32_t *result_flags)+{+int length = 1;+int size, offset;+PCRE2_SPTR alternative;+uint32_t recurse_flags = 0;++memset(common->recurse_bitset, 0, common->recurse_bitset_size);++#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+SLJIT_ASSERT(common->control_head_ptr != 0);+recurse_flags |= recurse_flag_control_head_found;+#endif++/* Calculate the sum of the private machine words. */+while (cc < ccend)+ {+ size = 0;+ switch(*cc)+ {+ case OP_SET_SOM:+ SLJIT_ASSERT(common->has_set_som);+ recurse_flags |= recurse_flag_setsom_found;+ cc += 1;+ break;++ case OP_RECURSE:+ if (common->has_set_som)+ recurse_flags |= recurse_flag_setsom_found;+ if (common->mark_ptr != 0)+ recurse_flags |= recurse_flag_setmark_found;+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))+ length++;+ cc += 1 + LINK_SIZE;+ break;++ case OP_KET:+ offset = PRIVATE_DATA(cc);+ if (offset != 0)+ {+ if (recurse_check_bit(common, offset))+ length++;+ SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);+ cc += PRIVATE_DATA(cc + 1);+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRAPOS:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_SCOND:+ SLJIT_ASSERT(PRIVATE_DATA(cc) != 0);+ if (recurse_check_bit(common, PRIVATE_DATA(cc)))+ length++;+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_SCBRA:+ offset = GET2(cc, 1 + LINK_SIZE);+ if (recurse_check_bit(common, OVECTOR(offset << 1)))+ {+ SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));+ length += 2;+ }+ if (common->optimized_cbracket[offset] == 0 && recurse_check_bit(common, OVECTOR_PRIV(offset)))+ length++;+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))+ length++;+ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ offset = GET2(cc, 1 + LINK_SIZE);+ if (recurse_check_bit(common, OVECTOR(offset << 1)))+ {+ SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));+ length += 2;+ }+ if (recurse_check_bit(common, OVECTOR_PRIV(offset)))+ length++;+ if (recurse_check_bit(common, PRIVATE_DATA(cc)))+ length++;+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))+ length++;+ 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) && recurse_check_bit(common, PRIVATE_DATA(cc)))+ length++;+ cc += 1 + LINK_SIZE;+ break;++ CASE_ITERATOR_PRIVATE_DATA_1+ offset = PRIVATE_DATA(cc);+ if (offset != 0 && recurse_check_bit(common, offset))+ length++;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_PRIVATE_DATA_2A+ offset = PRIVATE_DATA(cc);+ if (offset != 0 && recurse_check_bit(common, offset))+ {+ SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));+ length += 2;+ }+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_PRIVATE_DATA_2B+ offset = PRIVATE_DATA(cc);+ if (offset != 0 && recurse_check_bit(common, offset))+ {+ SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));+ length += 2;+ }+ cc += 2 + IMM2_SIZE;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_1+ offset = PRIVATE_DATA(cc);+ if (offset != 0 && recurse_check_bit(common, offset))+ length++;+ cc += 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A+ offset = PRIVATE_DATA(cc);+ if (offset != 0 && recurse_check_bit(common, offset))+ {+ SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));+ length += 2;+ }+ cc += 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2B+ offset = PRIVATE_DATA(cc);+ if (offset != 0 && recurse_check_bit(common, offset))+ {+ SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));+ length += 2;+ }+ cc += 1 + IMM2_SIZE;+ break;++ case OP_CLASS:+ case OP_NCLASS:+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR);+#else+ size = 1 + 32 / (int)sizeof(PCRE2_UCHAR);+#endif++ offset = PRIVATE_DATA(cc);+ if (offset != 0 && recurse_check_bit(common, offset))+ length += get_class_iterator_size(cc + size);+ cc += size;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_THEN_ARG:+ SLJIT_ASSERT(common->mark_ptr != 0);+ recurse_flags |= recurse_flag_setmark_found;+ if (common->control_head_ptr != 0)+ recurse_flags |= recurse_flag_control_head_found;+ if (*cc != OP_MARK)+ recurse_flags |= recurse_flag_quit_found;++ cc += 1 + 2 + cc[1];+ break;++ case OP_PRUNE:+ case OP_SKIP:+ case OP_COMMIT:+ recurse_flags |= recurse_flag_quit_found;+ cc++;+ break;++ case OP_SKIP_ARG:+ recurse_flags |= recurse_flag_quit_found;+ cc += 1 + 2 + cc[1];+ break;++ case OP_THEN:+ SLJIT_ASSERT(common->control_head_ptr != 0);+ recurse_flags |= recurse_flag_quit_found | recurse_flag_control_head_found;+ cc++;+ break;++ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ recurse_flags |= recurse_flag_accept_found;+ cc++;+ break;++ default:+ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ break;+ }+ }+SLJIT_ASSERT(cc == ccend);++if (recurse_flags & recurse_flag_control_head_found)+ length++;+if (recurse_flags & recurse_flag_quit_found)+ {+ if (recurse_flags & recurse_flag_setsom_found)+ length++;+ if (recurse_flags & recurse_flag_setmark_found)+ length++;+ }++*result_flags = recurse_flags;+return length;+}++enum copy_recurse_data_types {+ recurse_copy_from_global,+ recurse_copy_private_to_global,+ recurse_copy_shared_to_global,+ recurse_copy_kept_shared_to_global,+ recurse_swap_global+};++static void copy_recurse_data(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend,+ int type, int stackptr, int stacktop, uint32_t recurse_flags)+{+delayed_mem_copy_status status;+PCRE2_SPTR alternative;+sljit_sw private_srcw[2];+sljit_sw shared_srcw[3];+sljit_sw kept_shared_srcw[2];+int private_count, shared_count, kept_shared_count;+int from_sp, base_reg, offset, i;++memset(common->recurse_bitset, 0, common->recurse_bitset_size);++#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+SLJIT_ASSERT(common->control_head_ptr != 0);+recurse_check_bit(common, common->control_head_ptr);+#endif++switch (type)+ {+ case recurse_copy_from_global:+ from_sp = TRUE;+ base_reg = STACK_TOP;+ break;++ case recurse_copy_private_to_global:+ case recurse_copy_shared_to_global:+ case recurse_copy_kept_shared_to_global:+ from_sp = FALSE;+ base_reg = STACK_TOP;+ break;++ default:+ SLJIT_ASSERT(type == recurse_swap_global);+ from_sp = FALSE;+ base_reg = TMP2;+ break;+ }++stackptr = STACK(stackptr);+stacktop = STACK(stacktop);++status.tmp_regs[0] = TMP1;+status.saved_tmp_regs[0] = TMP1;++if (base_reg != TMP2)+ {+ status.tmp_regs[1] = TMP2;+ status.saved_tmp_regs[1] = TMP2;+ }+else+ {+ status.saved_tmp_regs[1] = RETURN_ADDR;+ if (HAS_VIRTUAL_REGISTERS)+ status.tmp_regs[1] = STR_PTR;+ else+ status.tmp_regs[1] = RETURN_ADDR;+ }++status.saved_tmp_regs[2] = TMP3;+if (HAS_VIRTUAL_REGISTERS)+ status.tmp_regs[2] = STR_END;+else+ status.tmp_regs[2] = TMP3;++delayed_mem_copy_init(&status, common);++if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global)+ {+ SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_private_to_global || type == recurse_swap_global);++ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, common->recursive_head_ptr);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, common->recursive_head_ptr, base_reg, stackptr);+ }++stackptr += sizeof(sljit_sw);++#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+if (type != recurse_copy_shared_to_global)+ {+ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, common->control_head_ptr);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, common->control_head_ptr, base_reg, stackptr);+ }++stackptr += sizeof(sljit_sw);+#endif++while (cc < ccend)+ {+ private_count = 0;+ shared_count = 0;+ kept_shared_count = 0;++ switch(*cc)+ {+ case OP_SET_SOM:+ SLJIT_ASSERT(common->has_set_som);+ if ((recurse_flags & recurse_flag_quit_found) && recurse_check_bit(common, OVECTOR(0)))+ {+ kept_shared_srcw[0] = OVECTOR(0);+ kept_shared_count = 1;+ }+ cc += 1;+ break;++ case OP_RECURSE:+ if (recurse_flags & recurse_flag_quit_found)+ {+ if (common->has_set_som && recurse_check_bit(common, OVECTOR(0)))+ {+ kept_shared_srcw[0] = OVECTOR(0);+ kept_shared_count = 1;+ }+ if (common->mark_ptr != 0 && recurse_check_bit(common, common->mark_ptr))+ {+ kept_shared_srcw[kept_shared_count] = common->mark_ptr;+ kept_shared_count++;+ }+ }+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))+ {+ shared_srcw[0] = common->capture_last_ptr;+ shared_count = 1;+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_KET:+ private_srcw[0] = PRIVATE_DATA(cc);+ if (private_srcw[0] != 0)+ {+ if (recurse_check_bit(common, private_srcw[0]))+ private_count = 1;+ SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);+ cc += PRIVATE_DATA(cc + 1);+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRAPOS:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_SCOND:+ private_srcw[0] = PRIVATE_DATA(cc);+ if (recurse_check_bit(common, private_srcw[0]))+ private_count = 1;+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_SCBRA:+ offset = GET2(cc, 1 + LINK_SIZE);+ shared_srcw[0] = OVECTOR(offset << 1);+ if (recurse_check_bit(common, shared_srcw[0]))+ {+ shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw);+ SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1]));+ shared_count = 2;+ }++ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))+ {+ shared_srcw[shared_count] = common->capture_last_ptr;+ shared_count++;+ }++ if (common->optimized_cbracket[offset] == 0)+ {+ private_srcw[0] = OVECTOR_PRIV(offset);+ if (recurse_check_bit(common, private_srcw[0]))+ private_count = 1;+ }++ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ offset = GET2(cc, 1 + LINK_SIZE);+ shared_srcw[0] = OVECTOR(offset << 1);+ if (recurse_check_bit(common, shared_srcw[0]))+ {+ shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw);+ SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1]));+ shared_count = 2;+ }++ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))+ {+ shared_srcw[shared_count] = common->capture_last_ptr;+ shared_count++;+ }++ private_srcw[0] = PRIVATE_DATA(cc);+ if (recurse_check_bit(common, private_srcw[0]))+ private_count = 1;++ offset = OVECTOR_PRIV(offset);+ if (recurse_check_bit(common, offset))+ {+ private_srcw[private_count] = offset;+ private_count++;+ }+ 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)+ {+ private_srcw[0] = PRIVATE_DATA(cc);+ if (recurse_check_bit(common, private_srcw[0]))+ private_count = 1;+ }+ cc += 1 + LINK_SIZE;+ break;++ CASE_ITERATOR_PRIVATE_DATA_1+ private_srcw[0] = PRIVATE_DATA(cc);+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))+ private_count = 1;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_PRIVATE_DATA_2A+ private_srcw[0] = PRIVATE_DATA(cc);+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))+ {+ private_count = 2;+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));+ }+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_PRIVATE_DATA_2B+ private_srcw[0] = PRIVATE_DATA(cc);+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))+ {+ private_count = 2;+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));+ }+ cc += 2 + IMM2_SIZE;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_1+ private_srcw[0] = PRIVATE_DATA(cc);+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))+ private_count = 1;+ cc += 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A+ private_srcw[0] = PRIVATE_DATA(cc);+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))+ {+ private_count = 2;+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));+ }+ cc += 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2B+ private_srcw[0] = PRIVATE_DATA(cc);+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))+ {+ private_count = 2;+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));+ }+ cc += 1 + IMM2_SIZE;+ break;++ case OP_CLASS:+ case OP_NCLASS:+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ i = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR);+#else+ i = 1 + 32 / (int)sizeof(PCRE2_UCHAR);+#endif+ if (PRIVATE_DATA(cc) != 0)+ {+ private_count = 1;+ private_srcw[0] = PRIVATE_DATA(cc);+ switch(get_class_iterator_size(cc + i))+ {+ case 1:+ break;++ case 2:+ if (recurse_check_bit(common, private_srcw[0]))+ {+ private_count = 2;+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));+ }+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ }+ cc += i;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_THEN_ARG:+ SLJIT_ASSERT(common->mark_ptr != 0);+ if ((recurse_flags & recurse_flag_quit_found) && recurse_check_bit(common, common->mark_ptr))+ {+ kept_shared_srcw[0] = common->mark_ptr;+ kept_shared_count = 1;+ }+ if (common->control_head_ptr != 0 && recurse_check_bit(common, common->control_head_ptr))+ {+ private_srcw[0] = common->control_head_ptr;+ private_count = 1;+ }+ cc += 1 + 2 + cc[1];+ break;++ case OP_THEN:+ SLJIT_ASSERT(common->control_head_ptr != 0);+ if (recurse_check_bit(common, common->control_head_ptr))+ {+ private_srcw[0] = common->control_head_ptr;+ private_count = 1;+ }+ cc++;+ break;++ default:+ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ continue;+ }++ if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global)+ {+ SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_private_to_global || type == recurse_swap_global);++ for (i = 0; i < private_count; i++)+ {+ SLJIT_ASSERT(private_srcw[i] != 0);++ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, private_srcw[i]);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, private_srcw[i], base_reg, stackptr);++ stackptr += sizeof(sljit_sw);+ }+ }+ else+ stackptr += sizeof(sljit_sw) * private_count;++ if (type != recurse_copy_private_to_global && type != recurse_copy_kept_shared_to_global)+ {+ SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_shared_to_global || type == recurse_swap_global);++ for (i = 0; i < shared_count; i++)+ {+ SLJIT_ASSERT(shared_srcw[i] != 0);++ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, shared_srcw[i]);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, shared_srcw[i], base_reg, stackptr);++ stackptr += sizeof(sljit_sw);+ }+ }+ else+ stackptr += sizeof(sljit_sw) * shared_count;++ if (type != recurse_copy_private_to_global && type != recurse_swap_global)+ {+ SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_shared_to_global || type == recurse_copy_kept_shared_to_global);++ for (i = 0; i < kept_shared_count; i++)+ {+ SLJIT_ASSERT(kept_shared_srcw[i] != 0);++ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, kept_shared_srcw[i]);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, kept_shared_srcw[i], base_reg, stackptr);++ stackptr += sizeof(sljit_sw);+ }+ }+ else+ stackptr += sizeof(sljit_sw) * kept_shared_count;+ }++SLJIT_ASSERT(cc == ccend && stackptr == stacktop);++delayed_mem_copy_finish(&status);+}++static SLJIT_INLINE PCRE2_SPTR set_then_offsets(compiler_common *common, PCRE2_SPTR cc, sljit_u8 *current_offset)+{+PCRE2_SPTR end = bracketend(cc);+BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT;++/* Assert captures then. */+if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA)+ current_offset = NULL;+/* Conditional block does not. */+if (*cc == OP_COND || *cc == OP_SCOND)+ has_alternatives = FALSE;++cc = next_opcode(common, cc);++if (has_alternatives)+ {+ if (*cc == OP_REVERSE)+ cc += 1 + IMM2_SIZE;+ else if (*cc == OP_VREVERSE)+ cc += 1 + 2 * IMM2_SIZE;++ current_offset = common->then_offsets + (cc - common->start);+ }++while (cc < end)+ {+ if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND))+ cc = set_then_offsets(common, cc, current_offset);+ else+ {+ if (*cc == OP_ALT && has_alternatives)+ {+ cc += 1 + LINK_SIZE;++ if (*cc == OP_REVERSE)+ cc += 1 + IMM2_SIZE;+ else if (*cc == OP_VREVERSE)+ cc += 1 + 2 * IMM2_SIZE;++ current_offset = common->then_offsets + (cc - common->start);+ continue;+ }++ if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL)+ *current_offset = 1;+ cc = next_opcode(common, cc);+ }+ }++return end;+}++#undef CASE_ITERATOR_PRIVATE_DATA_1+#undef CASE_ITERATOR_PRIVATE_DATA_2A+#undef CASE_ITERATOR_PRIVATE_DATA_2B+#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_1+#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2A+#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2B++static SLJIT_INLINE BOOL is_powerof2(unsigned int value)+{+return (value & (value - 1)) == 0;+}++static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)+{+while (list != NULL)+ {+ /* sljit_set_label is clever enough to do nothing+ if either the jump or the label is NULL. */+ SET_LABEL(list->jump, label);+ list = list->next;+ }+}++static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump *jump)+{+jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));+if (list_item)+ {+ list_item->next = *list;+ list_item->jump = jump;+ *list = list_item;+ }+}++static void add_stub(compiler_common *common, struct sljit_jump *start)+{+DEFINE_COMPILER;+stub_list *list_item = sljit_alloc_memory(compiler, sizeof(stub_list));++if (list_item)+ {+ list_item->start = start;+ list_item->quit = LABEL();+ list_item->next = common->stubs;+ common->stubs = list_item;+ }+}++static void flush_stubs(compiler_common *common)+{+DEFINE_COMPILER;+stub_list *list_item = common->stubs;++while (list_item)+ {+ JUMPHERE(list_item->start);+ add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));+ JUMPTO(SLJIT_JUMP, list_item->quit);+ list_item = list_item->next;+ }+common->stubs = NULL;+}++static SLJIT_INLINE void count_match(compiler_common *common)+{+DEFINE_COMPILER;++OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);+add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO));+}++static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)+{+/* May destroy all locals and registers except TMP2. */+DEFINE_COMPILER;++SLJIT_ASSERT(size > 0);+OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * SSIZE_OF(sw));+#ifdef DESTROY_REGISTERS+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);+OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);+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_LESS, STACK_TOP, 0, STACK_LIMIT, 0));+}++static SLJIT_INLINE void free_stack(compiler_common *common, int size)+{+DEFINE_COMPILER;++SLJIT_ASSERT(size > 0);+OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * SSIZE_OF(sw));+}++static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size)+{+DEFINE_COMPILER;+sljit_uw *result;++if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;++result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw), compiler->allocator_data);+if (SLJIT_UNLIKELY(result == NULL))+ {+ sljit_set_compiler_memory_error(compiler);+ return NULL;+ }++*(void**)result = common->read_only_data_head;+common->read_only_data_head = (void *)result;+return result + 1;+}++static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)+{+DEFINE_COMPILER;+struct sljit_label *loop;+sljit_s32 i;++/* At this point we can freely use all temporary registers. */+SLJIT_ASSERT(length > 1);+/* TMP1 returns with begin - 1. */+OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1));+if (length < 8)+ {+ for (i = 1; i < length; i++)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), SLJIT_R0, 0);+ }+else+ {+ if (sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS)+ {+ GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START);+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);+ loop = LABEL();+ sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw));+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, loop);+ }+ else+ {+ GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START + sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);+ loop = LABEL();+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);+ OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));+ 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_early_fail(compiler_common *common)+{+DEFINE_COMPILER;+sljit_u32 size = (sljit_u32)(common->early_fail_end_ptr - common->early_fail_start_ptr);+sljit_u32 uncleared_size;+sljit_s32 src = SLJIT_IMM;+sljit_s32 i;+struct sljit_label *loop;++SLJIT_ASSERT(common->early_fail_start_ptr < common->early_fail_end_ptr);++if (size == sizeof(sljit_sw))+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->early_fail_start_ptr, SLJIT_IMM, 0);+ return;+ }++if (sljit_get_register_index(SLJIT_GP_REGISTER, TMP3) >= 0 && !sljit_has_cpu_feature(SLJIT_HAS_ZERO_REGISTER))+ {+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);+ src = TMP3;+ }++if (size <= 6 * sizeof(sljit_sw))+ {+ for (i = common->early_fail_start_ptr; i < common->early_fail_end_ptr; i += sizeof(sljit_sw))+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, src, 0);+ return;+ }++GET_LOCAL_BASE(TMP1, 0, common->early_fail_start_ptr);++uncleared_size = ((size / sizeof(sljit_sw)) % 3) * sizeof(sljit_sw);++OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, size - uncleared_size);++loop = LABEL();+OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), 0, src, 0);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));+OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -2 * SSIZE_OF(sw), src, 0);+OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -1 * SSIZE_OF(sw), src, 0);+CMPTO(SLJIT_LESS, TMP1, 0, TMP2, 0, loop);++if (uncleared_size >= sizeof(sljit_sw))+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), 0, src, 0);++if (uncleared_size >= 2 * sizeof(sljit_sw))+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), sizeof(sljit_sw), src, 0);+}++static SLJIT_INLINE void do_reset_match(compiler_common *common, int length)+{+DEFINE_COMPILER;+struct sljit_label *loop;+int i;++SLJIT_ASSERT(length > 1);+/* OVECTOR(1) contains the "string begin - 1" constant. */+if (length > 2)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));+if (length < 8)+ {+ for (i = 2; i < length; i++)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), TMP1, 0);+ }+else+ {+ if (sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS)+ {+ GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);+ loop = LABEL();+ sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, loop);+ }+ else+ {+ GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + 2 * sizeof(sljit_sw));+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);+ loop = LABEL();+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(sljit_sw));+ OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, loop);+ }+ }++if (!HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, stack));+else+ OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);++if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);+if (common->control_head_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);+if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end));+}++static sljit_sw SLJIT_FUNC do_search_mark(sljit_sw *current, PCRE2_SPTR skip_arg)+{+while (current != NULL)+ {+ switch (current[1])+ {+ case type_then_trap:+ break;++ case type_mark:+ if (PRIV(strcmp)(skip_arg, (PCRE2_SPTR)current[2]) == 0)+ return current[3];+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]);+ current = (sljit_sw*)current[0];+ }+return 0;+}++static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)+{+DEFINE_COMPILER;+struct sljit_label *loop;+BOOL has_pre;++/* At this point we can freely use all registers. */+OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0);++if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);+ if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);+ OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, oveccount));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);+ if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);+ OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),+ SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));+ }+else+ {+ OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, match_data));+ if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);+ OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, oveccount));+ OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);+ if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R0, 0);+ OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));+ }++has_pre = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS;++GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0));+OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? SLJIT_R0 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));++loop = LABEL();++if (has_pre)+ sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));+else+ {+ OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));+ }++OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, sizeof(PCRE2_SIZE));+OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0);+/* Copy the integer value to the output buffer */+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif++SLJIT_ASSERT(sizeof(PCRE2_SIZE) == 4 || sizeof(PCRE2_SIZE) == 8);+OP1(((sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV), SLJIT_MEM1(SLJIT_R2), 0, SLJIT_S1, 0);++OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+JUMPTO(SLJIT_NOT_ZERO, loop);++/* Calculate the return value, which is the maximum ovector value. */+if (topbracket > 1)+ {+ if (sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * SSIZE_OF(sw))) == SLJIT_SUCCESS)+ {+ GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);++ /* OVECTOR(0) is never equal to SLJIT_S2. */+ loop = LABEL();+ sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * SSIZE_OF(sw)));+ OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);+ }+ else+ {+ GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + (topbracket - 1) * 2 * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);++ /* OVECTOR(0) is never equal to SLJIT_S2. */+ loop = LABEL();+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0);+ OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * SSIZE_OF(sw));+ OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);+ }+ }+else+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);+}++static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit)+{+DEFINE_COMPILER;+sljit_s32 mov_opcode;+sljit_s32 arguments_reg = !HAS_VIRTUAL_REGISTERS ? ARGUMENTS : SLJIT_R1;++SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S0, str_end_must_be_saved_reg0);+SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0+ && (common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start != 0 : common->hit_start == 0));++if (arguments_reg != ARGUMENTS)+ OP1(SLJIT_MOV, arguments_reg, 0, ARGUMENTS, 0);+OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP),+ common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start : common->start_ptr);+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_PARTIAL);++/* Store match begin and end. */+OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, begin));+OP1(SLJIT_MOV, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0);+OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, match_data));++mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;++OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S1, 0);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector), SLJIT_R2, 0);++OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_S1, 0);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+OP2(SLJIT_ASHR, STR_END, 0, STR_END, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector) + sizeof(PCRE2_SIZE), STR_END, 0);++JUMPTO(SLJIT_JUMP, quit);+}++static SLJIT_INLINE void check_start_used_ptr(compiler_common *common)+{+/* May destroy TMP1. */+DEFINE_COMPILER;+struct sljit_jump *jump;++if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ /* The value of -1 must be kept for start_used_ptr! */+ OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, 1);+ /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting+ is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */+ jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ JUMPHERE(jump);+ }+else if (common->mode == PCRE2_JIT_PARTIAL_HARD)+ {+ jump = CMP(SLJIT_LESS_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ JUMPHERE(jump);+ }+}++static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, PCRE2_SPTR cc)+{+/* Detects if the character has an othercase. */+unsigned int c;++#ifdef SUPPORT_UNICODE+if (common->utf || common->ucp)+ {+ if (common->utf)+ {+ GETCHAR(c, cc);+ }+ else+ c = *cc;++ if (c > 127)+ return c != UCD_OTHERCASE(c);++ return common->fcc[c] != c;+ }+else+#endif+ c = *cc;+return MAX_255(c) ? common->fcc[c] != c : FALSE;+}++static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)+{+/* Returns with the othercase. */+#ifdef SUPPORT_UNICODE+if ((common->utf || common->ucp) && c > 127)+ return UCD_OTHERCASE(c);+#endif+return TABLE_GET(c, common->fcc, c);+}++static unsigned int char_get_othercase_bit(compiler_common *common, PCRE2_SPTR cc)+{+/* Detects if the character and its othercase has only 1 bit difference. */+unsigned int c, oc, bit;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+int n;+#endif++#ifdef SUPPORT_UNICODE+if (common->utf || common->ucp)+ {+ if (common->utf)+ {+ GETCHAR(c, cc);+ }+ else+ c = *cc;++ if (c <= 127)+ oc = common->fcc[c];+ else+ oc = UCD_OTHERCASE(c);+ }+else+ {+ c = *cc;+ oc = TABLE_GET(c, common->fcc, c);+ }+#else+c = *cc;+oc = TABLE_GET(c, common->fcc, c);+#endif++SLJIT_ASSERT(c != oc);++bit = c ^ oc;+/* Optimized for English alphabet. */+if (c <= 127 && bit == 0x20)+ return (0 << 8) | 0x20;++/* Since c != oc, they must have at least 1 bit difference. */+if (!is_powerof2(bit))+ return 0;++#if PCRE2_CODE_UNIT_WIDTH == 8++#ifdef SUPPORT_UNICODE+if (common->utf && c > 127)+ {+ n = GET_EXTRALEN(*cc);+ while ((bit & 0x3f) == 0)+ {+ n--;+ bit >>= 6;+ }+ return (n << 8) | bit;+ }+#endif /* SUPPORT_UNICODE */+return (0 << 8) | bit;++#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32++#ifdef SUPPORT_UNICODE+if (common->utf && c > 65535)+ {+ if (bit >= (1u << 10))+ bit >>= 10;+ else+ return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));+ }+#endif /* SUPPORT_UNICODE */+return (bit < 256) ? ((0u << 8) | bit) : ((1u << 8) | (bit >> 8));++#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+}++static void check_partial(compiler_common *common, BOOL force)+{+/* Checks whether a partial matching is occurred. Does not modify registers. */+DEFINE_COMPILER;+struct sljit_jump *jump = NULL;++SLJIT_ASSERT(!force || common->mode != PCRE2_JIT_COMPLETE);++if (common->mode == PCRE2_JIT_COMPLETE)+ return;++if (!force && !common->allow_empty_partial)+ jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);++if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+else+ {+ if (common->partialmatchlabel != NULL)+ JUMPTO(SLJIT_JUMP, common->partialmatchlabel);+ else+ add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));+ }++if (jump != NULL)+ JUMPHERE(jump);+}++static void check_str_end(compiler_common *common, jump_list **end_reached)+{+/* Does not affect registers. Usually used in a tight spot. */+DEFINE_COMPILER;+struct sljit_jump *jump;++if (common->mode == PCRE2_JIT_COMPLETE)+ {+ add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+ return;+ }++jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+ add_jump(compiler, end_reached, JUMP(SLJIT_JUMP));+ }+else+ {+ add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));+ if (common->partialmatchlabel != NULL)+ JUMPTO(SLJIT_JUMP, common->partialmatchlabel);+ else+ add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));+ }+JUMPHERE(jump);+}++static void detect_partial_match(compiler_common *common, jump_list **backtracks)+{+DEFINE_COMPILER;+struct sljit_jump *jump;++if (common->mode == PCRE2_JIT_COMPLETE)+ {+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+ return;+ }++/* Partial matching mode. */+jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);+if (!common->allow_empty_partial)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));+else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1));++if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ }+else+ {+ if (common->partialmatchlabel != NULL)+ JUMPTO(SLJIT_JUMP, common->partialmatchlabel);+ else+ add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));+ }+JUMPHERE(jump);+}++static void process_partial_match(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *jump;++/* Partial matching mode. */+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+ JUMPHERE(jump);+ }+else if (common->mode == PCRE2_JIT_PARTIAL_HARD)+ {+ if (common->partialmatchlabel != NULL)+ CMPTO(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0, common->partialmatchlabel);+ else+ add_jump(compiler, &common->partialmatch, CMP(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));+ }+}++static void detect_partial_match_to(compiler_common *common, struct sljit_label *label)+{+DEFINE_COMPILER;++CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, label);+process_partial_match(common);+}++static void peek_char(compiler_common *common, sljit_u32 max, sljit_s32 dst, sljit_sw dstw, jump_list **backtracks)+{+/* Reads the character into TMP1, keeps STR_PTR.+Does not check STR_END. TMP2, dst, RETURN_ADDR Destroyed. */+DEFINE_COMPILER;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_jump *jump;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */++SLJIT_UNUSED_ARG(max);+SLJIT_UNUSED_ARG(dst);+SLJIT_UNUSED_ARG(dstw);+SLJIT_UNUSED_ARG(backtracks);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+ if (max < 128) return;++ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);+ OP1(SLJIT_MOV, dst, dstw, STR_PTR, 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, common->invalid_utf ? &common->utfreadchar_invalid : &common->utfreadchar, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, STR_PTR, 0, dst, dstw);+ if (backtracks && common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf)+ {+ if (max < 0xd800) return;++ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);++ if (common->invalid_utf)+ {+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);+ OP1(SLJIT_MOV, dst, dstw, STR_PTR, 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, STR_PTR, 0, dst, dstw);+ if (backtracks && common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ }+ else+ {+ /* TMP2 contains the high surrogate. */+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+ }++ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf)+ {+ if (max < 0xd800) return;++ if (backtracks != NULL)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));+ }+ else+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000);+ SELECT(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR, TMP1);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);+ SELECT(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR, TMP1);+ }+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */+}++static void peek_char_back(compiler_common *common, sljit_u32 max, jump_list **backtracks)+{+/* Reads one character back without moving STR_PTR. TMP2 must+contain the start of the subject buffer. Affects TMP1, TMP2, and RETURN_ADDR. */+DEFINE_COMPILER;++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_jump *jump;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */++SLJIT_UNUSED_ARG(max);+SLJIT_UNUSED_ARG(backtracks);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+ if (max < 128) return;++ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);+ if (common->invalid_utf)+ {+ add_jump(compiler, &common->utfpeakcharback_invalid, JUMP(SLJIT_FAST_CALL));+ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ }+ else+ add_jump(compiler, &common->utfpeakcharback, JUMP(SLJIT_FAST_CALL));+ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf)+ {+ if (max < 0xd800) return;++ if (common->invalid_utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);+ add_jump(compiler, &common->utfpeakcharback_invalid, JUMP(SLJIT_FAST_CALL));+ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ }+ else+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xdc00);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xdc00);+ /* TMP2 contains the low surrogate. */+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x10000);+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+ }+ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */+}++#define READ_CHAR_UPDATE_STR_PTR 0x1+#define READ_CHAR_UTF8_NEWLINE 0x2+#define READ_CHAR_NEWLINE (READ_CHAR_UPDATE_STR_PTR | READ_CHAR_UTF8_NEWLINE)+#define READ_CHAR_VALID_UTF 0x4++static void read_char(compiler_common *common, sljit_u32 min, sljit_u32 max,+ jump_list **backtracks, sljit_u32 options)+{+/* 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+outside the range. Does not check STR_END. */+DEFINE_COMPILER;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_jump *jump;+#endif+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+struct sljit_jump *jump2;+#endif++SLJIT_UNUSED_ARG(min);+SLJIT_UNUSED_ARG(max);+SLJIT_UNUSED_ARG(backtracks);+SLJIT_UNUSED_ARG(options);+SLJIT_ASSERT(min <= max);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+ if (max < 128 && !(options & READ_CHAR_UPDATE_STR_PTR)) return;++ if (common->invalid_utf && !(options & READ_CHAR_VALID_UTF))+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);++ if (options & READ_CHAR_UTF8_NEWLINE)+ add_jump(compiler, &common->utfreadnewline_invalid, JUMP(SLJIT_FAST_CALL));+ else+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));++ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ JUMPHERE(jump);+ return;+ }++ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);+ if (min >= 0x10000)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ 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);+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ 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);+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));+ if (!(options & READ_CHAR_UPDATE_STR_PTR))+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));+ 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);+ JUMPHERE(jump2);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);+ }+ else if (min >= 0x800 && max <= 0xffff)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ 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);+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ if (!(options & READ_CHAR_UPDATE_STR_PTR))+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+ 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);+ JUMPHERE(jump2);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);+ }+ else if (max >= 0x800)+ {+ add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));+ }+ else if (max < 128)+ {+ 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+ {+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ if (!(options & READ_CHAR_UPDATE_STR_PTR))+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ else+ 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);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);+ }+ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf)+ {+ if (max < 0xd800 && !(options & READ_CHAR_UPDATE_STR_PTR)) return;++ if (common->invalid_utf && !(options & READ_CHAR_VALID_UTF))+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);++ if (options & READ_CHAR_UTF8_NEWLINE)+ add_jump(compiler, &common->utfreadnewline_invalid, JUMP(SLJIT_FAST_CALL));+ else+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));++ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ JUMPHERE(jump);+ return;+ }++ if (max >= 0x10000)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800);+ /* TMP2 contains the high surrogate. */+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+ JUMPHERE(jump);+ return;+ }++ /* Skip low surrogate if necessary. */+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)+ {+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0x400);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ SELECT(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0, STR_PTR);+ if (max >= 0xd800)+ SELECT(SLJIT_LESS, TMP1, SLJIT_IMM, 0x10000, TMP1);+ }+ else+ {+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ if (max >= 0xd800)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);+ JUMPHERE(jump);+ }+ }+#elif PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf)+ {+ if (backtracks != NULL)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));+ }+ else+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000);+ SELECT(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR, TMP1);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);+ SELECT(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR, TMP1);+ }+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */+}++static void skip_valid_char(compiler_common *common)+{+DEFINE_COMPILER;+#if (defined SUPPORT_UNICODE) && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)+struct sljit_jump *jump;+#endif++#if (defined SUPPORT_UNICODE) && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)+ if (common->utf)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+#if PCRE2_CODE_UNIT_WIDTH == 8+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 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 PCRE2_CODE_UNIT_WIDTH == 16+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, 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 /* PCRE2_CODE_UNIT_WIDTH == 8 */+ JUMPHERE(jump);+ return;+ }+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+}++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8++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 sljit_u8 value = nclass ? 0xff : 0;+const sljit_u8 *end = bitset + 32;++bitset += 16;+do+ {+ if (*bitset++ != value)+ return FALSE;+ }+while (bitset < end);+return TRUE;+}++static void read_char7_type(compiler_common *common, jump_list **backtracks, BOOL negated)+{+/* Reads the precise character type of a character into TMP1, if the character+is less than 128. Otherwise it returns with zero. Does not check STR_END. The+full_read argument tells whether characters above max are accepted or not. */+DEFINE_COMPILER;+struct sljit_jump *jump;++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));++/* All values > 127 are zero in ctypes. */+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);++if (negated)+ {+ jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x80);++ if (common->invalid_utf)+ {+ OP1(SLJIT_MOV, TMP1, 0, TMP2, 0);+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+ }+ else+ {+ 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);+ }+}++#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */++static void read_char8_type(compiler_common *common, jump_list **backtracks, BOOL negated)+{+/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */+DEFINE_COMPILER;+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+struct sljit_jump *jump;+#endif+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+struct sljit_jump *jump2;+#endif++SLJIT_UNUSED_ARG(backtracks);+SLJIT_UNUSED_ARG(negated);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+ /* The result of this read may be unused, but saves an "else" part. */+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+ jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x80);++ if (!negated)+ {+ if (common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);+ if (common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe0 - 0xc2));++ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);+ if (common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40));++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+ jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+ JUMPHERE(jump2);+ }+ else if (common->invalid_utf)+ {+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+ jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+ JUMPHERE(jump2);+ }+ else+ add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));++ JUMPHERE(jump);+ return;+ }+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf && negated)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x110000));+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32 */++#if PCRE2_CODE_UNIT_WIDTH != 8+/* The ctypes array contains only 256 values. */+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+#if PCRE2_CODE_UNIT_WIDTH != 8+JUMPHERE(jump);+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf && negated)+ {+ /* Skip low surrogate if necessary. */+ if (!common->invalid_utf)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)+ {+ OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0x400);+ SELECT(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0, STR_PTR);+ }+ else+ {+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPHERE(jump);+ }+ return;+ }++ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400));+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xdc00);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400));++ JUMPHERE(jump);+ return;+ }+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16 */+}++static void move_back(compiler_common *common, jump_list **backtracks, BOOL must_be_valid)+{+/* Goes one character back. Affects STR_PTR and TMP1. If must_be_valid is TRUE,+TMP2 is not used. Otherwise TMP2 must contain the start of the subject buffer,+and it is destroyed. Does not modify STR_PTR for invalid character sequences. */+DEFINE_COMPILER;++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_jump *jump;+#endif++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+struct sljit_label *label;++if (common->utf)+ {+ if (!must_be_valid && common->invalid_utf)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);+ add_jump(compiler, &common->utfmoveback_invalid, JUMP(SLJIT_FAST_CALL));+ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));+ JUMPHERE(jump);+ return;+ }++ label = LABEL();+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);+ CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);+ return;+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ if (!must_be_valid && common->invalid_utf)+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000 - 0xd800);+ add_jump(compiler, &common->utfmoveback_invalid, JUMP(SLJIT_FAST_CALL));+ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));+ JUMPHERE(jump);+ return;+ }++ /* Skip low surrogate if necessary. */+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0xdc00);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ return;+ }+#elif PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf && !must_be_valid)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));+ if (backtracks != NULL)+ {+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ return;+ }++ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x110000);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ return;+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */++SLJIT_UNUSED_ARG(backtracks);+SLJIT_UNUSED_ARG(must_be_valid);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+}++static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpifmatch)+{+/* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */+DEFINE_COMPILER;+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)+ {+ if (jumpifmatch)+ {+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR));+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));+ }+ else+ {+ jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));+ JUMPHERE(jump);+ }+ }+else+ {+ SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);+ add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));+ }+}++#ifdef SUPPORT_UNICODE++#if PCRE2_CODE_UNIT_WIDTH == 8+static void do_utfreadchar(compiler_common *common)+{+/* Fast decoding a UTF-8 character. TMP1 contains the first byte+of the character (>= 0xc0). Return char value in TMP1. */+DEFINE_COMPILER;+struct sljit_jump *jump;++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+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);++/* Searching for the first zero. */+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x800);+jump = JUMP(SLJIT_NOT_ZERO);+/* Two byte sequence. */+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3000);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+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);++OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x10000);+jump = JUMP(SLJIT_NOT_ZERO);+/* Three byte sequence. */+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0000);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Four byte sequence. */+JUMPHERE(jump);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xf0000);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));+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);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfreadtype8(compiler_common *common)+{+/* Fast decoding a UTF-8 character type. TMP2 contains the first byte+of the character (>= 0xc0). Return value in TMP1. */+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_jump *compare;++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++OP2U(SLJIT_AND | SLJIT_SET_Z, 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));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);+/* The upper 5 bits are known at this point. */+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_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(compare);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* We only have types for characters less than 256. */+JUMPHERE(jump);+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);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfreadchar_invalid(compiler_common *common)+{+/* Slow decoding a UTF-8 character. TMP1 contains the first byte+of the character (>= 0xc0). Return char value in TMP1. STR_PTR is+undefined for invalid characters. */+DEFINE_COMPILER;+sljit_s32 i;+sljit_s32 has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV);+struct sljit_jump *jump;+struct sljit_jump *buffer_end_close;+struct sljit_label *three_byte_entry;+struct sljit_label *exit_invalid_label;+struct sljit_jump *exit_invalid[11];++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc2);++/* Usually more than 3 characters remained in the subject buffer. */+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));++/* Not a valid start of a multi-byte sequence, no more bytes read. */+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xf5 - 0xc2);++buffer_end_close = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+/* If TMP2 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x800);+jump = JUMP(SLJIT_NOT_ZERO);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump);++/* Three-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+if (has_cmov)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);+ SELECT(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0x20000, TMP1);+ exit_invalid[2] = NULL;+ }+else+ exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x10000);+jump = JUMP(SLJIT_NOT_ZERO);++three_byte_entry = LABEL();++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2d800);+if (has_cmov)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);+ SELECT(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0xd800, TMP1);+ exit_invalid[3] = NULL;+ }+else+ exit_invalid[3] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (has_cmov)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);+ SELECT(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR, TMP1);+ exit_invalid[4] = NULL;+ }+else+ exit_invalid[4] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump);++/* Four-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+if (has_cmov)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);+ SELECT(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0, TMP1);+ exit_invalid[5] = NULL;+ }+else+ exit_invalid[5] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc10000);+if (has_cmov)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);+ SELECT(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000, TMP1);+ exit_invalid[6] = NULL;+ }+else+ exit_invalid[6] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(buffer_end_close);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+exit_invalid[7] = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);++/* Two-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+/* If TMP2 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+exit_invalid[8] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x800);+jump = JUMP(SLJIT_NOT_ZERO);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Three-byte sequence. */+JUMPHERE(jump);+exit_invalid[9] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+if (has_cmov)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);+ SELECT(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR, TMP1);+ exit_invalid[10] = NULL;+ }+else+ exit_invalid[10] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++/* One will be substracted from STR_PTR later. */+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));++/* Four byte sequences are not possible. */+CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x30000, three_byte_entry);++exit_invalid_label = LABEL();+for (i = 0; i < 11; i++)+ sljit_set_label(exit_invalid[i], exit_invalid_label);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfreadnewline_invalid(compiler_common *common)+{+/* Slow decoding a UTF-8 character, specialized for newlines.+TMP1 contains the first byte of the character (>= 0xc0). Return+char value in TMP1. */+DEFINE_COMPILER;+struct sljit_label *loop;+struct sljit_label *skip_start;+struct sljit_label *three_byte_exit;+struct sljit_jump *jump[5];++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++if (common->nltype != NLTYPE_ANY)+ {+ SLJIT_ASSERT(common->nltype != NLTYPE_FIXED || common->newline < 128);++ /* All newlines are ascii, just skip intermediate octets. */+ jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ loop = LABEL();+ if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)) == SLJIT_SUCCESS)+ sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ else+ {+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ }++ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);+ CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ JUMPHERE(jump[0]);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+ OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+ return;+ }++jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++jump[1] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xc2);+jump[2] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xe2);++skip_start = LABEL();+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);+jump[3] = CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80);++/* Skip intermediate octets. */+loop = LABEL();+jump[4] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);+CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop);++JUMPHERE(jump[3]);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++three_byte_exit = LABEL();+JUMPHERE(jump[0]);+JUMPHERE(jump[4]);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Two byte long newline: 0x85. */+JUMPHERE(jump[1]);+CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x85, skip_start);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x85);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Three byte long newlines: 0x2028 and 0x2029. */+JUMPHERE(jump[2]);+CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, skip_start);+CMPTO(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0, three_byte_exit);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++OP2(SLJIT_SUB, TMP1, 0, TMP2, 0, SLJIT_IMM, 0x80);+CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x40, skip_start);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0x2000);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfmoveback_invalid(compiler_common *common)+{+/* Goes one character back. */+DEFINE_COMPILER;+sljit_s32 i;+struct sljit_jump *jump;+struct sljit_jump *buffer_start_close;+struct sljit_label *exit_ok_label;+struct sljit_label *exit_invalid_label;+struct sljit_jump *exit_invalid[7];++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xc0);++/* Two-byte sequence. */+buffer_start_close = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);+jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x20);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Three-byte sequence. */+JUMPHERE(jump);+exit_invalid[1] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, -0x40);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);+jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x10);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Four-byte sequence. */+JUMPHERE(jump);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0 - 0x80);+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x40);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xf0);+exit_invalid[3] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x05);++exit_ok_label = LABEL();+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Two-byte sequence. */+JUMPHERE(buffer_start_close);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));++exit_invalid[4] = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);+CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x20, exit_ok_label);++/* Three-byte sequence. */+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+exit_invalid[5] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, -0x40);+exit_invalid[6] = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);+CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10, exit_ok_label);++/* Four-byte sequences are not possible. */++exit_invalid_label = LABEL();+sljit_set_label(exit_invalid[5], exit_invalid_label);+sljit_set_label(exit_invalid[6], exit_invalid_label);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[4]);+/* -2 + 4 = 2 */+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));++exit_invalid_label = LABEL();+for (i = 0; i < 4; i++)+ sljit_set_label(exit_invalid[i], exit_invalid_label);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(4));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfpeakcharback(compiler_common *common)+{+/* Peak a character back. Does not modify STR_PTR. */+DEFINE_COMPILER;+struct sljit_jump *jump[2];++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);+jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x20);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);+jump[1] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-4));+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0 - 0x80);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf0);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++JUMPHERE(jump[1]);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++JUMPHERE(jump[0]);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfpeakcharback_invalid(compiler_common *common)+{+/* Peak a character back. Does not modify STR_PTR. */+DEFINE_COMPILER;+sljit_s32 i;+sljit_s32 has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV);+struct sljit_jump *jump[2];+struct sljit_label *two_byte_entry;+struct sljit_label *three_byte_entry;+struct sljit_label *exit_invalid_label;+struct sljit_jump *exit_invalid[8];++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xc0);+jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);++/* Two-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);+jump[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x1e);++two_byte_entry = LABEL();+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+/* If TMP1 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump[1]);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2 - 0x80);+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++/* Three-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0);+jump[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x10);++three_byte_entry = LABEL();+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+if (has_cmov)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);+ SELECT(SLJIT_LESS, TMP1, SLJIT_IMM, -0xd800, TMP1);+ exit_invalid[2] = NULL;+ }+else+ exit_invalid[2] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+if (has_cmov)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);+ SELECT(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR, TMP1);+ exit_invalid[3] = NULL;+ }+else+ exit_invalid[3] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump[1]);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0 - 0x80);+exit_invalid[4] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++/* Four-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-4));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf0);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 18);+/* ADD is used instead of OR because of the SUB 0x10000 above. */+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);++if (has_cmov)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);+ SELECT(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000, TMP1);+ exit_invalid[5] = NULL;+ }+else+ exit_invalid[5] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump[0]);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);++/* Two-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);+CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x1e, two_byte_entry);++OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2 - 0x80);+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);+exit_invalid[6] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++/* Three-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0);+CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x10, three_byte_entry);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump[0]);+exit_invalid[7] = CMP(SLJIT_GREATER, TMP2, 0, STR_PTR, 0);++/* Two-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);+CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x1e, two_byte_entry);++exit_invalid_label = LABEL();+for (i = 0; i < 8; i++)+ sljit_set_label(exit_invalid[i], exit_invalid_label);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */++#if PCRE2_CODE_UNIT_WIDTH == 16++static void do_utfreadchar_invalid(compiler_common *common)+{+/* Slow decoding a UTF-16 character. TMP1 contains the first half+of the character (>= 0xd800). Return char value in TMP1. STR_PTR is+undefined for invalid characters. */+DEFINE_COMPILER;+struct sljit_jump *exit_invalid[3];++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++/* TMP2 contains the high surrogate. */+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xdc00);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x10000);+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[0]);+JUMPHERE(exit_invalid[1]);+JUMPHERE(exit_invalid[2]);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfreadnewline_invalid(compiler_common *common)+{+/* Slow decoding a UTF-16 character, specialized for newlines.+TMP1 contains the first half of the character (>= 0xd800). Return+char value in TMP1. */++DEFINE_COMPILER;+struct sljit_jump *exit_invalid[2];++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++/* TMP2 contains the high surrogate. */+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00);++OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xdc00);+OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0x400);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[0]);+JUMPHERE(exit_invalid[1]);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfmoveback_invalid(compiler_common *common)+{+/* Goes one character back. */+DEFINE_COMPILER;+struct sljit_jump *exit_invalid[3];++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++exit_invalid[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x400);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[0]);+JUMPHERE(exit_invalid[1]);+JUMPHERE(exit_invalid[2]);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfpeakcharback_invalid(compiler_common *common)+{+/* Peak a character back. Does not modify STR_PTR. */+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_jump *exit_invalid[3];++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+exit_invalid[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);++JUMPHERE(jump);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[0]);+JUMPHERE(exit_invalid[1]);+JUMPHERE(exit_invalid[2]);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */++/* UCD_BLOCK_SIZE must be 128 (see the assert below). */+#define UCD_BLOCK_MASK 127+#define UCD_BLOCK_SHIFT 7++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;+#if PCRE2_CODE_UNIT_WIDTH == 32+struct sljit_jump *jump;+#endif++#if defined SLJIT_DEBUG && SLJIT_DEBUG+/* dummy_ucd_record */+const ucd_record *record = GET_UCD(UNASSIGNED_UTF_CHAR);+SLJIT_ASSERT(record->script == ucp_Unknown && 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) == 12);++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++#if PCRE2_CODE_UNIT_WIDTH == 32+if (!common->utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);+ JUMPHERE(jump);+ }+#endif++OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);+OP1(SLJIT_MOV_U16, 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);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_getucdtype(compiler_common *common)+{+/* Search the UCD record for the character comes in TMP1.+Returns chartype in TMP1 and UCD offset in TMP2. */+DEFINE_COMPILER;+#if PCRE2_CODE_UNIT_WIDTH == 32+struct sljit_jump *jump;+#endif++#if defined SLJIT_DEBUG && SLJIT_DEBUG+/* dummy_ucd_record */+const ucd_record *record = GET_UCD(UNASSIGNED_UTF_CHAR);+SLJIT_ASSERT(record->script == ucp_Unknown && 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) == 12);++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++#if PCRE2_CODE_UNIT_WIDTH == 32+if (!common->utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);+ JUMPHERE(jump);+ }+#endif++OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);+OP1(SLJIT_MOV_U16, 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);++/* TMP2 is multiplied by 12. Same as (TMP2 << 2) + ((TMP2 << 2) << 1). */+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 1);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++#endif /* SUPPORT_UNICODE */++static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_label *mainloop;+struct sljit_label *newlinelabel = NULL;+struct sljit_jump *start;+struct sljit_jump *end = NULL;+struct sljit_jump *end2 = NULL;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *loop;+struct sljit_jump *jump;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */+jump_list *newline = NULL;+sljit_u32 overall_options = common->re->overall_options;+BOOL hascrorlf = (common->re->flags & PCRE2_HASCRORLF) != 0;+BOOL newlinecheck = FALSE;+BOOL readuchar = FALSE;++if (!(hascrorlf || (overall_options & PCRE2_FIRSTLINE) != 0)+ && (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255))+ newlinecheck = TRUE;++SLJIT_ASSERT(common->abort_label == NULL);++if ((overall_options & PCRE2_FIRSTLINE) != 0)+ {+ /* Search for the end of the first line. */+ SLJIT_ASSERT(common->match_end_ptr != 0);+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);++ if (common->nltype == NLTYPE_FIXED && common->newline > 255)+ {+ mainloop = LABEL();+ 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), IN_UCHARS(-1));+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ 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->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->match_end_ptr, STR_PTR, 0);+ read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE);+ 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->match_end_ptr, STR_PTR, 0);+ set_jumps(newline, LABEL());+ }++ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ }+else if ((overall_options & PCRE2_USE_OFFSET_LIMIT) != 0)+ {+ /* Check whether offset limit is set and valid. */+ SLJIT_ASSERT(common->match_end_ptr != 0);++ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, offset_limit));+ }+ else+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, offset_limit));++ OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);+ end = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw) PCRE2_UNSET);+ if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);+ else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));++#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif /* PCRE2_CODE_UNIT_WIDTH == [16|32] */+ if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));++ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);+ end2 = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);+ OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);+ JUMPHERE(end2);+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+ add_jump(compiler, &common->abort, CMP(SLJIT_LESS, TMP2, 0, STR_PTR, 0));+ JUMPHERE(end);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, TMP2, 0);+ }++start = JUMP(SLJIT_JUMP);++if (newlinecheck)+ {+ newlinelabel = LABEL();+ 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);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, common->newline & 0xff);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif /* PCRE2_CODE_UNIT_WIDTH == [16|32] */+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ end2 = JUMP(SLJIT_JUMP);+ }++mainloop = LABEL();++/* Increasing the STR_PTR here requires one less jump in the most common case. */+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && !common->invalid_utf) readuchar = TRUE;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */+if (newlinecheck) readuchar = TRUE;++if (readuchar)+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);++if (newlinecheck)+ CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->invalid_utf)+ {+ /* Skip continuation code units. */+ loop = LABEL();+ jump = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ 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, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);+ CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x40, loop);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPHERE(jump);+ }+else if (common->utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 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(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->invalid_utf)+ {+ /* Skip continuation code units. */+ loop = LABEL();+ jump = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ 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, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xdc00);+ CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x400, loop);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPHERE(jump);+ }+else if (common->utf)+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))+ {+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x400);+ SELECT(SLJIT_LESS, STR_PTR, TMP2, 0, STR_PTR);+ }+ else+ {+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x400);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ }+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */+JUMPHERE(start);++if (newlinecheck)+ {+ JUMPHERE(end);+ JUMPHERE(end2);+ }++return mainloop;+}+++static SLJIT_INLINE void add_prefix_char(PCRE2_UCHAR chr, fast_forward_char_data *chars, BOOL last)+{+sljit_u32 i, count = chars->count;++if (count == 255)+ return;++if (count == 0)+ {+ chars->count = 1;+ chars->chars[0] = chr;++ if (last)+ chars->last_count = 1;+ return;+ }++for (i = 0; i < count; i++)+ if (chars->chars[i] == chr)+ return;++if (count >= MAX_DIFF_CHARS)+ {+ chars->count = 255;+ return;+ }++chars->chars[count] = chr;+chars->count = count + 1;++if (last)+ chars->last_count++;+}++static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, fast_forward_char_data *chars, int max_chars, sljit_u32 *rec_count)+{+/* Recursive function, which scans prefix literals. */+BOOL last, any, class, caseless;+int len, repeat, len_save, consumed = 0;+sljit_u32 chr; /* Any unicode character. */+sljit_u8 *bytes, *bytes_end, byte;+PCRE2_SPTR alternative, cc_save, oc;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+PCRE2_UCHAR othercase[4];+#elif defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16+PCRE2_UCHAR othercase[2];+#else+PCRE2_UCHAR othercase[1];+#endif++repeat = 1;+while (TRUE)+ {+ if (*rec_count == 0)+ return 0;+ (*rec_count)--;++ last = TRUE;+ any = FALSE;+ class = FALSE;+ caseless = FALSE;++ switch (*cc)+ {+ case OP_CHARI:+ caseless = TRUE;+ /* Fall through */+ case OP_CHAR:+ last = FALSE;+ cc++;+ break;++ 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:+ case OP_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:+ /* Zero width assertions. */+ cc++;+ continue;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ cc = bracketend(cc);+ continue;++ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSPLUSI:+ caseless = TRUE;+ /* Fall through */+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSPLUS:+ cc++;+ break;++ case OP_EXACTI:+ caseless = TRUE;+ /* Fall through */+ case OP_EXACT:+ repeat = GET2(cc, 1);+ last = FALSE;+ cc += 1 + IMM2_SIZE;+ break;++ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_POSQUERYI:+ caseless = TRUE;+ /* Fall through */+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_POSQUERY:+ len = 1;+ cc++;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);+#endif+ max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count);+ if (max_chars == 0)+ return consumed;+ last = FALSE;+ break;++ case OP_KET:+ cc += 1 + LINK_SIZE;+ continue;++ case OP_ALT:+ cc += GET(cc, 1);+ continue;++ case OP_ONCE:+ case OP_BRA:+ case OP_BRAPOS:+ case OP_CBRA:+ case OP_CBRAPOS:+ alternative = cc + GET(cc, 1);+ while (*alternative == OP_ALT)+ {+ max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, max_chars, rec_count);+ if (max_chars == 0)+ return consumed;+ alternative += GET(alternative, 1);+ }++ if (*cc == OP_CBRA || *cc == OP_CBRAPOS)+ cc += IMM2_SIZE;+ cc += 1 + LINK_SIZE;+ continue;++ case OP_CLASS:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE))+ return consumed;+#endif+ class = TRUE;+ break;++ case OP_NCLASS:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ class = TRUE;+ break;++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ any = TRUE;+ cc += GET(cc, 1);+ break;+#endif++ case OP_DIGIT:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE))+ return consumed;+#endif+ any = TRUE;+ cc++;+ break;++ case OP_WHITESPACE:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE))+ return consumed;+#endif+ any = TRUE;+ cc++;+ break;++ case OP_WORDCHAR:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE))+ return consumed;+#endif+ any = TRUE;+ cc++;+ break;++ case OP_NOT:+ case OP_NOTI:+ cc++;+ /* Fall through. */+ case OP_NOT_DIGIT:+ case OP_NOT_WHITESPACE:+ case OP_NOT_WORDCHAR:+ case OP_ANY:+ case OP_ALLANY:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ any = TRUE;+ cc++;+ break;++#ifdef SUPPORT_UNICODE+ case OP_NOTPROP:+ case OP_PROP:+#if PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ any = TRUE;+ cc += 1 + 2;+ break;+#endif++ case OP_TYPEEXACT:+ repeat = GET2(cc, 1);+ cc += 1 + IMM2_SIZE;+ continue;++ case OP_NOTEXACT:+ case OP_NOTEXACTI:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ any = TRUE;+ repeat = GET2(cc, 1);+ cc += 1 + IMM2_SIZE + 1;+ break;++ default:+ return consumed;+ }++ if (any)+ {+ do+ {+ chars->count = 255;++ consumed++;+ if (--max_chars == 0)+ return consumed;+ chars++;+ }+ while (--repeat > 0);++ repeat = 1;+ continue;+ }++ if (class)+ {+ bytes = (sljit_u8*) (cc + 1);+ cc += 1 + 32 / sizeof(PCRE2_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+ {+ if (bytes[31] & 0x80)+ chars->count = 255;+ else if (chars->count != 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, TRUE);+ byte >>= 1;+ chr++;+ }+ while (byte != 0);+ chr = (chr + 7) & (sljit_u32)(~7);+ }+ }+ while (chars->count != 255 && bytes < bytes_end);+ bytes = bytes_end - 32;+ }++ consumed++;+ if (--max_chars == 0)+ return consumed;+ 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;+ }++ len = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);+#endif++ if (caseless && char_has_othercase(common, cc))+ {+#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+ GETCHAR(chr, cc);+ if ((int)PRIV(ord2utf)(char_othercase(common, chr), othercase) != len)+ return consumed;+ }+ else+#endif+ {+ chr = *cc;+#ifdef SUPPORT_UNICODE+ if (common->ucp && chr > 127)+ {+ chr = UCD_OTHERCASE(chr);+ othercase[0] = (chr == (PCRE2_UCHAR)chr) ? chr : *cc;+ }+ else+#endif+ othercase[0] = TABLE_GET(chr, common->fcc, chr);+ }+ }+ else+ {+ caseless = FALSE;+ othercase[0] = 0; /* Stops compiler warning - PH */+ }++ len_save = len;+ cc_save = cc;+ while (TRUE)+ {+ oc = othercase;+ do+ {+ len--;+ consumed++;++ chr = *cc;+ add_prefix_char(*cc, chars, len == 0);++ if (caseless)+ add_prefix_char(*oc, chars, len == 0);++ if (--max_chars == 0)+ return consumed;+ chars++;+ cc++;+ oc++;+ }+ while (len > 0);++ if (--repeat == 0)+ break;++ len = len_save;+ cc = cc_save;+ }++ repeat = 1;+ if (last)+ return consumed;+ }+}++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+static void jumpto_if_not_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg, struct sljit_label *label)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);+CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0x80, label);+#elif PCRE2_CODE_UNIT_WIDTH == 16+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);+CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00, label);+#else+#error "Unknown code width"+#endif+}+#endif++#include "pcre2_jit_simd_inc.h"++#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD++static BOOL check_fast_forward_char_pair_simd(compiler_common *common, fast_forward_char_data *chars, int max)+{+ sljit_s32 i, j, max_i = 0, max_j = 0;+ sljit_u32 max_pri = 0;+ sljit_s32 max_offset = max_fast_forward_char_pair_offset();+ PCRE2_UCHAR a1, a2, a_pri, b1, b2, b_pri;++ for (i = max - 1; i >= 1; i--)+ {+ if (chars[i].last_count > 2)+ {+ a1 = chars[i].chars[0];+ a2 = chars[i].chars[1];+ a_pri = chars[i].last_count;++ j = i - max_offset;+ if (j < 0)+ j = 0;++ while (j < i)+ {+ b_pri = chars[j].last_count;+ if (b_pri > 2 && (sljit_u32)a_pri + (sljit_u32)b_pri >= max_pri)+ {+ b1 = chars[j].chars[0];+ b2 = chars[j].chars[1];++ if (a1 != b1 && a1 != b2 && a2 != b1 && a2 != b2)+ {+ max_pri = a_pri + b_pri;+ max_i = i;+ max_j = j;+ }+ }+ j++;+ }+ }+ }++if (max_pri == 0)+ return FALSE;++fast_forward_char_pair_simd(common, max_i, chars[max_i].chars[0], chars[max_i].chars[1], max_j, chars[max_j].chars[0], chars[max_j].chars[1]);+return TRUE;+}++#endif /* JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD */++static void fast_forward_first_char2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)+{+DEFINE_COMPILER;+struct sljit_label *start;+struct sljit_jump *match;+struct sljit_jump *partial_quit;+PCRE2_UCHAR mask;+BOOL has_match_end = (common->match_end_ptr != 0);++SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE || offset == 0);++if (has_match_end)+ OP1(SLJIT_MOV, TMP1, 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));++if (has_match_end)+ {+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);++ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offset + 1));+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_END, 0, TMP1, 0);+ SELECT(SLJIT_GREATER, STR_END, TMP1, 0, STR_END);+ }++#ifdef JIT_HAS_FAST_FORWARD_CHAR_SIMD++if (JIT_HAS_FAST_FORWARD_CHAR_SIMD)+ {+ fast_forward_char_simd(common, char1, char2, offset);++ if (offset > 0)+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));++ if (has_match_end)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+ return;+ }++#endif++start = LABEL();++partial_quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (char1 == char2)+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char1, start);+else+ {+ mask = char1 ^ char2;+ if (is_powerof2(mask))+ {+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask, start);+ }+ else+ {+ match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char2, start);+ JUMPHERE(match);+ }+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && offset > 0)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-(offset + 1)));+ jumpto_if_not_utf_char_start(compiler, TMP1, start);+ }+#endif++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset + 1));++if (common->mode != PCRE2_JIT_COMPLETE)+ JUMPHERE(partial_quit);++if (has_match_end)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+}++static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_label *start;+struct sljit_jump *match;+fast_forward_char_data chars[MAX_N_CHARS];+sljit_s32 offset;+PCRE2_UCHAR mask;+PCRE2_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].count = 0;+ chars[i].last_count = 0;+ }++rec_count = 10000;+max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count);++if (max < 1)+ return FALSE;++/* Convert last_count to priority. */+for (i = 0; i < max; i++)+ {+ SLJIT_ASSERT(chars[i].last_count <= chars[i].count);++ switch (chars[i].count)+ {+ case 0:+ chars[i].count = 255;+ chars[i].last_count = 0;+ break;++ case 1:+ chars[i].last_count = (chars[i].last_count == 1) ? 7 : 5;+ /* Simplifies algorithms later. */+ chars[i].chars[1] = chars[i].chars[0];+ break;++ case 2:+ SLJIT_ASSERT(chars[i].chars[0] != chars[i].chars[1]);++ if (is_powerof2(chars[i].chars[0] ^ chars[i].chars[1]))+ chars[i].last_count = (chars[i].last_count == 2) ? 6 : 4;+ else+ chars[i].last_count = (chars[i].last_count == 2) ? 3 : 2;+ break;++ default:+ chars[i].last_count = (chars[i].count == 255) ? 0 : 1;+ break;+ }+ }++#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD+if (JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD && check_fast_forward_char_pair_simd(common, chars, max))+ return TRUE;+#endif++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].count < 255))+ {+ range_len = i - from;+ range_right = i - 1;+ }++ if (i < max && chars[i].count < 255)+ {+ SLJIT_ASSERT(chars[i].count > 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++)+ {+ SLJIT_ASSERT(chars[range_right - i].count > 0 && chars[range_right - i].count < 255);++ char_set = chars[range_right - i].chars;+ char_set_end = char_set + chars[range_right - i].count;+ do+ {+ if (update_table[(*char_set) & 0xff] > IN_UCHARS(i))+ update_table[(*char_set) & 0xff] = IN_UCHARS(i);+ char_set++;+ }+ while (char_set < char_set_end);+ }+ }++offset = -1;+/* Scan forward. */+for (i = 0; i < max; i++)+ {+ if (range_right == i)+ continue;++ if (offset == -1)+ {+ if (chars[i].last_count >= 2)+ offset = i;+ }+ else if (chars[offset].last_count < chars[i].last_count)+ offset = i;+ }++SLJIT_ASSERT(offset == -1 || (chars[offset].count >= 1 && chars[offset].count <= 2));++if (range_right < 0)+ {+ if (offset < 0)+ return FALSE;+ /* Works regardless the value is 1 or 2. */+ fast_forward_first_char2(common, chars[offset].chars[0], chars[offset].chars[1], offset);+ return TRUE;+ }++SLJIT_ASSERT(range_right != offset);++if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);+ OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_END, 0, TMP1, 0);+ SELECT(SLJIT_GREATER, STR_END, TMP1, 0, STR_END);+ }+else+ {+ OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));+ }++SLJIT_ASSERT(range_right >= 0);++if (!HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);++start = LABEL();+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));++#if PCRE2_CODE_UNIT_WIDTH == 8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));+#else+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);+#endif++if (!HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);+else+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);++if (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 (chars[offset].count == 1)+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0], start);+ else+ {+ mask = chars[offset].chars[0] ^ chars[offset].chars[1];+ if (is_powerof2(mask))+ {+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0] | mask, start);+ }+ else+ {+ match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0]);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[1], start);+ JUMPHERE(match);+ }+ }+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && offset != 0)+ {+ if (offset < 0)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ }+ else+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));++ jumpto_if_not_utf_char_start(compiler, TMP1, start);++ 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));++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+else+ OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));+return TRUE;+}++static SLJIT_INLINE void fast_forward_first_char(compiler_common *common)+{+PCRE2_UCHAR first_char = (PCRE2_UCHAR)(common->re->first_codeunit);+PCRE2_UCHAR oc;++oc = first_char;+if ((common->re->flags & PCRE2_FIRSTCASELESS) != 0)+ {+ oc = TABLE_GET(first_char, common->fcc, first_char);+#if defined SUPPORT_UNICODE+ if (first_char > 127 && (common->utf || common->ucp))+ oc = UCD_OTHERCASE(first_char);+#endif+ }++fast_forward_first_char2(common, first_char, oc, 0);+}++static SLJIT_INLINE void fast_forward_newline(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_label *loop;+struct sljit_jump *lastchar = NULL;+struct sljit_jump *firstchar;+struct sljit_jump *quit = NULL;+struct sljit_jump *foundcr = NULL;+struct sljit_jump *notfoundnl;+jump_list *newline = NULL;++if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ }++if (common->nltype == NLTYPE_FIXED && common->newline > 255)+ {+#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD+ if (JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD && common->mode == PCRE2_JIT_COMPLETE)+ {+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);++ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2U(SLJIT_SUB | SLJIT_SET_Z, STR_PTR, 0, TMP1, 0);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_NOT_EQUAL);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);++ fast_forward_char_pair_simd(common, 1, common->newline & 0xff, common->newline & 0xff, 0, (common->newline >> 8) & 0xff, (common->newline >> 8) & 0xff);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+ }+ else+#endif /* JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD */+ {+ lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);++ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, STR_PTR, 0, TMP1, 0);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++ loop = LABEL();+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 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));+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);+ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);++ JUMPHERE(quit);+ JUMPHERE(lastchar);+ }++ JUMPHERE(firstchar);++ if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+ return;+ }++if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+ }+else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));++/* Example: match /^/ to \r\n from offset 1. */+firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);++if (common->nltype == NLTYPE_ANY)+ move_back(common, NULL, FALSE);+else+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++loop = LABEL();+common->ff_newline_shortcut = loop;++#ifdef JIT_HAS_FAST_FORWARD_CHAR_SIMD+if (JIT_HAS_FAST_FORWARD_CHAR_SIMD && (common->nltype == NLTYPE_FIXED || common->nltype == NLTYPE_ANYCRLF))+ {+ if (common->nltype == NLTYPE_ANYCRLF)+ {+ fast_forward_char_simd(common, CHAR_CR, CHAR_LF, 0);+ if (common->mode != PCRE2_JIT_COMPLETE)+ lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ quit = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);+ }+ else+ {+ fast_forward_char_simd(common, common->newline, common->newline, 0);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ if (common->mode != PCRE2_JIT_COMPLETE)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);+ SELECT(SLJIT_GREATER, STR_PTR, STR_END, 0, STR_PTR);+ }+ }+ }+else+#endif /* JIT_HAS_FAST_FORWARD_CHAR_SIMD */+ {+ read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE);+ lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)+ foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);+ check_newlinechar(common, common->nltype, &newline, FALSE);+ set_jumps(newline, loop);+ }++if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)+ {+ if (quit == NULL)+ {+ quit = JUMP(SLJIT_JUMP);+ JUMPHERE(foundcr);+ }++ notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NL);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ JUMPHERE(notfoundnl);+ JUMPHERE(quit);+ }++if (lastchar)+ JUMPHERE(lastchar);+JUMPHERE(firstchar);++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+}++static BOOL optimize_class(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)+{+DEFINE_COMPILER;+const sljit_u8 *start_bits = common->re->start_bitmap;+struct sljit_label *start;+struct sljit_jump *partial_quit;+#if PCRE2_CODE_UNIT_WIDTH != 8+struct sljit_jump *found = NULL;+#endif+jump_list *matches = NULL;++if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_END, 0, TMP1, 0);+ SELECT(SLJIT_GREATER, STR_END, TMP1, 0, STR_END);+ }++start = LABEL();++partial_quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (!optimize_class(common, start_bits, (start_bits[31] & 0x80) != 0, FALSE, &matches))+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ if ((start_bits[31] & 0x80) != 0)+ found = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 255);+ else+ CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 255, start);+#elif defined SUPPORT_UNICODE+ if (common->utf && is_char7_bitset(start_bits, FALSE))+ CMPTO(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 127, start);+#endif+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);+ if (!HAS_VIRTUAL_REGISTERS)+ {+ OP2(SLJIT_SHL, TMP3, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP3, 0);+ }+ else+ {+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);+ }+ JUMPTO(SLJIT_ZERO, start);+ }+else+ set_jumps(matches, start);++#if PCRE2_CODE_UNIT_WIDTH != 8+if (found != NULL)+ JUMPHERE(found);+#endif++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (common->mode != PCRE2_JIT_COMPLETE)+ JUMPHERE(partial_quit);++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0);+}++static SLJIT_INLINE jump_list *search_requested_char(compiler_common *common, PCRE2_UCHAR req_char, BOOL caseless, BOOL has_firstchar)+{+DEFINE_COMPILER;+struct sljit_label *loop;+struct sljit_jump *toolong;+struct sljit_jump *already_found;+struct sljit_jump *found;+struct sljit_jump *found_oc = NULL;+jump_list *not_found = NULL;+sljit_u32 oc, bit;++SLJIT_ASSERT(common->req_char_ptr != 0);+OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(REQ_CU_MAX) * 100);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr);+toolong = CMP(SLJIT_LESS, TMP2, 0, STR_END, 0);+already_found = CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0);++if (has_firstchar)+ OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+else+ OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);++oc = req_char;+if (caseless)+ {+ oc = TABLE_GET(req_char, common->fcc, req_char);+#if defined SUPPORT_UNICODE+ if (req_char > 127 && (common->utf || common->ucp))+ oc = UCD_OTHERCASE(req_char);+#endif+ }++#ifdef JIT_HAS_FAST_REQUESTED_CHAR_SIMD+if (JIT_HAS_FAST_REQUESTED_CHAR_SIMD)+ {+ not_found = fast_requested_char_simd(common, req_char, oc);+ }+else+#endif+ {+ loop = LABEL();+ add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));++ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0);++ if (req_char == oc)+ found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char);+ else+ {+ bit = req_char ^ oc;+ if (is_powerof2(bit))+ {+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);+ found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit);+ }+ else+ {+ found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char);+ found_oc = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, oc);+ }+ }+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPTO(SLJIT_JUMP, loop);++ JUMPHERE(found);+ if (found_oc)+ JUMPHERE(found_oc);+ }++OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, TMP1, 0);++JUMPHERE(already_found);+JUMPHERE(toolong);+return not_found;+}++static void do_revertframes(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_label *mainloop;++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);+GET_LOCAL_BASE(TMP1, 0, 0);++/* Drop frames until we reach STACK_TOP. */+mainloop = LABEL();+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -SSIZE_OF(sw));+OP2U(SLJIT_SUB | SLJIT_SET_SIG_LESS_EQUAL | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, 0);+jump = JUMP(SLJIT_SIG_LESS_EQUAL);++OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);+if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * SSIZE_OF(sw)));+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -(3 * SSIZE_OF(sw)));+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * SSIZE_OF(sw));+ }+else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), -(2 * SSIZE_OF(sw)));+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(3 * SSIZE_OF(sw)));+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * SSIZE_OF(sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);+ GET_LOCAL_BASE(TMP1, 0, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP3, 0);+ }+JUMPTO(SLJIT_JUMP, mainloop);++JUMPHERE(jump);+sljit_set_current_flags(compiler, SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE | SLJIT_SET_SIG_LESS_EQUAL | SLJIT_SET_Z);+jump = JUMP(SLJIT_NOT_ZERO /* SIG_LESS */);+/* End of reverting values. */+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump);+OP2(SLJIT_SUB, TMP2, 0, SLJIT_IMM, 0, TMP2, 0);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);+if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * SSIZE_OF(sw)));+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * SSIZE_OF(sw));+ }+else+ {+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(2 * SSIZE_OF(sw)));+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * SSIZE_OF(sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP3, 0);+ }+JUMPTO(SLJIT_JUMP, mainloop);+}++#ifdef SUPPORT_UNICODE+#define UCPCAT(bit) (1 << (bit))+#define UCPCAT2(bit1, bit2) (UCPCAT(bit1) | UCPCAT(bit2))+#define UCPCAT3(bit1, bit2, bit3) (UCPCAT(bit1) | UCPCAT(bit2) | UCPCAT(bit3))+#define UCPCAT_RANGE(start, end) (((1 << ((end) + 1)) - 1) - ((1 << (start)) - 1))+#define UCPCAT_L UCPCAT_RANGE(ucp_Ll, ucp_Lu)+#define UCPCAT_N UCPCAT_RANGE(ucp_Nd, ucp_No)+#define UCPCAT_ALL ((1 << (ucp_Zs + 1)) - 1)+#endif++static void check_wordboundary(compiler_common *common, BOOL ucp)+{+DEFINE_COMPILER;+struct sljit_jump *skipread;+jump_list *skipread_list = NULL;+#ifdef SUPPORT_UNICODE+struct sljit_label *valid_utf;+jump_list *invalid_utf1 = NULL;+#endif /* SUPPORT_UNICODE */+jump_list *invalid_utf2 = NULL;+#if PCRE2_CODE_UNIT_WIDTH != 8 || defined SUPPORT_UNICODE+struct sljit_jump *jump;+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 || SUPPORT_UNICODE */++SLJIT_UNUSED_ARG(ucp);+SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCALS0);+/* Get type of the previous char, and put it to TMP3. */+OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);+skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);++#ifdef SUPPORT_UNICODE+if (common->invalid_utf)+ {+ peek_char_back(common, READ_CHAR_MAX, &invalid_utf1);++ if (common->mode != PCRE2_JIT_COMPLETE)+ {+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);+ move_back(common, NULL, TRUE);+ check_start_used_ptr(common);+ OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);+ }+ }+else+#endif /* SUPPORT_UNICODE */+ {+ if (common->mode == PCRE2_JIT_COMPLETE)+ peek_char_back(common, READ_CHAR_MAX, NULL);+ else+ {+ move_back(common, NULL, TRUE);+ check_start_used_ptr(common);+ read_char(common, 0, READ_CHAR_MAX, NULL, READ_CHAR_UPDATE_STR_PTR);+ }+ }++/* Testing char type. */+#ifdef SUPPORT_UNICODE+if (ucp)+ {+ add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP1, 0);+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, UCPCAT2(ucp_Mn, ucp_Pc) | UCPCAT_L | UCPCAT_N);+ OP_FLAGS(SLJIT_MOV, TMP3, 0, SLJIT_NOT_ZERO);+ }+else+#endif /* SUPPORT_UNICODE */+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+#elif defined SUPPORT_UNICODE+ /* Here TMP3 has already been zeroed. */+ jump = NULL;+ if (common->utf)+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ 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, TMP3, 0, TMP1, 0, SLJIT_IMM, 1);+#if PCRE2_CODE_UNIT_WIDTH != 8+ JUMPHERE(jump);+#elif defined SUPPORT_UNICODE+ if (jump != NULL)+ JUMPHERE(jump);+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ }+JUMPHERE(skipread);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);+check_str_end(common, &skipread_list);+peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, &invalid_utf2);++/* Testing char type. This is a code duplication. */+#ifdef SUPPORT_UNICODE++valid_utf = LABEL();++if (ucp)+ {+ add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP1, 0);+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, UCPCAT2(ucp_Mn, ucp_Pc) | UCPCAT_L | UCPCAT_N);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO);+ }+else+#endif /* SUPPORT_UNICODE */+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ /* TMP2 may be destroyed by peek_char. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+#elif defined SUPPORT_UNICODE+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);+ jump = NULL;+ if (common->utf)+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+#endif+ 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);+#if PCRE2_CODE_UNIT_WIDTH != 8+ JUMPHERE(jump);+#elif defined SUPPORT_UNICODE+ if (jump != NULL)+ JUMPHERE(jump);+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ }+set_jumps(skipread_list, LABEL());++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP2(SLJIT_XOR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, TMP3, 0);+OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);++#ifdef SUPPORT_UNICODE+if (common->invalid_utf)+ {+ set_jumps(invalid_utf1, LABEL());++ peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, NULL);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR, valid_utf);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, -1);+ OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);++ set_jumps(invalid_utf2, LABEL());+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ OP1(SLJIT_MOV, TMP2, 0, TMP3, 0);+ OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);+ }+#endif /* SUPPORT_UNICODE */+}++static BOOL optimize_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)+{+/* May destroy TMP1. */+DEFINE_COMPILER;+int ranges[MAX_CLASS_RANGE_SIZE];+sljit_u8 bit, cbit, all;+int i, byte, length = 0;++bit = bits[0] & 0x1;+/* All bits will be zero or one (since bit is zero or one). */+all = (sljit_u8)-bit;++for (i = 0; i < 256; )+ {+ byte = i >> 3;+ if ((i & 0x7) == 0 && bits[byte] == all)+ i += 8;+ else+ {+ cbit = (bits[byte] >> (i & 0x7)) & 0x1;+ if (cbit != bit)+ {+ if (length >= MAX_CLASS_RANGE_SIZE)+ return FALSE;+ ranges[length] = i;+ length++;+ bit = cbit;+ all = (sljit_u8)-cbit; /* sign extend bit into byte */+ }+ i++;+ }+ }++if (((bit == 0) && nclass) || ((bit == 1) && !nclass))+ {+ if (length >= MAX_CLASS_RANGE_SIZE)+ return FALSE;+ ranges[length] = 256;+ length++;+ }++if (length < 0 || length > 4)+ return FALSE;++bit = bits[0] & 0x1;+if (invert) bit ^= 0x1;++/* No character is accepted. */+if (length == 0 && bit == 0)+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));++switch(length)+ {+ case 0:+ /* When bit != 0, all characters are accepted. */+ return TRUE;++ case 1:+ add_jump(compiler, backtracks, CMP(bit == 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));+ return TRUE;++ case 2:+ if (ranges[0] + 1 != ranges[1])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));+ }+ else+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));+ return TRUE;++ case 3:+ if (bit != 0)+ {+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));+ if (ranges[0] + 1 != ranges[1])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));+ return TRUE;+ }++ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[0]));+ if (ranges[1] + 1 != ranges[2])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1]);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1]));+ return TRUE;++ case 4:+ if ((ranges[1] - ranges[0]) == (ranges[3] - ranges[2])+ && (ranges[0] | (ranges[2] - ranges[0])) == ranges[2]+ && (ranges[1] & (ranges[2] - ranges[0])) == 0+ && is_powerof2(ranges[2] - ranges[0]))+ {+ SLJIT_ASSERT((ranges[0] & (ranges[2] - ranges[0])) == 0 && (ranges[2] & ranges[3] & (ranges[2] - ranges[0])) != 0);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[0]);+ if (ranges[2] + 1 != ranges[3])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]);+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));+ }+ else+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));+ return TRUE;+ }++ if (bit != 0)+ {+ i = 0;+ if (ranges[0] + 1 != ranges[1])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));+ i = ranges[0];+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));++ if (ranges[2] + 1 != ranges[3])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - i);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2] - i));+ return TRUE;+ }++ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[0]));+ if (ranges[1] + 1 != ranges[2])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));+ return TRUE;++ default:+ SLJIT_UNREACHABLE();+ return FALSE;+ }+}++static BOOL optimize_class_chars(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)+{+/* May destroy TMP1. */+DEFINE_COMPILER;+uint16_t char_list[MAX_CLASS_CHARS_SIZE];+uint8_t byte;+sljit_s32 type;+int i, j, k, len, c;++if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV))+ return FALSE;++len = 0;++for (i = 0; i < 32; i++)+ {+ byte = bits[i];++ if (nclass)+ byte = (sljit_u8)~byte;++ j = 0;+ while (byte != 0)+ {+ if (byte & 0x1)+ {+ c = i * 8 + j;++ k = len;++ if ((c & 0x20) != 0)+ {+ for (k = 0; k < len; k++)+ if (char_list[k] == c - 0x20)+ {+ char_list[k] |= 0x120;+ break;+ }+ }++ if (k == len)+ {+ if (len >= MAX_CLASS_CHARS_SIZE)+ return FALSE;++ char_list[len++] = (uint16_t) c;+ }+ }++ byte >>= 1;+ j++;+ }+ }++if (len == 0) return FALSE; /* Should never occur, but stops analyzers complaining. */++i = 0;+j = 0;++if (char_list[0] == 0)+ {+ i++;+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_ZERO);+ }+else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);++while (i < len)+ {+ if ((char_list[i] & 0x100) != 0)+ j++;+ else+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, char_list[i]);+ SELECT(SLJIT_ZERO, TMP2, TMP1, 0, TMP2);+ }+ i++;+ }++if (j != 0)+ {+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x20);++ for (i = 0; i < len; i++)+ if ((char_list[i] & 0x100) != 0)+ {+ j--;+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, char_list[i] & 0xff);+ SELECT(SLJIT_ZERO, TMP2, TMP1, 0, TMP2);+ }+ }++if (invert)+ nclass = !nclass;++type = nclass ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;+add_jump(compiler, backtracks, CMP(type, TMP2, 0, SLJIT_IMM, 0));+return TRUE;+}++static BOOL optimize_class(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)+{+/* May destroy TMP1. */+if (optimize_class_ranges(common, bits, nclass, invert, backtracks))+ return TRUE;+return optimize_class_chars(common, bits, nclass, invert, backtracks);+}++static void check_anynewline(compiler_common *common)+{+/* Check whether TMP1 contains a newline character. TMP2 destroyed. */+DEFINE_COMPILER;++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);+OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+#endif+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);+#if PCRE2_CODE_UNIT_WIDTH == 8+ }+#endif+#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void check_hspace(compiler_common *common)+{+/* Check whether TMP1 contains a newline character. TMP2 destroyed. */+DEFINE_COMPILER;++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x09);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x20);+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0xa0);+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+#endif+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x1680);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);+#if PCRE2_CODE_UNIT_WIDTH == 8+ }+#endif+#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void check_vspace(compiler_common *common)+{+/* Check whether TMP1 contains a newline character. TMP2 destroyed. */+DEFINE_COMPILER;++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);+OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+#endif+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);+#if PCRE2_CODE_UNIT_WIDTH == 8+ }+#endif+#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_casefulcmp(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_label *label;+int char1_reg;+int char2_reg;++if (HAS_VIRTUAL_REGISTERS)+ {+ char1_reg = STR_END;+ char2_reg = STACK_TOP;+ }+else+ {+ char1_reg = TMP3;+ char2_reg = RETURN_ADDR;+ }++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++if (char1_reg == STR_END)+ {+ OP1(SLJIT_MOV, TMP3, 0, char1_reg, 0);+ OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0);+ }++if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)+ {+ label = LABEL();+ sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));+ sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPTO(SLJIT_NOT_ZERO, label);++ JUMPHERE(jump);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ }+else if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ label = LABEL();+ sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));+ sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPTO(SLJIT_NOT_ZERO, label);++ JUMPHERE(jump);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ }+else+ {+ label = LABEL();+ OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);+ OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPTO(SLJIT_NOT_ZERO, label);++ JUMPHERE(jump);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ }++if (char1_reg == STR_END)+ {+ OP1(SLJIT_MOV, char1_reg, 0, TMP3, 0);+ OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0);+ }++OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);+}++static void do_caselesscmp(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_label *label;+int char1_reg = STR_END;+int char2_reg;+int lcc_table;+int opt_type = 0;++if (HAS_VIRTUAL_REGISTERS)+ {+ char2_reg = STACK_TOP;+ lcc_table = STACK_LIMIT;+ }+else+ {+ char2_reg = RETURN_ADDR;+ lcc_table = TMP3;+ }++if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)+ opt_type = 1;+else if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)+ opt_type = 2;++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0);++if (char2_reg == STACK_TOP)+ {+ OP1(SLJIT_MOV, TMP3, 0, char2_reg, 0);+ OP1(SLJIT_MOV, RETURN_ADDR, 0, lcc_table, 0);+ }++OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc);++if (opt_type == 1)+ {+ label = LABEL();+ sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));+ sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ }+else if (opt_type == 2)+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ label = LABEL();+ sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));+ sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ }+else+ {+ label = LABEL();+ OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);+ OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ }++#if PCRE2_CODE_UNIT_WIDTH != 8+jump = CMP(SLJIT_GREATER, char1_reg, 0, SLJIT_IMM, 255);+#endif+OP1(SLJIT_MOV_U8, char1_reg, 0, SLJIT_MEM2(lcc_table, char1_reg), 0);+#if PCRE2_CODE_UNIT_WIDTH != 8+JUMPHERE(jump);+jump = CMP(SLJIT_GREATER, char2_reg, 0, SLJIT_IMM, 255);+#endif+OP1(SLJIT_MOV_U8, char2_reg, 0, SLJIT_MEM2(lcc_table, char2_reg), 0);+#if PCRE2_CODE_UNIT_WIDTH != 8+JUMPHERE(jump);+#endif++if (opt_type == 0)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);+OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+JUMPTO(SLJIT_NOT_ZERO, label);++JUMPHERE(jump);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);++if (opt_type == 2)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (char2_reg == STACK_TOP)+ {+ OP1(SLJIT_MOV, char2_reg, 0, TMP3, 0);+ OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0);+ }++OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);+OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);+}++static PCRE2_SPTR byte_sequence_compare(compiler_common *common, BOOL caseless, PCRE2_SPTR cc,+ compare_context *context, jump_list **backtracks)+{+DEFINE_COMPILER;+unsigned int othercasebit = 0;+PCRE2_SPTR othercasechar = NULL;+#ifdef SUPPORT_UNICODE+int utflength;+#endif++if (caseless && char_has_othercase(common, cc))+ {+ othercasebit = char_get_othercase_bit(common, cc);+ SLJIT_ASSERT(othercasebit);+ /* Extracting bit difference info. */+#if PCRE2_CODE_UNIT_WIDTH == 8+ othercasechar = cc + (othercasebit >> 8);+ othercasebit &= 0xff;+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ /* Note that this code only handles characters in the BMP. If there+ ever are characters outside the BMP whose othercase differs in only one+ bit from itself (there currently are none), this code will need to be+ revised for PCRE2_CODE_UNIT_WIDTH == 32. */+ othercasechar = cc + (othercasebit >> 9);+ if ((othercasebit & 0x100) != 0)+ othercasebit = (othercasebit & 0xff) << 8;+ else+ othercasebit &= 0xff;+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+ }++if (context->sourcereg == -1)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ if (context->length >= 4)+ OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+ else if (context->length >= 2)+ OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+ else+#endif+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+#elif PCRE2_CODE_UNIT_WIDTH == 16+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ if (context->length >= 4)+ 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);+#elif PCRE2_CODE_UNIT_WIDTH == 32+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+ context->sourcereg = TMP2;+ }++#ifdef SUPPORT_UNICODE+utflength = 1;+if (common->utf && HAS_EXTRALEN(*cc))+ utflength += GET_EXTRALEN(*cc);++do+ {+#endif++ context->length -= IN_UCHARS(1);+#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)++ /* Unaligned read is supported. */+ if (othercasebit != 0 && othercasechar == cc)+ {+ context->c.asuchars[context->ucharptr] = *cc | othercasebit;+ context->oc.asuchars[context->ucharptr] = othercasebit;+ }+ else+ {+ context->c.asuchars[context->ucharptr] = *cc;+ context->oc.asuchars[context->ucharptr] = 0;+ }+ context->ucharptr++;++#if PCRE2_CODE_UNIT_WIDTH == 8+ if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1))+#else+ if (context->ucharptr >= 2 || context->length == 0)+#endif+ {+ if (context->length >= 4)+ OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);+ else if (context->length >= 2)+ OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);+#if PCRE2_CODE_UNIT_WIDTH == 8+ else if (context->length >= 1)+ OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;++ switch(context->ucharptr)+ {+ case 4 / sizeof(PCRE2_UCHAR):+ if (context->oc.asint != 0)+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));+ break;++ case 2 / sizeof(PCRE2_UCHAR):+ if (context->oc.asushort != 0)+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));+ break;++#if PCRE2_CODE_UNIT_WIDTH == 8+ case 1:+ if (context->oc.asbyte != 0)+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));+ break;+#endif++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ context->ucharptr = 0;+ }++#else++ /* Unaligned read is unsupported or in 32 bit mode. */+ if (context->length >= 1)+ OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);++ context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;++ if (othercasebit != 0 && othercasechar == cc)+ {+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));++#endif++ cc++;+#ifdef SUPPORT_UNICODE+ utflength--;+ }+while (utflength > 0);+#endif++return cc;+}++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8++#define SET_CHAR_OFFSET(value) \+ if ((value) != charoffset) \+ { \+ if ((value) < charoffset) \+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(charoffset - (value))); \+ else \+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)((value) - charoffset)); \+ } \+ charoffset = (value);++static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr);++#ifdef SUPPORT_UNICODE+#define XCLASS_SAVE_CHAR 0x001+#define XCLASS_CHAR_SAVED 0x002+#define XCLASS_HAS_TYPE 0x004+#define XCLASS_HAS_SCRIPT 0x008+#define XCLASS_HAS_SCRIPT_EXTENSION 0x010+#define XCLASS_HAS_BOOL 0x020+#define XCLASS_HAS_BIDICL 0x040+#define XCLASS_NEEDS_UCD (XCLASS_HAS_TYPE | XCLASS_HAS_SCRIPT | XCLASS_HAS_SCRIPT_EXTENSION | XCLASS_HAS_BOOL | XCLASS_HAS_BIDICL)+#define XCLASS_SCRIPT_EXTENSION_NOTPROP 0x080+#define XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR 0x100+#define XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0 0x200+#endif /* SUPPORT_UNICODE */++static void compile_xclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)+{+DEFINE_COMPILER;+jump_list *found = NULL;+jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks;+sljit_uw c, charoffset, max = 256, min = READ_CHAR_MAX;+struct sljit_jump *jump = NULL;+PCRE2_SPTR ccbegin;+int compares, invertcmp, numberofcmps;+#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)+BOOL utf = common->utf;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */++#ifdef SUPPORT_UNICODE+sljit_u32 unicode_status = 0;+sljit_u32 category_list = 0;+sljit_u32 items;+int typereg = TMP1;+const sljit_u32 *other_cases;+#endif /* SUPPORT_UNICODE */++/* Scanning the necessary info. */+cc++;+ccbegin = cc;+compares = 0;++if (cc[-1] & XCL_MAP)+ {+ min = 0;+ cc += 32 / sizeof(PCRE2_UCHAR);+ }++while (*cc != XCL_END)+ {+ compares++;++ if (*cc == XCL_SINGLE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);+ if (c > max) max = c;+ if (c < min) min = c;+#ifdef SUPPORT_UNICODE+ unicode_status |= XCLASS_SAVE_CHAR;+#endif /* SUPPORT_UNICODE */+ }+ else if (*cc == XCL_RANGE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);+ if (c < min) min = c;+ GETCHARINCTEST(c, cc);+ if (c > max) max = c;+#ifdef SUPPORT_UNICODE+ unicode_status |= XCLASS_SAVE_CHAR;+#endif /* SUPPORT_UNICODE */+ }+#ifdef SUPPORT_UNICODE+ else+ {+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);+ cc++;++ if (*cc == PT_CLIST && cc[-1] == XCL_PROP)+ {+ other_cases = PRIV(ucd_caseless_sets) + cc[1];+ while (*other_cases != NOTACHAR)+ {+ if (*other_cases > max) max = *other_cases;+ if (*other_cases < min) min = *other_cases;+ other_cases++;+ }+ }+ else+ {+ max = READ_CHAR_MAX;+ min = 0;+ }++ items = 0;++ switch(*cc)+ {+ case PT_ANY:+ /* Any either accepts everything or ignored. */+ if (cc[-1] == XCL_PROP)+ items = UCPCAT_ALL;+ else+ compares--;+ break;++ case PT_LAMP:+ items = UCPCAT3(ucp_Lu, ucp_Ll, ucp_Lt);+ break;++ case PT_GC:+ items = UCPCAT_RANGE(PRIV(ucp_typerange)[(int)cc[1] * 2], PRIV(ucp_typerange)[(int)cc[1] * 2 + 1]);+ break;++ case PT_PC:+ items = UCPCAT(cc[1]);+ break;++ case PT_WORD:+ items = UCPCAT2(ucp_Mn, ucp_Pc) | UCPCAT_L | UCPCAT_N;+ break;++ case PT_ALNUM:+ items = UCPCAT_L | UCPCAT_N;+ break;++ case PT_SCX:+ unicode_status |= XCLASS_HAS_SCRIPT_EXTENSION;+ if (cc[-1] == XCL_NOTPROP)+ {+ unicode_status |= XCLASS_SCRIPT_EXTENSION_NOTPROP;+ break;+ }+ compares++;+ /* Fall through */++ case PT_SC:+ unicode_status |= XCLASS_HAS_SCRIPT;+ break;++ case PT_SPACE:+ case PT_PXSPACE:+ case PT_PXGRAPH:+ case PT_PXPRINT:+ case PT_PXPUNCT:+ unicode_status |= XCLASS_SAVE_CHAR | XCLASS_HAS_TYPE;+ break;++ case PT_CLIST:+ case PT_UCNC:+ case PT_PXXDIGIT:+ unicode_status |= XCLASS_SAVE_CHAR;+ break;++ case PT_BOOL:+ unicode_status |= XCLASS_HAS_BOOL;+ break;++ case PT_BIDICL:+ unicode_status |= XCLASS_HAS_BIDICL;+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++ if (items > 0)+ {+ if (cc[-1] == XCL_NOTPROP)+ items ^= UCPCAT_ALL;+ category_list |= items;+ unicode_status |= XCLASS_HAS_TYPE;+ compares--;+ }++ cc += 2;+ }+#endif /* SUPPORT_UNICODE */+ }++#ifdef SUPPORT_UNICODE+if (category_list == UCPCAT_ALL)+ {+ /* All characters are accepted, same as dotall. */+ compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE);+ if (list == backtracks)+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ return;+ }++if (compares == 0 && category_list == 0)+ {+ /* No characters are accepted, same as (*F) or dotall. */+ compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE);+ if (list != backtracks)+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ return;+ }+#else /* !SUPPORT_UNICODE */+SLJIT_ASSERT(compares > 0);+#endif /* SUPPORT_UNICODE */++/* We are not necessary in utf mode even in 8 bit mode. */+cc = ccbegin;+if ((cc[-1] & XCL_NOT) != 0)+ read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR);+else+ {+#ifdef SUPPORT_UNICODE+ read_char(common, min, max, (unicode_status & XCLASS_NEEDS_UCD) ? backtracks : NULL, 0);+#else /* !SUPPORT_UNICODE */+ read_char(common, min, max, NULL, 0);+#endif /* SUPPORT_UNICODE */+ }++if ((cc[-1] & XCL_HASPROP) == 0)+ {+ if ((cc[-1] & XCL_MAP) != 0)+ {+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+ if (!optimize_class(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_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);+ add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO));+ }++ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ JUMPHERE(jump);++ cc += 32 / sizeof(PCRE2_UCHAR);+ }+ else+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, min);+ add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, max - min));+ }+ }+else if ((cc[-1] & XCL_MAP) != 0)+ {+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);+#ifdef SUPPORT_UNICODE+ unicode_status |= XCLASS_CHAR_SAVED;+#endif /* SUPPORT_UNICODE */+ if (!optimize_class(common, (const sljit_u8 *)cc, FALSE, TRUE, list))+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ jump = NULL;+ if (common->utf)+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);++ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);+ add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO));++#if PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf)+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ JUMPHERE(jump);+ }++ OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);+ cc += 32 / sizeof(PCRE2_UCHAR);+ }++#ifdef SUPPORT_UNICODE+if (unicode_status & XCLASS_NEEDS_UCD)+ {+ if ((unicode_status & (XCLASS_SAVE_CHAR | XCLASS_CHAR_SAVED)) == XCLASS_SAVE_CHAR)+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);++#if PCRE2_CODE_UNIT_WIDTH == 32+ if (!common->utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);+ JUMPHERE(jump);+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */++ OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);+ OP1(SLJIT_MOV_U16, 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);+ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);++ ccbegin = cc;++ if (category_list != 0)+ compares++;++ if (unicode_status & XCLASS_HAS_BIDICL)+ {+ OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass));+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BIDICLASS_SHIFT);++ while (*cc != XCL_END)+ {+ 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_BIDICL)+ {+ 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;+ }+ }++ cc = ccbegin;+ }++ if (unicode_status & XCLASS_HAS_BOOL)+ {+ OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, bprops));+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BPROPS_MASK);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);++ while (*cc != XCL_END)+ {+ 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_BOOL)+ {+ compares--;+ invertcmp = (compares == 0 && list != backtracks);+ if (cc[-1] == XCL_NOTPROP)+ invertcmp ^= 0x1;++ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_boolprop_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)(1u << (cc[1] & 0x1f)));+ add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp));+ }+ cc += 2;+ }+ }++ cc = ccbegin;+ }++ if (unicode_status & XCLASS_HAS_SCRIPT)+ {+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));++ while (*cc != XCL_END)+ {+ 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++;+ switch (*cc)+ {+ case PT_SCX:+ if (cc[-1] == XCL_NOTPROP)+ break;+ /* Fall through */++ case PT_SC:+ compares--;+ invertcmp = (compares == 0 && list != backtracks);+ if (cc[-1] == XCL_NOTPROP)+ invertcmp ^= 0x1;++ add_jump(compiler, compares > 0 ? list : backtracks, CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]));+ }+ cc += 2;+ }+ }++ cc = ccbegin;+ }++ if (unicode_status & XCLASS_HAS_SCRIPT_EXTENSION)+ {+ OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass));+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_SCRIPTX_MASK);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);++ if (unicode_status & XCLASS_SCRIPT_EXTENSION_NOTPROP)+ {+ if (unicode_status & XCLASS_HAS_TYPE)+ {+ if (unicode_status & XCLASS_SAVE_CHAR)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP2, 0);+ unicode_status |= XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0;+ }+ else+ {+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0);+ unicode_status |= XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR;+ }+ }+ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));+ }++ while (*cc != XCL_END)+ {+ 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_SCX)+ {+ compares--;+ invertcmp = (compares == 0 && list != backtracks);++ jump = NULL;+ if (cc[-1] == XCL_NOTPROP)+ {+ jump = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, (int)cc[1]);+ if (invertcmp)+ {+ add_jump(compiler, backtracks, jump);+ jump = NULL;+ }+ invertcmp ^= 0x1;+ }++ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_script_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)(1u << (cc[1] & 0x1f)));+ add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp));++ if (jump != NULL)+ JUMPHERE(jump);+ }+ cc += 2;+ }+ }++ if (unicode_status & XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ else if (unicode_status & XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR)+ OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0);+ cc = ccbegin;+ }++ if (unicode_status & XCLASS_SAVE_CHAR)+ OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);++ if (unicode_status & XCLASS_HAS_TYPE)+ {+ if (unicode_status & XCLASS_SAVE_CHAR)+ typereg = RETURN_ADDR;++ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));+ OP2(SLJIT_SHL, typereg, 0, SLJIT_IMM, 1, TMP2, 0);++ if (category_list > 0)+ {+ compares--;+ invertcmp = (compares == 0 && list != backtracks);+ OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, category_list);+ add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp));+ }+ }+ }+#endif /* SUPPORT_UNICODE */++/* Generating code. */+charoffset = 0;+numberofcmps = 0;++while (*cc != XCL_END)+ {+ compares--;+ invertcmp = (compares == 0 && list != backtracks);+ jump = NULL;++ if (*cc == XCL_SINGLE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);++ if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, 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)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, 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;+ }+ else+ {+ jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));+ numberofcmps = 0;+ }+ }+ else if (*cc == XCL_RANGE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);+ SET_CHAR_OFFSET(c);+ GETCHARINCTEST(c, cc);++ if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))+ {+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, 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;+ }+ else+ {+ jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));+ numberofcmps = 0;+ }+ }+#ifdef SUPPORT_UNICODE+ else+ {+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);+ if (*cc == XCL_NOTPROP)+ invertcmp ^= 0x1;+ cc++;+ switch(*cc)+ {+ case PT_ANY:+ case PT_LAMP:+ case PT_GC:+ case PT_PC:+ case PT_SC:+ case PT_SCX:+ case PT_BOOL:+ case PT_BIDICL:+ case PT_WORD:+ case PT_ALNUM:+ compares++;+ /* Already handled. */+ break;++ case PT_SPACE:+ case PT_PXSPACE:+ SET_CHAR_OFFSET(9);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xd - 0x9);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);++ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Zl, ucp_Zs));+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_ZERO);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ break;++ case PT_CLIST:+ other_cases = PRIV(ucd_caseless_sets) + cc[1];++ /* At least three characters are required.+ Otherwise this case would be handled by the normal code path. */+ SLJIT_ASSERT(other_cases[0] != NOTACHAR && other_cases[1] != NOTACHAR && other_cases[2] != NOTACHAR);+ SLJIT_ASSERT(other_cases[0] < other_cases[1] && other_cases[1] < other_cases[2]);++ /* Optimizing character pairs, if their difference is power of 2. */+ if (is_powerof2(other_cases[1] ^ other_cases[0]))+ {+ if (charoffset == 0)+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);+ else+ {+ 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]);+ }+ OP2U(SLJIT_SUB | SLJIT_SET_Z, 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]))+ {+ if (charoffset == 0)+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[2] ^ other_cases[1]);+ else+ {+ 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]);+ }+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, other_cases[2]);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);++ OP2U(SLJIT_SUB | SLJIT_SET_Z, 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+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+ }++ while (*other_cases != NOTACHAR)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, 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:+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ SET_CHAR_OFFSET(0xa0);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);+ SET_CHAR_OFFSET(0);+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, 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:+ OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Cc, ucp_Cs) | UCPCAT_RANGE(ucp_Zl, ucp_Zs));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO);++ OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT(ucp_Cf));+ jump = JUMP(SLJIT_ZERO);++ c = charoffset;+ /* In case of ucp_Cf, we overwrite the result. */+ SET_CHAR_OFFSET(0x2066);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);++ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ /* Restore charoffset. */+ SET_CHAR_OFFSET(c);++ JUMPHERE(jump);+ jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);+ break;++ case PT_PXPRINT:+ OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Cc, ucp_Cs) | UCPCAT2(ucp_Zl, ucp_Zp));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO);++ OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT(ucp_Cf));+ jump = JUMP(SLJIT_ZERO);++ c = charoffset;+ /* In case of ucp_Cf, we overwrite the result. */+ SET_CHAR_OFFSET(0x2066);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);++ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ /* Restore charoffset. */+ SET_CHAR_OFFSET(c);++ JUMPHERE(jump);+ jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);+ break;++ case PT_PXPUNCT:+ OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Sc, ucp_So));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO);++ SET_CHAR_OFFSET(0);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x7f);+ OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL);++ OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Pc, ucp_Ps));+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_ZERO);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ break;++ case PT_PXXDIGIT:+ SET_CHAR_OFFSET(CHAR_A);+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, ~0x20);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP2, 0, SLJIT_IMM, CHAR_F - CHAR_A);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);++ SET_CHAR_OFFSET(CHAR_0);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_9 - CHAR_0);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);++ SET_CHAR_OFFSET(0xff10);+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 0xff46 - 0xff10);++ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xff19 - 0xff10);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);++ SET_CHAR_OFFSET(0xff21);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xff26 - 0xff21);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);++ SET_CHAR_OFFSET(0xff41);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xff46 - 0xff41);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);++ SET_CHAR_OFFSET(0xff10);++ JUMPHERE(jump);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, 0);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ cc += 2;+ }+#endif /* SUPPORT_UNICODE */++ if (jump != NULL)+ add_jump(compiler, compares > 0 ? list : backtracks, jump);+ }++SLJIT_ASSERT(compares == 0);+if (found != NULL)+ set_jumps(found, LABEL());+}++#undef SET_TYPE_OFFSET+#undef SET_CHAR_OFFSET++#endif++static PCRE2_SPTR compile_simple_assertion_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks)+{+DEFINE_COMPILER;+struct sljit_jump *jump[4];++switch(type)+ {+ case OP_SOD:+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ else+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));+ return cc;++ case OP_SOM:+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+ }+ else+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), 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:+ case OP_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:+ add_jump(compiler, (type == OP_NOT_WORD_BOUNDARY || type == OP_WORD_BOUNDARY) ? &common->wordboundary : &common->ucp_wordboundary, JUMP(SLJIT_FAST_CALL));+#ifdef SUPPORT_UNICODE+ if (common->invalid_utf)+ {+ add_jump(compiler, backtracks, CMP((type == OP_NOT_WORD_BOUNDARY || type == OP_NOT_UCP_WORD_BOUNDARY) ? SLJIT_NOT_EQUAL : SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0));+ return cc;+ }+#endif /* SUPPORT_UNICODE */+ sljit_set_current_flags(compiler, SLJIT_SET_Z);+ add_jump(compiler, backtracks, JUMP((type == OP_NOT_WORD_BOUNDARY || type == OP_NOT_UCP_WORD_BOUNDARY) ? SLJIT_NOT_ZERO : SLJIT_ZERO));+ return cc;++ 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 == PCRE2_JIT_COMPLETE)+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));+ else+ {+ jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, STR_END, 0);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);+ OP2U(SLJIT_SUB | SLJIT_SET_Z, 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));+ OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, 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, TMP3, 0, STR_PTR, 0);+ read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR);+ 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, TMP3, 0);+ }+ JUMPHERE(jump[2]);+ JUMPHERE(jump[3]);+ }+ JUMPHERE(jump[0]);+ if (common->mode != PCRE2_JIT_COMPLETE)+ check_partial(common, TRUE);+ return cc;++ case OP_EOD:+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));+ if (common->mode != PCRE2_JIT_COMPLETE)+ check_partial(common, TRUE);+ return cc;++ case OP_DOLL:+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);+ }+ else+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));++ 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);+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);+ }+ else+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));+ 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 == PCRE2_JIT_COMPLETE)+ 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, TMP3, 0, NULL);+ check_newlinechar(common, common->nltype, backtracks, FALSE);+ }+ JUMPHERE(jump[0]);+ return cc;++ case OP_CIRC:+ if (HAS_VIRTUAL_REGISTERS)+ {+ 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));+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));+ }+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));+ }+ return cc;++ case OP_CIRCM:+ /* TMP2 might be used by peek_char_back. */+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);+ }+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));+ jump[0] = JUMP(SLJIT_JUMP);+ JUMPHERE(jump[1]);++ if (!common->alt_circumflex)+ 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, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, TMP2, 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+ {+ peek_char_back(common, common->nlmax, backtracks);+ check_newlinechar(common, common->nltype, backtracks, FALSE);+ }+ JUMPHERE(jump[0]);+ return cc;+ }+SLJIT_UNREACHABLE();+return cc;+}++#ifdef SUPPORT_UNICODE++#if PCRE2_CODE_UNIT_WIDTH != 32++/* The code in this function copies the logic of the interpreter function that+is defined in the pcre2_extuni.c source. If that code is updated, this+function, and those below it, must be kept in step (note by PH, June 2024). */++static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc)+{+PCRE2_SPTR start_subject = args->begin;+PCRE2_SPTR end_subject = args->end;+int lgb, rgb, ricount;+PCRE2_SPTR prevcc, endcc, bptr;+BOOL first = TRUE;+BOOL was_ep_ZWJ = FALSE;+uint32_t c;++prevcc = cc;+endcc = NULL;+do+ {+ GETCHARINC(c, cc);+ rgb = UCD_GRAPHBREAK(c);++ if (first)+ {+ lgb = rgb;+ endcc = cc;+ first = FALSE;+ continue;+ }++ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)+ break;++ /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was+ preceded by Extended Pictographic. */++ if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ)+ break;++ /* Not breaking between Regional Indicators is allowed only if there+ are an even number of preceding RIs. */++ if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)+ {+ ricount = 0;+ bptr = prevcc;++ /* bptr is pointing to the left-hand character */+ while (bptr > start_subject)+ {+ bptr--;+ BACKCHAR(bptr);+ GETCHAR(c, bptr);++ if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator)+ break;++ ricount++;+ }++ if ((ricount & 1) != 0) break; /* Grapheme break required */+ }++ /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in+ between; see next statement). */++ was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ);++ /* If Extend follows Extended_Pictographic, do not update lgb; this allows+ any number of them before a following ZWJ. */++ if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic)+ lgb = rgb;++ prevcc = endcc;+ endcc = cc;+ }+while (cc < end_subject);++return endcc;+}++#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */++/* The code in this function copies the logic of the interpreter function that+is defined in the pcre2_extuni.c source. If that code is updated, this+function, and the one below it, must be kept in step (note by PH, June 2024). */++static PCRE2_SPTR SLJIT_FUNC do_extuni_utf_invalid(jit_arguments *args, PCRE2_SPTR cc)+{+PCRE2_SPTR start_subject = args->begin;+PCRE2_SPTR end_subject = args->end;+int lgb, rgb, ricount;+PCRE2_SPTR prevcc, endcc, bptr;+BOOL first = TRUE;+BOOL was_ep_ZWJ = FALSE;+uint32_t c;++prevcc = cc;+endcc = NULL;+do+ {+ GETCHARINC_INVALID(c, cc, end_subject, break);+ rgb = UCD_GRAPHBREAK(c);++ if (first)+ {+ lgb = rgb;+ endcc = cc;+ first = FALSE;+ continue;+ }++ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)+ break;++ /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was+ preceded by Extended Pictographic. */++ if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ)+ break;++ /* Not breaking between Regional Indicators is allowed only if there+ are an even number of preceding RIs. */++ if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)+ {+ ricount = 0;+ bptr = prevcc;++ /* bptr is pointing to the left-hand character */+ while (bptr > start_subject)+ {+ GETCHARBACK_INVALID(c, bptr, start_subject, break);++ if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator)+ break;++ ricount++;+ }++ if ((ricount & 1) != 0)+ break; /* Grapheme break required */+ }++ /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in+ between; see next statement). */++ was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ);++ /* If Extend follows Extended_Pictographic, do not update lgb; this allows+ any number of them before a following ZWJ. */++ if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic)+ lgb = rgb;++ prevcc = endcc;+ endcc = cc;+ }+while (cc < end_subject);++return endcc;+}++/* The code in this function copies the logic of the interpreter function that+is defined in the pcre2_extuni.c source. If that code is updated, this+function must be kept in step (note by PH, June 2024). */++static PCRE2_SPTR SLJIT_FUNC do_extuni_no_utf(jit_arguments *args, PCRE2_SPTR cc)+{+PCRE2_SPTR start_subject = args->begin;+PCRE2_SPTR end_subject = args->end;+int lgb, rgb, ricount;+PCRE2_SPTR bptr;+uint32_t c;+BOOL was_ep_ZWJ = FALSE;++/* Patch by PH */+/* GETCHARINC(c, cc); */+c = *cc++;++#if PCRE2_CODE_UNIT_WIDTH == 32+if (c >= 0x110000)+ return cc;+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */+lgb = UCD_GRAPHBREAK(c);++while (cc < end_subject)+ {+ c = *cc;+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c >= 0x110000)+ break;+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */+ rgb = UCD_GRAPHBREAK(c);++ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)+ break;++ /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was+ preceded by Extended Pictographic. */++ if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ)+ break;++ /* Not breaking between Regional Indicators is allowed only if there+ are an even number of preceding RIs. */++ if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)+ {+ ricount = 0;+ bptr = cc - 1;++ /* bptr is pointing to the left-hand character */+ while (bptr > start_subject)+ {+ bptr--;+ c = *bptr;+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c >= 0x110000)+ break;+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */++ if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) break;++ ricount++;+ }++ if ((ricount & 1) != 0)+ break; /* Grapheme break required */+ }++ /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in+ between; see next statement). */++ was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ);++ /* If Extend follows Extended_Pictographic, do not update lgb; this allows+ any number of them before a following ZWJ. */++ if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic)+ lgb = rgb;++ cc++;+ }++return cc;+}++#endif /* SUPPORT_UNICODE */++static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr)+{+DEFINE_COMPILER;+int length;+unsigned int c, oc, bit;+compare_context context;+struct sljit_jump *jump[3];+jump_list *end_list;+#ifdef SUPPORT_UNICODE+PCRE2_UCHAR propdata[5];+#endif /* SUPPORT_UNICODE */++switch(type)+ {+ case OP_NOT_DIGIT:+ case OP_DIGIT:+ /* Digits are usually 0-9, so it is worth to optimize them. */+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_digit, FALSE))+ read_char7_type(common, backtracks, type == OP_NOT_DIGIT);+ else+#endif+ read_char8_type(common, backtracks, type == OP_NOT_DIGIT);+ /* Flip the starting bit in the negative case. */+ OP2U(SLJIT_AND | SLJIT_SET_Z, 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:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_space, FALSE))+ read_char7_type(common, backtracks, type == OP_NOT_WHITESPACE);+ else+#endif+ read_char8_type(common, backtracks, type == OP_NOT_WHITESPACE);+ OP2U(SLJIT_AND | SLJIT_SET_Z, 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:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_word, FALSE))+ read_char7_type(common, backtracks, type == OP_NOT_WORDCHAR);+ else+#endif+ read_char8_type(common, backtracks, type == OP_NOT_WORDCHAR);+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_word);+ add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO));+ return cc;++ case OP_ANY:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+ read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR);+ if (common->nltype == NLTYPE_FIXED && common->newline > 255)+ {+ jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);+ end_list = NULL;+ if (common->mode != PCRE2_JIT_PARTIAL_HARD)+ 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);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));+ set_jumps(end_list, LABEL());+ JUMPHERE(jump[0]);+ }+ else+ check_newlinechar(common, common->nltype, backtracks, TRUE);+ return cc;++ case OP_ALLANY:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+#ifdef SUPPORT_UNICODE+ if (common->utf && common->invalid_utf)+ {+ read_char(common, 0, READ_CHAR_MAX, backtracks, READ_CHAR_UPDATE_STR_PTR);+ return cc;+ }+#endif /* SUPPORT_UNICODE */++ skip_valid_char(common);+ return cc;++ case OP_ANYBYTE:+ 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;++#ifdef SUPPORT_UNICODE+ case OP_NOTPROP:+ case OP_PROP:+ propdata[0] = XCL_HASPROP;+ propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;+ 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++ case OP_ANYNL:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+ read_char(common, common->bsr_nlmin, common->bsr_nlmax, NULL, 0);+ 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 != PCRE2_JIT_PARTIAL_HARD)+ 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:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++ if (type == OP_NOT_HSPACE)+ read_char(common, 0x9, 0x3000, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0x9, 0x3000, NULL, 0);++ 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;++ case OP_NOT_VSPACE:+ case OP_VSPACE:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++ if (type == OP_NOT_VSPACE)+ read_char(common, 0xa, 0x2029, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0xa, 0x2029, NULL, 0);++ 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;++#ifdef SUPPORT_UNICODE+ case OP_EXTUNI:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++ SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);+ OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);++#if PCRE2_CODE_UNIT_WIDTH != 32+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM,+ common->utf ? (common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_utf)) : SLJIT_FUNC_ADDR(do_extuni_no_utf));+ if (common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));+#else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM,+ common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_no_utf));+ if (common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));+#endif++ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);++ if (common->mode == PCRE2_JIT_PARTIAL_HARD)+ {+ jump[0] = CMP(SLJIT_LESS, SLJIT_RETURN_REG, 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_CHAR:+ case OP_CHARI:+ length = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);+#endif++ if (check_str_ptr && common->mode != PCRE2_JIT_COMPLETE)+ detect_partial_match(common, backtracks);++ if (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));+ if (length > 1 || (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE))+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));++ context.length = IN_UCHARS(length);+ context.sourcereg = -1;+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ context.ucharptr = 0;+#endif+ return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);+ }++#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+ GETCHAR(c, cc);+ }+ else+#endif+ c = *cc;++ SLJIT_ASSERT(type == OP_CHARI && char_has_othercase(common, cc));++ if (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++ oc = char_othercase(common, c);+ read_char(common, c < oc ? c : oc, c > oc ? c : oc, NULL, 0);++ SLJIT_ASSERT(!is_powerof2(c ^ oc));++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, oc);+ SELECT(SLJIT_EQUAL, TMP1, SLJIT_IMM, c, TMP1);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));+ }+ else+ {+ jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc));+ JUMPHERE(jump[0]);+ }+ return cc + length;++ case OP_NOT:+ case OP_NOTI:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++ length = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ c = *cc;+ if (c < 128 && !common->invalid_utf)+ {+ 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+ {+ /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));+ }+ /* Skip the variable-length character. */+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ JUMPHERE(jump[0]);+ return cc + 1;+ }+ else+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ {+ GETCHARLEN(c, cc, length);+ }+ }+ else+#endif /* SUPPORT_UNICODE */+ c = *cc;++ if (type == OP_NOT || !char_has_othercase(common, cc))+ {+ read_char(common, c, c, backtracks, READ_CHAR_UPDATE_STR_PTR);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));+ }+ else+ {+ oc = char_othercase(common, c);+ read_char(common, c < oc ? c : oc, c > oc ? c : oc, backtracks, READ_CHAR_UPDATE_STR_PTR);+ bit = c ^ oc;+ if (is_powerof2(bit))+ {+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));+ }+ else+ {+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, oc));+ }+ }+ return cc + length;++ case OP_CLASS:+ case OP_NCLASS:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255;+ if (type == OP_NCLASS)+ read_char(common, 0, bit, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0, bit, NULL, 0);+#else+ if (type == OP_NCLASS)+ read_char(common, 0, 255, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0, 255, NULL, 0);+#endif++ if (optimize_class(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks))+ return cc + 32 / sizeof(PCRE2_UCHAR);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ jump[0] = NULL;+ if (common->utf)+ {+ jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, bit);+ if (type == OP_CLASS)+ {+ add_jump(compiler, backtracks, jump[0]);+ jump[0] = NULL;+ }+ }+#elif PCRE2_CODE_UNIT_WIDTH != 8+ jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+ if (type == OP_CLASS)+ {+ add_jump(compiler, backtracks, jump[0]);+ jump[0] = NULL;+ }+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */++ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);+ add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ if (jump[0] != NULL)+ JUMPHERE(jump[0]);+#endif+ return cc + 32 / sizeof(PCRE2_UCHAR);++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ 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+ }+SLJIT_UNREACHABLE();+return cc;+}++static SLJIT_INLINE PCRE2_SPTR compile_charn_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, jump_list **backtracks)+{+/* This function consumes at least one input character. */+/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */+DEFINE_COMPILER;+PCRE2_SPTR ccbegin = cc;+compare_context context;+int size;++context.length = 0;+do+ {+ if (cc >= ccend)+ break;++ if (*cc == OP_CHAR)+ {+ size = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[1]))+ size += GET_EXTRALEN(cc[1]);+#endif+ }+ else if (*cc == OP_CHARI)+ {+ size = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+ if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)+ size = 0;+ else if (HAS_EXTRALEN(cc[1]))+ size += GET_EXTRALEN(cc[1]);+ }+ else+#endif+ if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)+ size = 0;+ }+ else+ size = 0;++ cc += 1 + size;+ context.length += IN_UCHARS(size);+ }+while (size > 0 && context.length <= 128);++cc = ccbegin;+if (context.length > 0)+ {+ /* We have a fixed-length byte sequence. */+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));++ context.sourcereg = -1;+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ context.ucharptr = 0;+#endif+ do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0);+ return cc;+ }++/* A non-fixed length character will be checked if length == 0. */+return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE);+}++/* Forward definitions. */+static void compile_matchingpath(compiler_common *, PCRE2_SPTR, PCRE2_SPTR, backtrack_common *);+static void compile_backtrackingpath(compiler_common *, struct backtrack_common *);++#define PUSH_BACKTRACK(size, ccstart, error) \+ do \+ { \+ backtrack = sljit_alloc_memory(compiler, (size)); \+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \+ return error; \+ memset(backtrack, 0, size); \+ backtrack->prev = parent->top; \+ backtrack->cc = (ccstart); \+ parent->top = backtrack; \+ } \+ while (0)++#define PUSH_BACKTRACK_NOVALUE(size, ccstart) \+ do \+ { \+ backtrack = sljit_alloc_memory(compiler, (size)); \+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \+ return; \+ memset(backtrack, 0, size); \+ backtrack->prev = parent->top; \+ backtrack->cc = (ccstart); \+ parent->top = backtrack; \+ } \+ while (0)++#define BACKTRACK_AS(type) ((type *)backtrack)++static void compile_dnref_search(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)+{+/* The OVECTOR offset goes to TMP2. */+DEFINE_COMPILER;+int count = GET2(cc, 1 + IMM2_SIZE);+PCRE2_SPTR slot = common->name_table + GET2(cc, 1) * common->name_entry_size;+unsigned int offset;+jump_list *found = NULL;++SLJIT_ASSERT(*cc == OP_DNREF || *cc == OP_DNREFI);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));++count--;+while (count-- > 0)+ {+ offset = GET2(slot, 0) << 1;+ GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));+ add_jump(compiler, &found, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0));+ slot += common->name_entry_size;+ }++offset = GET2(slot, 0) << 1;+GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));+if (backtracks != NULL && !common->unset_backref)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0));++set_jumps(found, LABEL());+}++static void compile_ref_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)+{+DEFINE_COMPILER;+BOOL ref = (*cc == OP_REF || *cc == OP_REFI);+int offset = 0;+struct sljit_jump *jump = NULL;+struct sljit_jump *partial;+struct sljit_jump *nopartial;+#if defined SUPPORT_UNICODE+struct sljit_label *loop;+struct sljit_label *caseless_loop;+jump_list *no_match = NULL;+int source_reg = COUNT_MATCH;+int source_end_reg = ARGUMENTS;+int char1_reg = STACK_LIMIT;+#endif /* SUPPORT_UNICODE */++if (ref)+ {+ offset = GET2(cc, 1) << 1;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+ /* OVECTOR(1) contains the "string begin - 1" constant. */+ if (withchecks && !common->unset_backref)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));+ }+else+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);++#if defined SUPPORT_UNICODE+if (common->utf && *cc == OP_REFI)+ {+ SLJIT_ASSERT(common->iref_ptr != 0);++ if (ref)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));++ if (withchecks && emptyfail)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, TMP2, 0));++ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr, source_reg, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw), source_end_reg, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2, char1_reg, 0);++ OP1(SLJIT_MOV, source_reg, 0, TMP1, 0);+ OP1(SLJIT_MOV, source_end_reg, 0, TMP2, 0);++ loop = LABEL();+ jump = CMP(SLJIT_GREATER_EQUAL, source_reg, 0, source_end_reg, 0);+ partial = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++ /* Read original character. It must be a valid UTF character. */+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, source_reg, 0);++ read_char(common, 0, READ_CHAR_MAX, NULL, READ_CHAR_UPDATE_STR_PTR | READ_CHAR_VALID_UTF);++ OP1(SLJIT_MOV, source_reg, 0, STR_PTR, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ OP1(SLJIT_MOV, char1_reg, 0, TMP1, 0);++ /* Read second character. */+ read_char(common, 0, READ_CHAR_MAX, &no_match, READ_CHAR_UPDATE_STR_PTR);++ CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);++ OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);++ add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));++ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);++ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records));++ OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(ucd_record, other_case));+ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(ucd_record, caseset));+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);+ CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);++ add_jump(compiler, &no_match, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0));+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_caseless_sets));++ caseless_loop = LABEL();+ OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(uint32_t));+ OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, TMP1, 0, char1_reg, 0);+ JUMPTO(SLJIT_EQUAL, loop);+ JUMPTO(SLJIT_LESS, caseless_loop);++ set_jumps(no_match, LABEL());+ if (common->mode == PCRE2_JIT_COMPLETE)+ JUMPHERE(partial);++ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));++ if (common->mode != PCRE2_JIT_COMPLETE)+ {+ JUMPHERE(partial);+ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);++ check_partial(common, FALSE);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ }++ JUMPHERE(jump);+ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);+ return;+ }+else+#endif /* SUPPORT_UNICODE */+ {+ if (ref)+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);+ else+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);++ if (withchecks)+ jump = JUMP(SLJIT_ZERO);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+ partial = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);+ if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, backtracks, partial);++ add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));++ if (common->mode != PCRE2_JIT_COMPLETE)+ {+ nopartial = JUMP(SLJIT_JUMP);+ JUMPHERE(partial);+ /* TMP2 -= STR_END - STR_PTR */+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0);+ partial = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);+ add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));+ JUMPHERE(partial);+ check_partial(common, FALSE);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ JUMPHERE(nopartial);+ }+ }++if (jump != NULL)+ {+ if (emptyfail)+ add_jump(compiler, backtracks, jump);+ else+ JUMPHERE(jump);+ }+}++static SLJIT_INLINE PCRE2_SPTR compile_ref_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+BOOL ref = (*cc == OP_REF || *cc == OP_REFI);+backtrack_common *backtrack;+PCRE2_UCHAR type;+int offset = 0;+struct sljit_label *label;+struct sljit_jump *zerolength;+struct sljit_jump *jump = NULL;+PCRE2_SPTR ccbegin = cc;+int min = 0, max = 0;+BOOL minimize;++PUSH_BACKTRACK(sizeof(ref_iterator_backtrack), cc, NULL);++if (ref)+ offset = GET2(cc, 1) << 1;+else+ cc += IMM2_SIZE;+type = cc[1 + IMM2_SIZE];++SLJIT_COMPILE_ASSERT((OP_CRSTAR & 0x1) == 0, crstar_opcode_must_be_even);+minimize = (type & 0x1) != 0;+switch(type)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ min = 0;+ max = 0;+ cc += 1 + IMM2_SIZE + 1;+ break;+ case OP_CRPLUS:+ case OP_CRMINPLUS:+ min = 1;+ max = 0;+ cc += 1 + IMM2_SIZE + 1;+ break;+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ min = 0;+ max = 1;+ cc += 1 + IMM2_SIZE + 1;+ break;+ case OP_CRRANGE:+ case OP_CRMINRANGE:+ min = GET2(cc, 1 + IMM2_SIZE + 1);+ max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE);+ cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;+ break;+ default:+ SLJIT_UNREACHABLE();+ break;+ }++if (!minimize)+ {+ if (min == 0)+ {+ allocate_stack(common, 2);+ if (ref)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+ 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_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)+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ else+ {+ compile_dnref_search(common, ccbegin, NULL);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0);+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ }+ /* Restore if not zero length. */+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));+ }+ else+ {+ allocate_stack(common, 1);+ if (ref)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);++ if (ref)+ {+ if (!common->unset_backref)+ add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ }+ else+ {+ compile_dnref_search(common, ccbegin, &backtrack->own_backtracks);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0);+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ }+ }++ if (min > 1 || max > 1)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, 0);++ label = LABEL();+ if (!ref)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);+ compile_ref_matchingpath(common, ccbegin, &backtrack->own_backtracks, FALSE, FALSE);++ if (min > 1 || max > 1)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0);+ if (min > 1)+ CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, label);+ if (max > 1)+ {+ jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, label);+ JUMPHERE(jump);+ }+ }++ if (max == 0)+ {+ /* Includes min > 1 case as well. */+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, label);+ }++ JUMPHERE(zerolength);+ BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();++ count_match(common);+ return cc;+ }++allocate_stack(common, ref ? 2 : 3);+if (ref)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+if (type != OP_CRMINSTAR)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);++if (min == 0)+ {+ /* 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)+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ else+ {+ compile_dnref_search(common, ccbegin, NULL);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ }+ /* Length is non-zero, we can match real repeats. */+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ jump = JUMP(SLJIT_JUMP);+ }+else+ {+ if (ref)+ {+ if (!common->unset_backref)+ add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ }+ else+ {+ compile_dnref_search(common, ccbegin, &backtrack->own_backtracks);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ }+ }++BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();+if (max > 0)+ add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));++if (!ref)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));+compile_ref_matchingpath(common, ccbegin, &backtrack->own_backtracks, TRUE, TRUE);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);++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(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);++if (jump != NULL)+ JUMPHERE(jump);+JUMPHERE(zerolength);++count_match(common);+return cc;+}++static SLJIT_INLINE PCRE2_SPTR compile_recurse_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+recurse_entry *entry = common->entries;+recurse_entry *prev = NULL;+sljit_sw start = GET(cc, 1);+PCRE2_SPTR start_cc;+BOOL needs_control_head;++PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);++/* Inlining simple patterns. */+if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head) == no_stack)+ {+ start_cc = common->start + start;+ compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack);+ BACKTRACK_AS(recurse_backtrack)->inlined_pattern = TRUE;+ return cc + 1 + LINK_SIZE;+ }++while (entry != NULL)+ {+ if (entry->start == start)+ break;+ prev = entry;+ entry = entry->next;+ }++if (entry == NULL)+ {+ entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;+ entry->next = NULL;+ entry->entry_label = NULL;+ entry->backtrack_label = NULL;+ entry->entry_calls = NULL;+ entry->backtrack_calls = NULL;+ entry->start = start;++ if (prev != NULL)+ prev->next = entry;+ else+ common->entries = entry;+ }++BACKTRACK_AS(recurse_backtrack)->entry = entry;++if (entry->entry_label == NULL)+ add_jump(compiler, &entry->entry_calls, JUMP(SLJIT_FAST_CALL));+else+ JUMPTO(SLJIT_FAST_CALL, entry->entry_label);+/* Leave if the match is failed. */+add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));+BACKTRACK_AS(recurse_backtrack)->matchingpath = LABEL();+return cc + 1 + LINK_SIZE;+}++static sljit_s32 SLJIT_FUNC do_callout_jit(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector)+{+PCRE2_SPTR begin;+PCRE2_SIZE *ovector;+sljit_u32 oveccount, capture_top;++if (arguments->callout == NULL)+ return 0;++SLJIT_COMPILE_ASSERT(sizeof (PCRE2_SIZE) <= sizeof (sljit_sw), pcre2_size_must_be_lower_than_sljit_sw_size);++begin = arguments->begin;+ovector = (PCRE2_SIZE*)(callout_block + 1);+oveccount = callout_block->capture_top;++SLJIT_ASSERT(oveccount >= 1);++callout_block->version = 2;+callout_block->callout_flags = 0;++/* Offsets in subject. */+callout_block->subject_length = arguments->end - arguments->begin;+callout_block->start_match = jit_ovector[0] - begin;+callout_block->current_position = (PCRE2_SPTR)callout_block->offset_vector - begin;+callout_block->subject = begin;++/* Convert and copy the JIT offset vector to the ovector array. */+callout_block->capture_top = 1;+callout_block->offset_vector = ovector;++ovector[0] = PCRE2_UNSET;+ovector[1] = PCRE2_UNSET;+ovector += 2;+jit_ovector += 2;+capture_top = 1;++/* Convert pointers to sizes. */+while (--oveccount != 0)+ {+ capture_top++;++ ovector[0] = (PCRE2_SIZE)(jit_ovector[0] - begin);+ ovector[1] = (PCRE2_SIZE)(jit_ovector[1] - begin);++ if (ovector[0] != PCRE2_UNSET)+ callout_block->capture_top = capture_top;++ ovector += 2;+ jit_ovector += 2;+ }++return (arguments->callout)(callout_block, arguments->callout_data);+}++#define CALLOUT_ARG_OFFSET(arg) \+ SLJIT_OFFSETOF(pcre2_callout_block, arg)++static SLJIT_INLINE PCRE2_SPTR compile_callout_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+sljit_s32 mov_opcode;+unsigned int callout_length = (*cc == OP_CALLOUT)+ ? PRIV(OP_lengths)[OP_CALLOUT] : GET(cc, 1 + 2 * LINK_SIZE);+sljit_sw value1;+sljit_sw value2;+sljit_sw value3;+sljit_uw callout_arg_size = (common->re->top_bracket + 1) * 2 * SSIZE_OF(sw);++PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);++callout_arg_size = (sizeof(pcre2_callout_block) + callout_arg_size + sizeof(sljit_sw) - 1) / sizeof(sljit_sw);++allocate_stack(common, callout_arg_size);++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);+value1 = (*cc == OP_CALLOUT) ? cc[1 + 2 * LINK_SIZE] : 0;+OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, value1);+OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0);+OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_top), SLJIT_IMM, common->re->top_bracket + 1);++/* These pointer sized fields temporarly stores internal variables. */+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(offset_vector), STR_PTR, 0);++if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr));+mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 1));+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 1 + LINK_SIZE));++if (*cc == OP_CALLOUT)+ {+ value1 = 0;+ value2 = 0;+ value3 = 0;+ }+else+ {+ value1 = (sljit_sw) (cc + (1 + 4*LINK_SIZE) + 1);+ value2 = (callout_length - (1 + 4*LINK_SIZE + 2));+ value3 = (sljit_sw) (GET(cc, 1 + 3*LINK_SIZE));+ }++OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string), SLJIT_IMM, value1);+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_length), SLJIT_IMM, value2);+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_offset), SLJIT_IMM, value3);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0);++SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);++/* Needed to save important temporary registers. */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);+/* SLJIT_R0 = arguments */+OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0);+GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START);+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(32, W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_callout_jit));+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+free_stack(common, callout_arg_size);++/* Check return value. */+OP2U(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+add_jump(compiler, &backtrack->own_backtracks, JUMP(SLJIT_SIG_GREATER));+if (common->abort_label == NULL)+ add_jump(compiler, &common->abort, JUMP(SLJIT_NOT_EQUAL) /* SIG_LESS */);+else+ JUMPTO(SLJIT_NOT_EQUAL /* SIG_LESS */, common->abort_label);+return cc + callout_length;+}++#undef CALLOUT_ARG_SIZE+#undef CALLOUT_ARG_OFFSET++static PCRE2_SPTR compile_reverse_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack = NULL;+jump_list **reverse_failed;+unsigned int lmin, lmax;+#ifdef SUPPORT_UNICODE+struct sljit_jump *jump;+struct sljit_label *label;+#endif++SLJIT_ASSERT(parent->top == NULL);++if (*cc == OP_REVERSE)+ {+ reverse_failed = &parent->own_backtracks;+ lmin = GET2(cc, 1);+ lmax = lmin;+ cc += 1 + IMM2_SIZE;++ SLJIT_ASSERT(lmin > 0);+ }+else+ {+ SLJIT_ASSERT(*cc == OP_VREVERSE);+ PUSH_BACKTRACK(sizeof(vreverse_backtrack), cc, NULL);++ reverse_failed = &backtrack->own_backtracks;+ lmin = GET2(cc, 1);+ lmax = GET2(cc, 1 + IMM2_SIZE);+ cc += 1 + 2 * IMM2_SIZE;++ SLJIT_ASSERT(lmin < lmax);+ }++if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ }+else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));++#ifdef SUPPORT_UNICODE+if (common->utf)+ {+ if (lmin > 0)+ {+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, lmin);+ label = LABEL();+ add_jump(compiler, reverse_failed, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0));+ move_back(common, reverse_failed, FALSE);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ }++ if (lmin < lmax)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0);++ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, lmax - lmin);+ label = LABEL();+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);+ move_back(common, reverse_failed, FALSE);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);++ JUMPHERE(jump);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), STR_PTR, 0);+ }+ }+else+#endif+ {+ if (lmin > 0)+ {+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(lmin));+ add_jump(compiler, reverse_failed, CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0));+ }++ if (lmin < lmax)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0);++ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(lmax - lmin));+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, STR_PTR, 0, TMP2, 0);+ SELECT(SLJIT_LESS, STR_PTR, TMP2, 0, STR_PTR);++ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), STR_PTR, 0);+ }+ }++check_start_used_ptr(common);++if (lmin < lmax)+ BACKTRACK_AS(vreverse_backtrack)->matchingpath = LABEL();++return cc;+}++static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(PCRE2_SPTR cc)+{+while (TRUE)+ {+ switch (*cc)+ {+ case OP_CALLOUT_STR:+ cc += GET(cc, 1 + 2*LINK_SIZE);+ break;++ 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:+ case OP_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:+ cc += PRIV(OP_lengths)[*cc];+ break;++ case OP_KET:+ return FALSE;++ default:+ return TRUE;+ }+ }+}++static PCRE2_SPTR compile_assert_matchingpath(compiler_common *common, PCRE2_SPTR cc, assert_backtrack *backtrack, BOOL conditional)+{+DEFINE_COMPILER;+int framesize;+int extrasize;+BOOL local_quit_available = FALSE;+BOOL needs_control_head;+BOOL end_block_size = 0;+BOOL has_vreverse;+int private_data_ptr;+backtrack_common altbacktrack;+PCRE2_SPTR ccbegin;+PCRE2_UCHAR opcode;+PCRE2_UCHAR bra = OP_BRA;+jump_list *tmp = NULL;+jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.own_backtracks;+jump_list **found;+/* Saving previous accept variables. */+BOOL save_local_quit_available = common->local_quit_available;+BOOL save_in_positive_assertion = common->in_positive_assertion;+then_trap_backtrack *save_then_trap = common->then_trap;+struct sljit_label *save_quit_label = common->quit_label;+struct sljit_label *save_accept_label = common->accept_label;+jump_list *save_quit = common->quit;+jump_list *save_positive_assertion_quit = common->positive_assertion_quit;+jump_list *save_accept = common->accept;+struct sljit_jump *jump;+struct sljit_jump *brajump = NULL;++/* Assert captures then. */+common->then_trap = NULL;++if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)+ {+ SLJIT_ASSERT(!conditional);+ bra = *cc;+ cc++;+ }++private_data_ptr = PRIVATE_DATA(cc);+SLJIT_ASSERT(private_data_ptr != 0);+framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);+backtrack->framesize = framesize;+backtrack->private_data_ptr = private_data_ptr;+opcode = *cc;+SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);+found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;+ccbegin = cc;+cc += GET(cc, 1);++if (bra == OP_BRAMINZERO)+ {+ /* This is a braminzero backtrack path. */+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ }++if ((opcode == OP_ASSERTBACK || opcode == OP_ASSERTBACK_NOT) && find_vreverse(ccbegin))+ end_block_size = 3;++if (framesize < 0)+ {+ extrasize = 1;+ if (bra == OP_BRA && !assert_needs_str_ptr_saving(ccbegin + 1 + LINK_SIZE))+ extrasize = 0;++ extrasize += end_block_size;++ if (needs_control_head)+ extrasize++;++ if (framesize == no_frame)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);++ if (extrasize > 0)+ allocate_stack(common, extrasize);++ if (needs_control_head)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);++ if (extrasize > 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);++ if (needs_control_head)+ {+ SLJIT_ASSERT(extrasize == end_block_size + 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(end_block_size + 1), TMP1, 0);+ }+ }+else+ {+ extrasize = (needs_control_head ? 3 : 2) + end_block_size;++ OP1(SLJIT_MOV, TMP2, 0, STACK_TOP, 0);+ allocate_stack(common, framesize + extrasize);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ 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(end_block_size + 2), TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(end_block_size + 1), TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);+ }+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(end_block_size + 1), TMP1, 0);++ init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize);+ }++if (end_block_size > 0)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_END, 0);+ OP1(SLJIT_MOV, STR_END, 0, STR_PTR, 0);+ }++memset(&altbacktrack, 0, sizeof(backtrack_common));+if (conditional || (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT))+ {+ /* Control verbs cannot escape from these asserts. */+ local_quit_available = TRUE;+ common->local_quit_available = TRUE;+ common->quit_label = NULL;+ common->quit = NULL;+ }++common->in_positive_assertion = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK);+common->positive_assertion_quit = NULL;++while (1)+ {+ common->accept_label = NULL;+ common->accept = NULL;+ altbacktrack.top = NULL;+ altbacktrack.own_backtracks = NULL;++ if (*ccbegin == OP_ALT && extrasize > 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));++ altbacktrack.cc = ccbegin;+ ccbegin += 1 + LINK_SIZE;++ has_vreverse = (*ccbegin == OP_VREVERSE);+ if (*ccbegin == OP_REVERSE || has_vreverse)+ ccbegin = compile_reverse_matchingpath(common, ccbegin, &altbacktrack);++ compile_matchingpath(common, ccbegin, cc, &altbacktrack);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ {+ if (local_quit_available)+ {+ common->local_quit_available = save_local_quit_available;+ common->quit_label = save_quit_label;+ common->quit = save_quit;+ }+ common->in_positive_assertion = save_in_positive_assertion;+ common->then_trap = save_then_trap;+ common->accept_label = save_accept_label;+ common->positive_assertion_quit = save_positive_assertion_quit;+ common->accept = save_accept;+ return NULL;+ }++ if (has_vreverse)+ {+ SLJIT_ASSERT(altbacktrack.top != NULL);+ add_jump(compiler, &altbacktrack.top->simple_backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));+ }++ common->accept_label = LABEL();+ if (common->accept != NULL)+ set_jumps(common->accept, common->accept_label);++ /* Reset stack. */+ if (framesize < 0)+ {+ if (framesize == no_frame)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ else if (extrasize > 0)+ free_stack(common, extrasize);++ if (end_block_size > 0)+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize + 1));++ if (needs_control_head)+ 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_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));++ if (end_block_size > 0)+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize + 2));++ if (needs_control_head)+ 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 (end_block_size > 0)+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - extrasize + 1));++ if (needs_control_head)+ 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));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw));+ }+ }++ if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)+ {+ /* We know that STR_PTR was stored on the top of the stack. */+ if (conditional)+ {+ if (extrasize > 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-end_block_size - (needs_control_head ? 2 : 1)));+ }+ else if (bra == OP_BRAZERO)+ {+ if (framesize < 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize));+ else+ {+ 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_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), STACK(-framesize - 1));+ }+ }+ add_jump(compiler, found, JUMP(SLJIT_JUMP));++ compile_backtrackingpath(common, altbacktrack.top);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ {+ if (local_quit_available)+ {+ common->local_quit_available = save_local_quit_available;+ common->quit_label = save_quit_label;+ common->quit = save_quit;+ }+ common->in_positive_assertion = save_in_positive_assertion;+ common->then_trap = save_then_trap;+ common->accept_label = save_accept_label;+ common->positive_assertion_quit = save_positive_assertion_quit;+ common->accept = save_accept;+ return NULL;+ }+ set_jumps(altbacktrack.own_backtracks, LABEL());++ if (*cc != OP_ALT)+ break;++ ccbegin = cc;+ cc += GET(cc, 1);+ }++if (local_quit_available)+ {+ SLJIT_ASSERT(common->positive_assertion_quit == NULL);+ /* Makes the check less complicated below. */+ common->positive_assertion_quit = common->quit;+ }++/* None of them matched. */+if (common->positive_assertion_quit != NULL)+ {+ jump = JUMP(SLJIT_JUMP);+ set_jumps(common->positive_assertion_quit, LABEL());+ SLJIT_ASSERT(framesize != no_stack);+ if (framesize < 0)+ 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_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (extrasize + 1) * sizeof(sljit_sw));+ }+ JUMPHERE(jump);+ }++if (end_block_size > 0)+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(STACK_TOP), STACK(1));++if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(end_block_size + 1));++if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)+ {+ /* Assert is failed. */+ if ((conditional && extrasize > 0) || bra == OP_BRAZERO)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));++ if (framesize < 0)+ {+ /* The topmost item should be 0. */+ if (bra == OP_BRAZERO)+ {+ if (extrasize >= 2)+ free_stack(common, extrasize - 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else if (extrasize > 0)+ free_stack(common, extrasize);+ }+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));+ /* The topmost item should be 0. */+ if (bra == OP_BRAZERO)+ {+ free_stack(common, framesize + extrasize - 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else+ free_stack(common, framesize + extrasize);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }+ jump = JUMP(SLJIT_JUMP);+ if (bra != OP_BRAZERO)+ add_jump(compiler, target, jump);++ /* Assert is successful. */+ set_jumps(tmp, LABEL());+ if (framesize < 0)+ {+ /* We know that STR_PTR was stored on the top of the stack. */+ 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)+ {+ /* This allocation is always successful. */+ 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_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 (bra == OP_BRA)+ {+ /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */+ 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_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + end_block_size + 2) * sizeof(sljit_sw));++ if (extrasize == 2 + end_block_size)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ if (bra == OP_BRAMINZERO)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else+ {+ SLJIT_ASSERT(extrasize == 3 + end_block_size);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0);+ }+ }+ }++ if (bra == OP_BRAZERO)+ {+ backtrack->matchingpath = LABEL();+ SET_LABEL(jump, backtrack->matchingpath);+ }+ else if (bra == OP_BRAMINZERO)+ {+ JUMPTO(SLJIT_JUMP, backtrack->matchingpath);+ JUMPHERE(brajump);+ if (framesize >= 0)+ {+ 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, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }+ set_jumps(backtrack->common.own_backtracks, LABEL());+ }+ }+else+ {+ /* AssertNot is successful. */+ if (framesize < 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, extrasize - 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else if (extrasize > 0)+ free_stack(common, extrasize);+ }+ else+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));+ /* The topmost item should be 0. */+ if (bra != OP_BRA)+ {+ free_stack(common, framesize + extrasize - 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else+ free_stack(common, framesize + extrasize);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }++ if (bra == OP_BRAZERO)+ backtrack->matchingpath = LABEL();+ else if (bra == OP_BRAMINZERO)+ {+ JUMPTO(SLJIT_JUMP, backtrack->matchingpath);+ JUMPHERE(brajump);+ }++ if (bra != OP_BRA)+ {+ SLJIT_ASSERT(found == &backtrack->common.own_backtracks);+ set_jumps(backtrack->common.own_backtracks, LABEL());+ backtrack->common.own_backtracks = NULL;+ }+ }++if (local_quit_available)+ {+ common->local_quit_available = save_local_quit_available;+ common->quit_label = save_quit_label;+ common->quit = save_quit;+ }+common->in_positive_assertion = save_in_positive_assertion;+common->then_trap = save_then_trap;+common->accept_label = save_accept_label;+common->positive_assertion_quit = save_positive_assertion_quit;+common->accept = save_accept;+return cc + 1 + LINK_SIZE;+}++static SLJIT_INLINE void match_once_common(compiler_common *common, PCRE2_UCHAR ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head)+{+DEFINE_COMPILER;+int stacksize;++if (framesize < 0)+ {+ if (framesize == no_frame)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ else+ {+ stacksize = needs_control_head ? 1 : 0;+ if (ket != OP_KET || has_alternatives)+ 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) ? 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), 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), STACK(-1));+ }+ }+else+ {+ stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1;+ 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), STACK(-1));++ if (ket == OP_KETRMAX)+ {+ /* TMP2 which is set here used by OP_KETRMAX below. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ }+ }+if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0);+}++static SLJIT_INLINE int match_capture_common(compiler_common *common, int stacksize, int offset, int private_data_ptr)+{+DEFINE_COMPILER;++if (common->capture_last_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);+ stacksize++;+ }+if (common->optimized_cbracket[offset >> 1] == 0)+ {+ 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), STACK(stacksize), TMP1, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ stacksize += 2;+ }+return stacksize;+}++static PCRE2_SPTR SLJIT_FUNC do_script_run(PCRE2_SPTR ptr, PCRE2_SPTR endptr)+{+ if (PRIV(script_run)(ptr, endptr, FALSE))+ return endptr;+ return NULL;+}++#ifdef SUPPORT_UNICODE++static PCRE2_SPTR SLJIT_FUNC do_script_run_utf(PCRE2_SPTR ptr, PCRE2_SPTR endptr)+{+ if (PRIV(script_run)(ptr, endptr, TRUE))+ return endptr;+ return NULL;+}++#endif /* SUPPORT_UNICODE */++static void match_script_run_common(compiler_common *common, int private_data_ptr, backtrack_common *parent)+{+DEFINE_COMPILER;++SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+#ifdef SUPPORT_UNICODE+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM,+ common->utf ? SLJIT_FUNC_ADDR(do_script_run_utf) : SLJIT_FUNC_ADDR(do_script_run));+#else+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_script_run));+#endif++OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);+add_jump(compiler, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));+}++/*+ Handling bracketed expressions is probably the most complex part.++ Stack layout naming characters:+ S - Push the current STR_PTR+ 0 - Push a 0 (NULL)+ A - Push the current STR_PTR. Needed for restoring the STR_PTR+ before the next alternative. Not pushed if there are no alternatives.+ M - Any values pushed by the current alternative. Can be empty, or anything.+ C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.+ L - Push the previous local (pointed by localptr) to the stack+ () - opional values stored on the stack+ ()* - optonal, can be stored multiple times++ The following list shows the regular expression templates, their PCRE byte codes+ and stack layout supported by pcre-sljit.++ (?:) OP_BRA | OP_KET A M+ () OP_CBRA | OP_KET C M+ (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*+ OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*+ (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*+ OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*+ ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*+ OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*+ ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*+ OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*+ (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )+ (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )+ ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )+ ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )+ (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*+ OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*+ (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*+ OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*+ ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*+ OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*+ ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*+ OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*+++ Stack layout naming characters:+ A - Push the alternative index (starting from 0) on the stack.+ Not pushed if there is no alternatives.+ M - Any values pushed by the current alternative. Can be empty, or anything.++ The next list shows the possible content of a bracket:+ (|) OP_*BRA | OP_ALT ... M A+ (?()|) OP_*COND | OP_ALT M A+ (?>|) OP_ONCE | OP_ALT ... [stack trace] M A+ Or nothing, if trace is unnecessary+*/++static PCRE2_SPTR compile_bracket_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+PCRE2_UCHAR opcode;+int private_data_ptr = 0;+int offset = 0;+int i, stacksize;+int repeat_ptr = 0, repeat_length = 0;+int repeat_type = 0, repeat_count = 0;+PCRE2_SPTR ccbegin;+PCRE2_SPTR matchingpath;+PCRE2_SPTR slot;+PCRE2_UCHAR bra = OP_BRA;+PCRE2_UCHAR ket;+assert_backtrack *assert;+BOOL has_alternatives;+BOOL needs_control_head = FALSE;+BOOL has_vreverse = FALSE;+struct sljit_jump *jump;+struct sljit_jump *skip;+struct sljit_label *rmax_label = NULL;+struct sljit_jump *braminzero = NULL;++PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);++if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)+ {+ bra = *cc;+ cc++;+ opcode = *cc;+ }++opcode = *cc;+ccbegin = cc;+matchingpath = bracketend(cc) - 1 - LINK_SIZE;+ket = *matchingpath;+if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0)+ {+ repeat_ptr = PRIVATE_DATA(matchingpath);+ repeat_length = PRIVATE_DATA(matchingpath + 1);+ repeat_type = PRIVATE_DATA(matchingpath + 2);+ repeat_count = PRIVATE_DATA(matchingpath + 3);+ SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0);+ if (repeat_type == OP_UPTO)+ ket = OP_KETRMAX;+ if (repeat_type == OP_MINUPTO)+ ket = OP_KETRMIN;+ }++matchingpath = ccbegin + 1 + LINK_SIZE;+SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);+SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));+cc += GET(cc, 1);++has_alternatives = *cc == OP_ALT;+if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND))+ {+ SLJIT_COMPILE_ASSERT(OP_DNRREF == OP_RREF + 1 && OP_FALSE == OP_RREF + 2 && OP_TRUE == OP_RREF + 3,+ compile_time_checks_must_be_grouped_together);+ has_alternatives = ((*matchingpath >= OP_RREF && *matchingpath <= OP_TRUE) || *matchingpath == OP_FAIL) ? FALSE : TRUE;+ }++if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))+ opcode = OP_SCOND;++if (opcode == OP_CBRA || opcode == OP_SCBRA)+ {+ /* Capturing brackets has a pre-allocated space. */+ offset = GET2(ccbegin, 1 + LINK_SIZE);+ if (common->optimized_cbracket[offset] == 0)+ {+ private_data_ptr = OVECTOR_PRIV(offset);+ offset <<= 1;+ }+ else+ {+ offset <<= 1;+ private_data_ptr = OVECTOR(offset);+ }+ BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;+ matchingpath += IMM2_SIZE;+ }+else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_ONCE || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)+ {+ /* Other brackets simply allocate the next entry. */+ private_data_ptr = PRIVATE_DATA(ccbegin);+ SLJIT_ASSERT(private_data_ptr != 0);+ BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;+ if (opcode == OP_ONCE)+ BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, NULL, FALSE, &needs_control_head);+ }++/* Instructions before the first alternative. */+stacksize = 0;+if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))+ stacksize++;+if (bra == OP_BRAZERO)+ stacksize++;++if (stacksize > 0)+ allocate_stack(common, stacksize);++stacksize = 0;+if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);+ stacksize++;+ }++if (bra == OP_BRAZERO)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);++if (bra == OP_BRAMINZERO)+ {+ /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ if (ket != OP_KETRMIN)+ {+ free_stack(common, 1);+ braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ }+ else if (opcode == OP_ONCE || opcode >= OP_SBRA)+ {+ jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ /* Nothing stored during the first run. */+ skip = JUMP(SLJIT_JUMP);+ JUMPHERE(jump);+ /* Checking zero-length iteration. */+ if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)+ {+ /* When we come from outside, private_data_ptr contains the previous STR_PTR. */+ braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ }+ else+ {+ /* 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), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2));+ }+ JUMPHERE(skip);+ }+ else+ {+ jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ JUMPHERE(jump);+ }+ }++if (repeat_type != 0)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, repeat_count);+ if (repeat_type == OP_EXACT)+ rmax_label = LABEL();+ }++if (ket == OP_KETRMIN)+ BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();++if (ket == OP_KETRMAX)+ {+ rmax_label = LABEL();+ if (has_alternatives && opcode >= OP_BRA && opcode < OP_SBRA && repeat_type == 0)+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label;+ }++/* Handling capturing brackets and alternatives. */+if (opcode == OP_ONCE)+ {+ stacksize = 0;+ if (needs_control_head)+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ stacksize++;+ }++ if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)+ {+ /* Neither capturing brackets nor recursions are found in the block. */+ if (ket == OP_KETRMIN)+ {+ stacksize += 2;+ if (!needs_control_head)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ }+ else+ {+ if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);+ if (ket == OP_KETRMAX || has_alternatives)+ stacksize++;+ }++ if (stacksize > 0)+ allocate_stack(common, stacksize);++ stacksize = 0;+ if (needs_control_head)+ {+ stacksize++;+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ }++ if (ket == OP_KETRMIN)+ {+ if (needs_control_head)+ 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_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)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);+ }+ else+ {+ if (ket != OP_KET || has_alternatives)+ stacksize++;++ stacksize += BACKTRACK_AS(bracket_backtrack)->u.framesize + 1;+ allocate_stack(common, stacksize);++ if (needs_control_head)+ 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_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));++ stacksize = needs_control_head ? 1 : 0;+ if (ket != OP_KET || has_alternatives)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);+ stacksize++;+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);+ }+ else+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);+ }+ init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1);+ }+ }+else if (opcode == OP_CBRA || opcode == OP_SCBRA)+ {+ /* Saving the previous values. */+ if (common->optimized_cbracket[offset >> 1] != 0)+ {+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset));+ allocate_stack(common, 2);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ }+ }+else if (opcode == OP_ASSERTBACK_NA && PRIVATE_DATA(ccbegin + 1))+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ allocate_stack(common, 4);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw), STR_END, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);+ OP1(SLJIT_MOV, STR_END, 0, STR_PTR, 0);++ has_vreverse = (*matchingpath == OP_VREVERSE);+ if (*matchingpath == OP_REVERSE || has_vreverse)+ matchingpath = compile_reverse_matchingpath(common, matchingpath, backtrack);+ }+else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)+ {+ /* Saving the previous value. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);++ if (*matchingpath == OP_REVERSE)+ matchingpath = compile_reverse_matchingpath(common, matchingpath, backtrack);+ }+else if (has_alternatives)+ {+ /* Pushing the starting string pointer. */+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ }++/* Generating code for the first alternative. */+if (opcode == OP_COND || opcode == OP_SCOND)+ {+ if (*matchingpath == OP_CREF)+ {+ SLJIT_ASSERT(has_alternatives);+ add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed),+ CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));+ matchingpath += 1 + IMM2_SIZE;+ }+ else if (*matchingpath == OP_DNCREF)+ {+ SLJIT_ASSERT(has_alternatives);++ i = GET2(matchingpath, 1 + IMM2_SIZE);+ 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_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_Z, TMP2, 0, TMP2, 0, STR_PTR, 0);+ slot += common->name_entry_size;+ }+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_ZERO));+ matchingpath += 1 + 2 * IMM2_SIZE;+ }+ else if ((*matchingpath >= OP_RREF && *matchingpath <= OP_TRUE) || *matchingpath == OP_FAIL)+ {+ /* Never has other case. */+ BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;+ SLJIT_ASSERT(!has_alternatives);++ if (*matchingpath == OP_TRUE)+ {+ stacksize = 1;+ matchingpath++;+ }+ else if (*matchingpath == OP_FALSE || *matchingpath == OP_FAIL)+ stacksize = 0;+ else if (*matchingpath == OP_RREF)+ {+ stacksize = GET2(matchingpath, 1);+ if (common->currententry == NULL)+ stacksize = 0;+ else if (stacksize == RREF_ANY)+ stacksize = 1;+ else if (common->currententry->start == 0)+ stacksize = stacksize == 0;+ else+ stacksize = stacksize == (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);++ if (stacksize != 0)+ matchingpath += 1 + IMM2_SIZE;+ }+ else+ {+ if (common->currententry == NULL || common->currententry->start == 0)+ stacksize = 0;+ else+ {+ stacksize = GET2(matchingpath, 1 + IMM2_SIZE);+ slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;+ i = (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);+ while (stacksize > 0)+ {+ if ((int)GET2(slot, 0) == i)+ break;+ slot += common->name_entry_size;+ stacksize--;+ }+ }++ if (stacksize != 0)+ matchingpath += 1 + 2 * IMM2_SIZE;+ }++ /* The stacksize == 0 is a common "else" case. */+ if (stacksize == 0)+ {+ if (*cc == OP_ALT)+ {+ matchingpath = cc + 1 + LINK_SIZE;+ cc += GET(cc, 1);+ }+ else+ matchingpath = cc;+ }+ }+ else+ {+ SLJIT_ASSERT(has_alternatives && *matchingpath >= OP_ASSERT && *matchingpath <= OP_ASSERTBACK_NOT);+ /* Similar code as PUSH_BACKTRACK macro. */+ assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack));+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;+ memset(assert, 0, sizeof(assert_backtrack));+ assert->common.cc = matchingpath;+ BACKTRACK_AS(bracket_backtrack)->u.assert = assert;+ matchingpath = compile_assert_matchingpath(common, matchingpath, assert, TRUE);+ }+ }++compile_matchingpath(common, matchingpath, cc, backtrack);+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;++switch (opcode)+ {+ case OP_ASSERTBACK_NA:+ if (has_vreverse)+ {+ SLJIT_ASSERT(backtrack->top != NULL && PRIVATE_DATA(ccbegin + 1));+ add_jump(compiler, &backtrack->top->simple_backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));+ }++ if (PRIVATE_DATA(ccbegin + 1))+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw));+ break;+ case OP_ASSERT_NA:+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ break;+ case OP_ONCE:+ match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);+ break;+ case OP_SCRIPT_RUN:+ match_script_run_common(common, private_data_ptr, backtrack);+ break;+ }++stacksize = 0;+if (repeat_type == OP_MINUPTO)+ {+ /* We need to preserve the counter. TMP2 will be used below. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);+ stacksize++;+ }+if (ket != OP_KET || bra != OP_BRA)+ stacksize++;+if (offset != 0)+ {+ if (common->capture_last_ptr != 0)+ stacksize++;+ if (common->optimized_cbracket[offset >> 1] == 0)+ stacksize += 2;+ }+if (has_alternatives && opcode != OP_ONCE)+ stacksize++;++if (stacksize > 0)+ allocate_stack(common, stacksize);++stacksize = 0;+if (repeat_type == OP_MINUPTO)+ {+ /* TMP2 was set above. */+ OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);+ stacksize++;+ }++if (ket != OP_KET || bra != OP_BRA)+ {+ if (ket != OP_KET)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);+ stacksize++;+ }++if (offset != 0)+ stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);++/* Skip and count the other alternatives. */+i = 1;+while (*cc == OP_ALT)+ {+ cc += GET(cc, 1);+ i++;+ }++if (has_alternatives)+ {+ if (opcode != OP_ONCE)+ {+ if (i <= 3)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);+ else+ BACKTRACK_AS(bracket_backtrack)->u.matching_mov_addr = sljit_emit_mov_addr(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));+ }+ if (ket != OP_KETRMAX)+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();+ }++/* Must be after the matchingpath label. */+if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0)+ {+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+ }++if (ket == OP_KETRMAX)+ {+ if (repeat_type != 0)+ {+ if (has_alternatives)+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();+ 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)+ free_stack(common, 1);+ }+ else if (opcode < OP_BRA || opcode >= OP_SBRA)+ {+ if (has_alternatives)+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();++ /* Checking zero-length iteration. */+ if (opcode != OP_ONCE)+ {+ /* This case includes opcodes such as OP_SCRIPT_RUN. */+ CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0, rmax_label);+ /* Drop STR_PTR for greedy plus quantifier. */+ if (bra != OP_BRAZERO)+ free_stack(common, 1);+ }+ else+ /* TMP2 must contain the starting STR_PTR. */+ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label);+ }+ else+ JUMPTO(SLJIT_JUMP, rmax_label);+ BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();+ }++if (repeat_type == OP_EXACT)+ {+ count_match(common);+ 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)+ {+ /* We need to preserve the counter. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ }++if (bra == OP_BRAZERO)+ BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();++if (bra == OP_BRAMINZERO)+ {+ /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */+ JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath);+ if (braminzero != NULL)+ {+ JUMPHERE(braminzero);+ /* We need to release the end pointer to perform the+ backtrack for the zero-length iteration. When+ framesize is < 0, OP_ONCE will do the release itself. */+ if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0)+ {+ 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, (BACKTRACK_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw));+ }+ else if (ket == OP_KETRMIN && opcode != OP_ONCE)+ free_stack(common, 1);+ }+ /* Continue to the normal backtrack. */+ }++if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO || (has_alternatives && repeat_type != OP_EXACT))+ count_match(common);++cc += 1 + LINK_SIZE;++if (opcode == OP_ONCE)+ {+ int data;+ int framesize = BACKTRACK_AS(bracket_backtrack)->u.framesize;++ SLJIT_ASSERT(SHRT_MIN <= framesize && framesize < SHRT_MAX/2);+ /* We temporarily encode the needs_control_head in the lowest bit.+ The real value should be short enough for this operation to work+ without triggering Undefined Behaviour. */+ data = (int)((short)((unsigned short)framesize << 1) | (needs_control_head ? 1 : 0));+ BACKTRACK_AS(bracket_backtrack)->u.framesize = data;+ }+return cc + repeat_length;+}++static PCRE2_SPTR compile_bracketpos_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+PCRE2_UCHAR opcode;+int private_data_ptr;+int cbraprivptr = 0;+BOOL needs_control_head;+int framesize;+int stacksize;+int offset = 0;+BOOL zero = FALSE;+PCRE2_SPTR ccbegin = NULL;+int stack; /* Also contains the offset of control head. */+struct sljit_label *loop = NULL;+struct jump_list *emptymatch = NULL;++PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL);+if (*cc == OP_BRAPOSZERO)+ {+ zero = TRUE;+ cc++;+ }++opcode = *cc;+private_data_ptr = PRIVATE_DATA(cc);+SLJIT_ASSERT(private_data_ptr != 0);+BACKTRACK_AS(bracketpos_backtrack)->private_data_ptr = private_data_ptr;+switch(opcode)+ {+ case OP_BRAPOS:+ case OP_SBRAPOS:+ ccbegin = cc + 1 + LINK_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ offset = GET2(cc, 1 + LINK_SIZE);+ /* This case cannot be optimized in the same way as+ normal capturing brackets. */+ SLJIT_ASSERT(common->optimized_cbracket[offset] == 0);+ cbraprivptr = OVECTOR_PRIV(offset);+ offset <<= 1;+ ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);+BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize;+if (framesize < 0)+ {+ if (offset != 0)+ {+ stacksize = 2;+ if (common->capture_last_ptr != 0)+ stacksize++;+ }+ else+ stacksize = 1;++ if (needs_control_head)+ stacksize++;+ if (!zero)+ stacksize++;++ BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;+ allocate_stack(common, stacksize);+ if (framesize == no_frame)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);++ stack = 0;+ if (offset != 0)+ {+ stack = 2;+ 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), STACK(0), TMP1, 0);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);+ if (needs_control_head)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ if (common->capture_last_ptr != 0)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);+ stack = 3;+ }+ }+ else+ {+ 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);+ stack = 1;+ }++ if (needs_control_head)+ stack++;+ if (!zero)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), SLJIT_IMM, 1);+ if (needs_control_head)+ {+ stack--;+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);+ }+ }+else+ {+ stacksize = framesize + 1;+ if (!zero)+ stacksize++;+ if (needs_control_head)+ stacksize++;+ if (offset == 0)+ stacksize++;+ BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;++ allocate_stack(common, stacksize);+ 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_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));++ stack = 0;+ if (!zero)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);+ stack = 1;+ }+ if (needs_control_head)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);+ stack++;+ }+ if (offset == 0)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);+ stack++;+ }+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);+ init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize);+ stack -= 1 + (offset == 0);+ }++if (offset != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);++loop = LABEL();+while (*cc != OP_KETRPOS)+ {+ backtrack->top = NULL;+ backtrack->own_backtracks = NULL;+ cc += GET(cc, 1);++ compile_matchingpath(common, ccbegin, cc, backtrack);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;++ if (framesize < 0)+ {+ if (framesize == no_frame)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);++ if (offset != 0)+ {+ 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);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ }+ else+ {+ if (opcode == OP_SBRAPOS)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ }++ /* Even if the match is empty, we need to reset the control head. */+ if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));++ if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)+ add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));++ if (!zero)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);+ }+ else+ {+ if (offset != 0)+ {+ 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);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ 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), 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. */+ if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));++ if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)+ add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));++ if (!zero)+ {+ if (framesize < 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ }++ JUMPTO(SLJIT_JUMP, loop);+ flush_stubs(common);++ compile_backtrackingpath(common, backtrack->top);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;+ set_jumps(backtrack->own_backtracks, LABEL());++ if (framesize < 0)+ {+ if (offset != 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);+ else+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ }+ else+ {+ if (offset != 0)+ {+ /* Last alternative. */+ if (*cc == OP_KETRPOS)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));+ }+ }++ if (*cc == OP_KETRPOS)+ break;+ ccbegin = cc + 1 + LINK_SIZE;+ }++/* We don't have to restore the control head in case of a failed match. */++backtrack->own_backtracks = NULL;+if (!zero)+ {+ if (framesize < 0)+ add_jump(compiler, &backtrack->own_backtracks, 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->own_backtracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), STACK(-stacksize), SLJIT_IMM, 0));+ }++/* None of them matched. */+set_jumps(emptymatch, LABEL());+count_match(common);+return cc + 1 + LINK_SIZE;+}++static SLJIT_INLINE PCRE2_SPTR get_iterator_parameters(compiler_common *common, PCRE2_SPTR cc, PCRE2_UCHAR *opcode, PCRE2_UCHAR *type, sljit_u32 *max, sljit_u32 *exact, PCRE2_SPTR *end)+{+int class_len;++*opcode = *cc;+*exact = 0;++if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)+ {+ cc++;+ *type = OP_CHAR;+ }+else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI)+ {+ cc++;+ *type = OP_CHARI;+ *opcode -= OP_STARI - OP_STAR;+ }+else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO)+ {+ cc++;+ *type = OP_NOT;+ *opcode -= OP_NOTSTAR - OP_STAR;+ }+else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI)+ {+ cc++;+ *type = OP_NOTI;+ *opcode -= OP_NOTSTARI - OP_STAR;+ }+else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)+ {+ cc++;+ *opcode -= OP_TYPESTAR - OP_STAR;+ *type = OP_END;+ }+else+ {+ SLJIT_ASSERT(*opcode == OP_CLASS || *opcode == OP_NCLASS || *opcode == OP_XCLASS);+ *type = *opcode;+ cc++;+ class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(PCRE2_UCHAR))) : GET(cc, 0);+ *opcode = cc[class_len - 1];++ if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)+ {+ *opcode -= OP_CRSTAR - OP_STAR;+ *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;+ *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));+ *exact = GET2(cc, class_len);++ if (*max == 0)+ {+ if (*opcode == OP_CRPOSRANGE)+ *opcode = OP_POSSTAR;+ else+ *opcode -= OP_CRRANGE - OP_STAR;+ }+ 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;+ }++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 == OP_END)+ {+ *type = *cc;+ *end = next_opcode(common, cc);+ cc++;+ return cc;+ }++*end = cc + 1;+#ifdef SUPPORT_UNICODE+if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);+#endif+return cc;+}++static PCRE2_SPTR compile_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+PCRE2_UCHAR opcode;+PCRE2_UCHAR type;+sljit_u32 max = 0, exact;+sljit_s32 early_fail_ptr = PRIVATE_DATA(cc + 1);+sljit_s32 early_fail_type;+BOOL charpos_enabled;+PCRE2_UCHAR charpos_char;+unsigned int charpos_othercasebit;+PCRE2_SPTR 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 + SSIZE_OF(sw);+int tmp_base, tmp_offset;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+BOOL use_tmp;+#endif++PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL);++early_fail_type = (early_fail_ptr & 0x7);+early_fail_ptr >>= 3;++/* During recursion, these optimizations are disabled. */+if (common->early_fail_start_ptr == 0 && common->fast_forward_bc_ptr == NULL)+ {+ early_fail_ptr = 0;+ early_fail_type = type_skip;+ }++SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || early_fail_ptr == 0+ || (early_fail_ptr >= common->early_fail_start_ptr && early_fail_ptr <= common->early_fail_end_ptr));++if (early_fail_type == type_fail)+ add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), early_fail_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;+ }++/* Handle fixed part first. */+if (exact > 1)+ {+ SLJIT_ASSERT(early_fail_ptr == 0);++ if (common->mode == PCRE2_JIT_COMPLETE+#ifdef SUPPORT_UNICODE+ && !common->utf+#endif+ && type != OP_ANYNL && type != OP_EXTUNI)+ {+ OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact));+ add_jump(compiler, &backtrack->own_backtracks, 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->own_backtracks, 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->own_backtracks, 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->own_backtracks, TRUE);++if (early_fail_type == type_fail_range)+ {+ /* Range end first, followed by range start. */+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + SSIZE_OF(sw));+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, TMP2, 0);+ OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, TMP2, 0);+ add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_LESS_EQUAL, TMP2, 0, TMP1, 0));++ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + SSIZE_OF(sw), STR_PTR, 0);+ }++switch(opcode)+ {+ case OP_STAR:+ case OP_UPTO:+ SLJIT_ASSERT(early_fail_ptr == 0 || opcode == OP_STAR);++ if (type == OP_ANYNL || type == OP_EXTUNI)+ {+ SLJIT_ASSERT(private_data_ptr == 0);+ SLJIT_ASSERT(early_fail_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)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, max);++ label = LABEL();+ 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_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);+ }++ /* We cannot use TMP3 because of allocate_stack. */+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, label);+ if (jump != NULL)+ JUMPHERE(jump);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;+ }+#ifdef SUPPORT_UNICODE+ else if (type == OP_ALLANY && !common->invalid_utf)+#else+ else if (type == OP_ALLANY)+#endif+ {+ if (opcode == OP_STAR)+ {+ if (private_data_ptr == 0)+ allocate_stack(common, 2);++ OP1(SLJIT_MOV, base, offset0, STR_END, 0);+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);++ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);+ process_partial_match(common);++ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_END, 0);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;+ }+#ifdef SUPPORT_UNICODE+ else if (!common->utf)+#else+ else+#endif+ {+ if (private_data_ptr == 0)+ allocate_stack(common, 2);++ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));++ if (common->mode == PCRE2_JIT_COMPLETE)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);+ SELECT(SLJIT_GREATER, STR_PTR, STR_END, 0, STR_PTR);+ }+ else+ {+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);+ process_partial_match(common);+ JUMPHERE(jump);+ }++ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);++ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;+ }+ }++ charpos_enabled = FALSE;+ charpos_char = 0;+ charpos_othercasebit = 0;++ if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))+ {+#ifdef SUPPORT_UNICODE+ charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);+#else+ charpos_enabled = TRUE;+#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];+ /* Consume the OP_CHAR opcode. */+ end += 2;+#if PCRE2_CODE_UNIT_WIDTH == 8+ SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ 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->own_backtracks, JUMP(SLJIT_ZERO));+ }+ compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, FALSE);+ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ JUMPHERE(jump);++ detect_partial_match(common, &backtrack->own_backtracks);+ 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);++ 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 (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_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);+ JUMPTO(SLJIT_JUMP, label);+ }+ else+ {+ jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ JUMPHERE(jump);+ 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());+ OP2(SLJIT_ADD, STR_PTR, 0, base, offset0, SLJIT_IMM, IN_UCHARS(1));+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ }+ else+ {+ if (private_data_ptr == 0)+ allocate_stack(common, 2);++ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ use_tmp = (!HAS_VIRTUAL_REGISTERS && opcode == OP_STAR);+ SLJIT_ASSERT(!use_tmp || tmp_base == TMP3);++ if (common->utf)+ OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0);+#endif+ if (opcode == OP_UPTO)+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);++ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0);+#endif++ 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));+ }++ detect_partial_match_to(common, label);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ set_jumps(no_char1_match, LABEL());+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ {+ set_jumps(no_match, LABEL());+ if (use_tmp)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ OP1(SLJIT_MOV, base, offset0, TMP3, 0);+ }+ else+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ }+ else+#endif+ {+ 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 (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ }++ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;++ case OP_MINSTAR:+ if (private_data_ptr == 0)+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ break;++ case OP_MINUPTO:+ SLJIT_ASSERT(early_fail_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, max + 1);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;++ case OP_QUERY:+ case OP_MINQUERY:+ SLJIT_ASSERT(early_fail_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_AS(char_iterator_backtrack)->u.backtracks, TRUE);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;++ case OP_EXACT:+ break;++ case OP_POSSTAR:+#if defined SUPPORT_UNICODE+ if (type == OP_ALLANY && !common->invalid_utf)+#else+ if (type == OP_ALLANY)+#endif+ {+ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);+ process_partial_match(common);+ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_END, 0);+ break;+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (type == OP_EXTUNI || common->utf)+ {+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);+ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);+ detect_partial_match_to(common, label);++ set_jumps(no_match, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);+ if (early_fail_ptr != 0)+ {+ if (!HAS_VIRTUAL_REGISTERS && tmp_base == TMP3)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, TMP3, 0);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ }+ break;+ }+#endif++ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);+ detect_partial_match_to(common, 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());+ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ break;++ case OP_POSUPTO:+ SLJIT_ASSERT(early_fail_ptr == 0);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);++ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);+ 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);+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));+ detect_partial_match_to(common, label);++ set_jumps(no_match, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);+ break;+ }+#endif++ if (type == OP_ALLANY)+ {+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));++ if (common->mode == PCRE2_JIT_COMPLETE)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);+ SELECT(SLJIT_GREATER, STR_PTR, STR_END, 0, STR_PTR);+ }+ else+ {+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);+ process_partial_match(common);+ JUMPHERE(jump);+ }+ break;+ }++ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);++ detect_partial_match(common, &no_match);+ label = LABEL();+ 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);+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));+ detect_partial_match_to(common, 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;++ case OP_POSQUERY:+ SLJIT_ASSERT(early_fail_ptr == 0);+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);+ compile_char1_matchingpath(common, type, cc, &no_match, TRUE);+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);+ set_jumps(no_match, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++count_match(common);+return end;+}++static SLJIT_INLINE PCRE2_SPTR compile_fail_accept_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;++PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);++if (*cc == OP_FAIL)+ {+ add_jump(compiler, &backtrack->own_backtracks, JUMP(SLJIT_JUMP));+ return cc + 1;+ }++if (*cc == OP_ACCEPT && common->currententry == NULL && (common->re->overall_options & PCRE2_ENDANCHORED) != 0)+ add_jump(compiler, &common->restart_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0));++if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL || !common->might_be_empty)+ {+ /* No need to check notempty conditions. */+ if (common->accept_label == NULL)+ add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));+ else+ JUMPTO(SLJIT_JUMP, common->accept_label);+ return cc + 1;+ }++if (common->accept_label == NULL)+ add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)));+else+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label);++if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));+ }+else+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options));++OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);+add_jump(compiler, &backtrack->own_backtracks, JUMP(SLJIT_NOT_ZERO));+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);+if (common->accept_label == NULL)+ add_jump(compiler, &common->accept, JUMP(SLJIT_ZERO));+else+ JUMPTO(SLJIT_ZERO, common->accept_label);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));+if (common->accept_label == NULL)+ add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0));+else+ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->accept_label);+add_jump(compiler, &backtrack->own_backtracks, JUMP(SLJIT_JUMP));+return cc + 1;+}++static SLJIT_INLINE PCRE2_SPTR compile_close_matchingpath(compiler_common *common, PCRE2_SPTR cc)+{+DEFINE_COMPILER;+int offset = GET2(cc, 1);+BOOL optimized_cbracket = common->optimized_cbracket[offset] != 0;++/* Data will be discarded anyway... */+if (common->currententry != NULL)+ return cc + 1 + IMM2_SIZE;++if (!optimized_cbracket)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR_PRIV(offset));+offset <<= 1;+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+if (!optimized_cbracket)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+return cc + 1 + IMM2_SIZE;+}++static SLJIT_INLINE PCRE2_SPTR compile_control_verb_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+PCRE2_UCHAR opcode = *cc;+PCRE2_SPTR ccend = cc + 1;++if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG ||+ opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)+ ccend += 2 + cc[1];++PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);++if (opcode == OP_SKIP)+ {+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ return ccend;+ }++if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)+ {+ if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);+ }++return ccend;+}++static PCRE2_UCHAR then_trap_opcode[1] = { OP_THEN_TRAP };++static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+BOOL needs_control_head;+int size;++PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);+common->then_trap = BACKTRACK_AS(then_trap_backtrack);+BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;+BACKTRACK_AS(then_trap_backtrack)->start = (sljit_sw)(cc - common->start);+BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head);++size = BACKTRACK_AS(then_trap_backtrack)->framesize;+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_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);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0);++size = BACKTRACK_AS(then_trap_backtrack)->framesize;+if (size >= 0)+ init_frame(common, cc, ccend, size - 1, 0);+}++static void compile_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+BOOL has_then_trap = FALSE;+then_trap_backtrack *save_then_trap = NULL;++SLJIT_ASSERT(*ccend == OP_END || (*ccend >= OP_ALT && *ccend <= OP_KETRPOS));++if (common->has_then && common->then_offsets[cc - common->start] != 0)+ {+ SLJIT_ASSERT(*ccend != OP_END && common->control_head_ptr != 0);+ has_then_trap = TRUE;+ save_then_trap = common->then_trap;+ /* Tail item on backtrack. */+ compile_then_trap_matchingpath(common, cc, ccend, parent);+ }++while (cc < ccend)+ {+ switch(*cc)+ {+ case OP_SOD:+ 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_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:+ cc = compile_simple_assertion_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks);+ break;++ 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_NOTPROP:+ case OP_PROP:+ case OP_ANYNL:+ case OP_NOT_HSPACE:+ case OP_HSPACE:+ case OP_NOT_VSPACE:+ case OP_VSPACE:+ case OP_EXTUNI:+ case OP_NOT:+ case OP_NOTI:+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, TRUE);+ break;++ case OP_SET_SOM:+ PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ cc++;+ break;++ case OP_CHAR:+ case OP_CHARI:+ if (common->mode == PCRE2_JIT_COMPLETE)+ cc = compile_charn_matchingpath(common, cc, ccend, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks);+ else+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, TRUE);+ break;++ case OP_STAR:+ case OP_MINSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:+ case OP_STARI:+ case OP_MINSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:+ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:+ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ case OP_TYPEPOSUPTO:+ cc = compile_iterator_matchingpath(common, cc, parent);+ break;++ case OP_CLASS:+ case OP_NCLASS:+ if (cc[1 + (32 / sizeof(PCRE2_UCHAR))] >= OP_CRSTAR && cc[1 + (32 / sizeof(PCRE2_UCHAR))] <= OP_CRPOSRANGE)+ cc = compile_iterator_matchingpath(common, cc, parent);+ else+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, TRUE);+ break;++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ case OP_XCLASS:+ 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->simple_backtracks : &parent->own_backtracks, TRUE);+ break;+#endif++ case OP_REF:+ case OP_REFI:+ if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRPOSRANGE)+ cc = compile_ref_iterator_matchingpath(common, cc, parent);+ else+ {+ compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, TRUE, FALSE);+ cc += 1 + IMM2_SIZE;+ }+ break;++ case OP_DNREF:+ case OP_DNREFI:+ if (cc[1 + 2 * IMM2_SIZE] >= OP_CRSTAR && cc[1 + 2 * IMM2_SIZE] <= OP_CRPOSRANGE)+ cc = compile_ref_iterator_matchingpath(common, cc, parent);+ else+ {+ compile_dnref_search(common, cc, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks);+ compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, TRUE, FALSE);+ cc += 1 + 2 * IMM2_SIZE;+ }+ break;++ case OP_RECURSE:+ cc = compile_recurse_matchingpath(common, cc, parent);+ break;++ case OP_CALLOUT:+ case OP_CALLOUT_STR:+ cc = compile_callout_matchingpath(common, cc, parent);+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);+ cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);+ break;++ case OP_BRAMINZERO:+ PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc);+ cc = bracketend(cc + 1);+ if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)+ {+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ }+ else+ {+ allocate_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);+ }+ BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL();+ count_match(common);+ break;++ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRA:+ case OP_CBRA:+ case OP_COND:+ case OP_SBRA:+ case OP_SCBRA:+ case OP_SCOND:+ cc = compile_bracket_matchingpath(common, cc, parent);+ break;++ case OP_BRAZERO:+ if (cc[1] > OP_ASSERTBACK_NOT)+ cc = compile_bracket_matchingpath(common, cc, parent);+ else+ {+ PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);+ cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);+ }+ break;++ case OP_BRAPOS:+ case OP_CBRAPOS:+ case OP_SBRAPOS:+ case OP_SCBRAPOS:+ case OP_BRAPOSZERO:+ cc = compile_bracketpos_matchingpath(common, cc, parent);+ break;++ case OP_MARK:+ PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);+ SLJIT_ASSERT(common->mark_ptr != 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);+ allocate_stack(common, common->has_skip_arg ? 5 : 1);+ if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);+ if (common->has_skip_arg)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);+ }+ cc += 1 + 2 + cc[1];+ break;++ case OP_PRUNE:+ case OP_PRUNE_ARG:+ case OP_SKIP:+ case OP_SKIP_ARG:+ case OP_THEN:+ case OP_THEN_ARG:+ case OP_COMMIT:+ case OP_COMMIT_ARG:+ cc = compile_control_verb_matchingpath(common, cc, parent);+ break;++ case OP_FAIL:+ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ cc = compile_fail_accept_matchingpath(common, cc, parent);+ break;++ case OP_CLOSE:+ cc = compile_close_matchingpath(common, cc);+ break;++ case OP_SKIPZERO:+ cc = bracketend(cc + 1);+ break;++ default:+ SLJIT_UNREACHABLE();+ return;+ }+ if (cc == NULL)+ return;+ }++if (has_then_trap)+ {+ /* Head item on backtrack. */+ PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);+ BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;+ BACKTRACK_AS(then_trap_backtrack)->then_trap = common->then_trap;+ common->then_trap = save_then_trap;+ }+SLJIT_ASSERT(cc == ccend);+}++#undef PUSH_BACKTRACK+#undef PUSH_BACKTRACK_NOVALUE+#undef BACKTRACK_AS++#define COMPILE_BACKTRACKINGPATH(current) \+ do \+ { \+ compile_backtrackingpath(common, (current)); \+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \+ return; \+ } \+ while (0)++#define CURRENT_AS(type) ((type *)current)++static void compile_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+PCRE2_SPTR cc = current->cc;+PCRE2_UCHAR opcode;+PCRE2_UCHAR type;+sljit_u32 max = 0, exact;+struct sljit_label *label = NULL;+struct sljit_jump *jump = NULL;+jump_list *jumplist = NULL;+PCRE2_SPTR 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 + SSIZE_OF(sw);++cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end);++switch(opcode)+ {+ case OP_STAR:+ case OP_UPTO:+ if (type == OP_ANYNL || type == OP_EXTUNI)+ {+ SLJIT_ASSERT(private_data_ptr == 0);+ 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(char_iterator_backtrack)->matchingpath);+ }+ else+ {+ if (CURRENT_AS(char_iterator_backtrack)->u.charpos.enabled)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ 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);+ move_back(common, NULL, TRUE);+ CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP2, 0, label);+ }+ else+ {+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1);+ move_back(common, NULL, TRUE);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ }+ JUMPHERE(jump);+ if (private_data_ptr == 0)+ free_stack(common, 2);+ }+ break;++ case OP_MINSTAR:+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ 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)+ free_stack(common, 1);+ break;++ case OP_MINUPTO:+ OP1(SLJIT_MOV, TMP1, 0, base, offset1);+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+ add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO));++ OP1(SLJIT_MOV, base, offset1, TMP1, 0);+ 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)+ free_stack(common, 2);+ break;++ 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(char_iterator_backtrack)->matchingpath);+ jump = JUMP(SLJIT_JUMP);+ 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(char_iterator_backtrack)->matchingpath);+ JUMPHERE(jump);+ if (private_data_ptr == 0)+ free_stack(common, 1);+ break;++ case OP_MINQUERY:+ 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, TRUE);+ JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ set_jumps(jumplist, LABEL());+ JUMPHERE(jump);+ if (private_data_ptr == 0)+ free_stack(common, 1);+ break;++ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSQUERY:+ case OP_POSUPTO:+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++set_jumps(current->own_backtracks, LABEL());+}++static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+PCRE2_SPTR cc = current->cc;+BOOL ref = (*cc == OP_REF || *cc == OP_REFI);+PCRE2_UCHAR type;++type = cc[ref ? 1 + IMM2_SIZE : 1 + 2 * IMM2_SIZE];++if ((type & 0x1) == 0)+ {+ /* Maximize case. */+ set_jumps(current->own_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(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(ref_iterator_backtrack)->matchingpath);+set_jumps(current->own_backtracks, LABEL());+free_stack(common, ref ? 2 : 3);+}++static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+recurse_entry *entry;++if (!CURRENT_AS(recurse_backtrack)->inlined_pattern)+ {+ entry = CURRENT_AS(recurse_backtrack)->entry;+ if (entry->backtrack_label == NULL)+ add_jump(compiler, &entry->backtrack_calls, JUMP(SLJIT_FAST_CALL));+ else+ JUMPTO(SLJIT_FAST_CALL, entry->backtrack_label);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(recurse_backtrack)->matchingpath);+ }+else+ compile_backtrackingpath(common, current->top);++set_jumps(current->own_backtracks, LABEL());+}++static void compile_assert_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+PCRE2_SPTR cc = current->cc;+PCRE2_UCHAR bra = OP_BRA;+struct sljit_jump *brajump = NULL;++SLJIT_ASSERT(*cc != OP_BRAMINZERO);+if (*cc == OP_BRAZERO)+ {+ bra = *cc;+ cc++;+ }++if (bra == OP_BRAZERO)+ {+ SLJIT_ASSERT(current->own_backtracks == NULL);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ }++if (CURRENT_AS(assert_backtrack)->framesize < 0)+ {+ set_jumps(current->own_backtracks, LABEL());++ if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);+ free_stack(common, 1);+ }+ return;+ }++if (bra == OP_BRAZERO)+ {+ if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);+ free_stack(common, 1);+ return;+ }+ free_stack(common, 1);+ brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ }++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, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(assert_backtrack)->framesize - 1) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, TMP1, 0);++ set_jumps(current->own_backtracks, LABEL());+ }+else+ set_jumps(current->own_backtracks, LABEL());++if (bra == OP_BRAZERO)+ {+ /* We know there is enough place on the stack. */+ 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);+ }+}++static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+int opcode, stacksize, alt_count, alt_max;+int offset = 0;+int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;+int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;+PCRE2_SPTR cc = current->cc;+PCRE2_SPTR ccbegin;+PCRE2_SPTR ccprev;+PCRE2_UCHAR bra = OP_BRA;+PCRE2_UCHAR ket;+assert_backtrack *assert;+BOOL has_alternatives;+BOOL needs_control_head = FALSE;+BOOL has_vreverse;+struct sljit_jump *brazero = NULL;+struct sljit_jump *next_alt = NULL;+struct sljit_jump *once = NULL;+struct sljit_jump *cond = NULL;+struct sljit_label *rmin_label = NULL;+struct sljit_label *exact_label = NULL;+struct sljit_jump *mov_addr = NULL;++if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)+ {+ bra = *cc;+ cc++;+ }++opcode = *cc;+ccbegin = bracketend(cc) - 1 - LINK_SIZE;+ket = *ccbegin;+if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0)+ {+ repeat_ptr = PRIVATE_DATA(ccbegin);+ repeat_type = PRIVATE_DATA(ccbegin + 2);+ repeat_count = PRIVATE_DATA(ccbegin + 3);+ SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0);+ if (repeat_type == OP_UPTO)+ ket = OP_KETRMAX;+ if (repeat_type == OP_MINUPTO)+ ket = OP_KETRMIN;+ }+ccbegin = cc;+cc += GET(cc, 1);+has_alternatives = *cc == OP_ALT;+if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))+ has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL;+if (opcode == OP_CBRA || opcode == OP_SCBRA)+ offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;+if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))+ opcode = OP_SCOND;++alt_max = has_alternatives ? no_alternatives(ccbegin) : 0;++/* Decoding the needs_control_head in framesize. */+if (opcode == OP_ONCE)+ {+ needs_control_head = (CURRENT_AS(bracket_backtrack)->u.framesize & 0x1) != 0;+ CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;+ }++if (ket != OP_KET && repeat_type != 0)+ {+ /* TMP1 is used in OP_KETRMIN below. */+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ if (repeat_type == OP_UPTO)+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0, SLJIT_IMM, 1);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0);+ }++if (ket == OP_KETRMAX)+ {+ if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ brazero = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }+ }+else if (ket == OP_KETRMIN)+ {+ if (bra != OP_BRAMINZERO)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ if (repeat_type != 0)+ {+ /* TMP1 was set a few lines above. */+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);+ /* Drop STR_PTR for non-greedy plus quantifier. */+ if (opcode != OP_ONCE)+ free_stack(common, 1);+ }+ else if (opcode >= OP_SBRA || opcode == OP_ONCE)+ {+ /* Checking zero-length iteration. */+ if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ 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)+ free_stack(common, 1);+ }+ else+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);+ }+ rmin_label = LABEL();+ if (repeat_type != 0)+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);+ }+else if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ brazero = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }+else if (repeat_type == OP_EXACT)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);+ exact_label = LABEL();+ }++if (offset != 0)+ {+ if (common->capture_last_ptr != 0)+ {+ SLJIT_ASSERT(common->optimized_cbracket[offset >> 1] == 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));+ free_stack(common, 3);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);+ }+ else if (common->optimized_cbracket[offset >> 1] == 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ free_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);+ }+ }++if (SLJIT_UNLIKELY(opcode == OP_ONCE))+ {+ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)+ {+ 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, (CURRENT_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw));+ }+ once = JUMP(SLJIT_JUMP);+ }+else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))+ {+ if (has_alternatives)+ {+ /* Always exactly one alternative. */+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);++ alt_max = 2;+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }+ }+else if (has_alternatives)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);++ if (alt_max > 3)+ {+ sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);++ SLJIT_ASSERT(CURRENT_AS(bracket_backtrack)->u.matching_mov_addr);+ sljit_set_label(CURRENT_AS(bracket_backtrack)->u.matching_mov_addr, LABEL());+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ }+ else+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }++COMPILE_BACKTRACKINGPATH(current->top);+if (current->own_backtracks)+ set_jumps(current->own_backtracks, LABEL());++if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))+ {+ /* Conditional block always has at most one alternative. */+ if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)+ {+ SLJIT_ASSERT(has_alternatives);+ assert = CURRENT_AS(bracket_backtrack)->u.assert;+ if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))+ {+ 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, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0);+ }+ cond = JUMP(SLJIT_JUMP);+ set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());+ }+ else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL)+ {+ SLJIT_ASSERT(has_alternatives);+ cond = JUMP(SLJIT_JUMP);+ set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL());+ }+ else+ SLJIT_ASSERT(!has_alternatives);+ }++if (has_alternatives)+ {+ alt_count = 1;+ do+ {+ current->top = NULL;+ current->own_backtracks = NULL;+ current->simple_backtracks = NULL;+ /* Conditional blocks always have an additional alternative, even if it is empty. */+ if (*cc == OP_ALT)+ {+ ccprev = cc + 1 + LINK_SIZE;+ cc += GET(cc, 1);++ has_vreverse = FALSE;+ if (opcode == OP_ASSERTBACK || opcode == OP_ASSERTBACK_NA)+ {+ SLJIT_ASSERT(private_data_ptr != 0);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);++ has_vreverse = (*ccprev == OP_VREVERSE);+ if (*ccprev == OP_REVERSE || has_vreverse)+ ccprev = compile_reverse_matchingpath(common, ccprev, current);+ }+ else if (opcode != OP_COND && opcode != OP_SCOND)+ {+ if (opcode != OP_ONCE)+ {+ if (private_data_ptr != 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ else+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ }+ else+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0));+ }++ compile_matchingpath(common, ccprev, cc, current);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return;++ switch (opcode)+ {+ case OP_ASSERTBACK_NA:+ if (has_vreverse)+ {+ SLJIT_ASSERT(current->top != NULL && PRIVATE_DATA(ccbegin + 1));+ add_jump(compiler, ¤t->top->simple_backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));+ }++ if (PRIVATE_DATA(ccbegin + 1))+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw));+ break;+ case OP_ASSERT_NA:+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ break;+ case OP_SCRIPT_RUN:+ match_script_run_common(common, private_data_ptr, current);+ break;+ }+ }++ /* Instructions after the current alternative is successfully matched. */+ /* There is a similar code in compile_bracket_matchingpath. */+ if (opcode == OP_ONCE)+ match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);++ stacksize = 0;+ if (repeat_type == OP_MINUPTO)+ {+ /* We need to preserve the counter. TMP2 will be used below. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);+ stacksize++;+ }+ if (ket != OP_KET || bra != OP_BRA)+ stacksize++;+ if (offset != 0)+ {+ if (common->capture_last_ptr != 0)+ stacksize++;+ if (common->optimized_cbracket[offset >> 1] == 0)+ stacksize += 2;+ }+ if (opcode != OP_ONCE)+ stacksize++;++ if (stacksize > 0)+ allocate_stack(common, stacksize);++ stacksize = 0;+ if (repeat_type == OP_MINUPTO)+ {+ /* TMP2 was set above. */+ OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);+ stacksize++;+ }++ if (ket != OP_KET || bra != OP_BRA)+ {+ if (ket != OP_KET)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);+ stacksize++;+ }++ if (offset != 0)+ stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);++ if (opcode != OP_ONCE)+ {+ if (alt_max <= 3)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);+ else+ mov_addr = sljit_emit_mov_addr(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));+ }++ if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0)+ {+ /* If ket is not OP_KETRMAX, this code path is executed after the jump to alternative_matchingpath. */+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+ }++ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alternative_matchingpath);++ if (opcode != OP_ONCE)+ {+ if (alt_max <= 3)+ {+ JUMPHERE(next_alt);+ alt_count++;+ if (alt_count < alt_max)+ {+ SLJIT_ASSERT(alt_count == 2 && alt_max == 3);+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);+ }+ }+ else+ {+ sljit_set_label(mov_addr, LABEL());+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ }+ }++ COMPILE_BACKTRACKINGPATH(current->top);+ if (current->own_backtracks)+ set_jumps(current->own_backtracks, LABEL());+ SLJIT_ASSERT(!current->simple_backtracks);+ }+ while (*cc == OP_ALT);++ if (cond != NULL)+ {+ SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);+ assert = CURRENT_AS(bracket_backtrack)->u.assert;+ if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)+ {+ 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, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0);+ }+ JUMPHERE(cond);+ }++ /* Free the STR_PTR. */+ if (private_data_ptr == 0)+ free_stack(common, 1);+ }++if (offset != 0)+ {+ /* Using both tmp register is better for instruction scheduling. */+ if (common->optimized_cbracket[offset >> 1] != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ free_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);+ }+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }+ }+else if (opcode == OP_ASSERTBACK_NA && PRIVATE_DATA(ccbegin + 1))+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw), TMP2, 0);+ free_stack(common, 4);+ }+else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ }+else if (opcode == OP_ONCE)+ {+ cc = ccbegin + GET(ccbegin, 1);+ stacksize = needs_control_head ? 1 : 0;++ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)+ {+ /* Reset head and drop saved frame. */+ stacksize += CURRENT_AS(bracket_backtrack)->u.framesize + ((ket != OP_KET || *cc == OP_ALT) ? 2 : 1);+ }+ else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))+ {+ /* The STR_PTR must be released. */+ 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), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 1));+ else if (ket == OP_KETRMIN)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ /* See the comment below. */+ free_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }+ }++if (repeat_type == OP_EXACT)+ {+ OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0);+ CMPTO(SLJIT_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label);+ }+else if (ket == OP_KETRMAX)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ if (bra != OP_BRAZERO)+ free_stack(common, 1);++ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);+ if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);+ JUMPHERE(brazero);+ free_stack(common, 1);+ }+ }+else if (ket == OP_KETRMIN)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));++ /* OP_ONCE removes everything in case of a backtrack, so we don't+ need to explicitly release the STR_PTR. The extra release would+ affect badly the free_stack(2) above. */+ if (opcode != OP_ONCE)+ free_stack(common, 1);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label);+ if (opcode == OP_ONCE)+ free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);+ else if (bra == OP_BRAMINZERO)+ free_stack(common, 1);+ }+else if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);+ JUMPHERE(brazero);+ }+}++static SLJIT_INLINE void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+int offset;+struct sljit_jump *jump;+PCRE2_SPTR cc;++/* No retry on backtrack, just drop everything. */+if (CURRENT_AS(bracketpos_backtrack)->framesize < 0)+ {+ cc = current->cc;++ if (*cc == OP_BRAPOSZERO)+ cc++;++ if (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)+ {+ offset = (GET2(cc, 1 + LINK_SIZE)) << 1;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0);+ }+ set_jumps(current->own_backtracks, LABEL());+ free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);+ return;+ }++OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr);+add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(bracketpos_backtrack)->framesize - 1) * sizeof(sljit_sw));++if (current->own_backtracks)+ {+ jump = JUMP(SLJIT_JUMP);+ set_jumps(current->own_backtracks, LABEL());+ /* Drop the stack frame. */+ 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), STACK(-CURRENT_AS(bracketpos_backtrack)->framesize - 1));+}++static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+assert_backtrack backtrack;++current->top = NULL;+current->own_backtracks = NULL;+current->simple_backtracks = NULL;+if (current->cc[1] > OP_ASSERTBACK_NOT)+ {+ /* Manual call of compile_bracket_matchingpath and compile_bracket_backtrackingpath. */+ compile_bracket_matchingpath(common, current->cc, current);+ compile_bracket_backtrackingpath(common, current->top);+ }+else+ {+ memset(&backtrack, 0, sizeof(backtrack));+ backtrack.common.cc = current->cc;+ backtrack.matchingpath = CURRENT_AS(braminzero_backtrack)->matchingpath;+ /* Manual call of compile_assert_matchingpath. */+ compile_assert_matchingpath(common, current->cc, &backtrack, FALSE);+ }+SLJIT_ASSERT(!current->simple_backtracks && !current->own_backtracks);+}++static SLJIT_INLINE void compile_control_verb_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+PCRE2_UCHAR opcode = *current->cc;+struct sljit_label *loop;+struct sljit_jump *jump;++if (opcode == OP_THEN || opcode == OP_THEN_ARG)+ {+ if (common->then_trap != NULL)+ {+ SLJIT_ASSERT(common->control_head_ptr != 0);++ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start);+ jump = JUMP(SLJIT_JUMP);++ loop = LABEL();+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ JUMPHERE(jump);+ 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;+ }+ else if (!common->local_quit_available && common->in_positive_assertion)+ {+ add_jump(compiler, &common->positive_assertion_quit, JUMP(SLJIT_JUMP));+ return;+ }+ }++if (common->local_quit_available)+ {+ /* Abort match with a fail. */+ if (common->quit_label == NULL)+ add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));+ else+ JUMPTO(SLJIT_JUMP, common->quit_label);+ return;+ }++if (opcode == OP_SKIP_ARG)+ {+ SLJIT_ASSERT(common->control_head_ptr != 0 && TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_search_mark));++ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_R0, 0);+ add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0));+ return;+ }++if (opcode == OP_SKIP)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+else+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0);+add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP));+}++static SLJIT_INLINE void compile_vreverse_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_label *label;++OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(2));+jump = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(3));+skip_valid_char(common);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), STR_PTR, 0);+JUMPTO(SLJIT_JUMP, CURRENT_AS(vreverse_backtrack)->matchingpath);++label = LABEL();+sljit_set_label(jump, label);+set_jumps(current->own_backtracks, label);+}++static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+struct sljit_jump *jump;+int size;++if (CURRENT_AS(then_trap_backtrack)->then_trap)+ {+ common->then_trap = CURRENT_AS(then_trap_backtrack)->then_trap;+ return;+ }++size = CURRENT_AS(then_trap_backtrack)->framesize;+size = 3 + (size < 0 ? 0 : size);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(size - 3));+free_stack(common, size);+jump = JUMP(SLJIT_JUMP);++set_jumps(CURRENT_AS(then_trap_backtrack)->quit, LABEL());+/* STACK_TOP is set by THEN. */+if (CURRENT_AS(then_trap_backtrack)->framesize >= 0)+ {+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(then_trap_backtrack)->framesize - 1) * sizeof(sljit_sw));+ }+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+free_stack(common, 3);++JUMPHERE(jump);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0);+}++static void compile_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+then_trap_backtrack *save_then_trap = common->then_trap;++while (current)+ {+ if (current->simple_backtracks != NULL)+ set_jumps(current->simple_backtracks, LABEL());+ switch(*current->cc)+ {+ case OP_SET_SOM:+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP1, 0);+ break;++ case OP_STAR:+ case OP_MINSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:+ case OP_STARI:+ case OP_MINSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:+ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:+ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ case OP_TYPEPOSUPTO:+ case OP_CLASS:+ case OP_NCLASS:+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+#endif+ compile_iterator_backtrackingpath(common, current);+ break;++ case OP_REF:+ case OP_REFI:+ case OP_DNREF:+ case OP_DNREFI:+ compile_ref_iterator_backtrackingpath(common, current);+ break;++ case OP_RECURSE:+ compile_recurse_backtrackingpath(common, current);+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ compile_assert_backtrackingpath(common, current);+ break;++ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRA:+ case OP_CBRA:+ case OP_COND:+ case OP_SBRA:+ case OP_SCBRA:+ case OP_SCOND:+ compile_bracket_backtrackingpath(common, current);+ break;++ case OP_BRAZERO:+ if (current->cc[1] > OP_ASSERTBACK_NOT)+ compile_bracket_backtrackingpath(common, current);+ else+ compile_assert_backtrackingpath(common, current);+ break;++ case OP_BRAPOS:+ case OP_CBRAPOS:+ case OP_SBRAPOS:+ case OP_SCBRAPOS:+ case OP_BRAPOSZERO:+ compile_bracketpos_backtrackingpath(common, current);+ break;++ case OP_BRAMINZERO:+ compile_braminzero_backtrackingpath(common, current);+ break;++ case OP_MARK:+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0));+ if (common->has_skip_arg)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, common->has_skip_arg ? 5 : 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0);+ if (common->has_skip_arg)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0);+ break;++ case OP_THEN:+ case OP_THEN_ARG:+ case OP_PRUNE:+ case OP_PRUNE_ARG:+ case OP_SKIP:+ case OP_SKIP_ARG:+ compile_control_verb_backtrackingpath(common, current);+ break;++ case OP_COMMIT:+ case OP_COMMIT_ARG:+ if (!common->local_quit_available)+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+ if (common->quit_label == NULL)+ add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));+ else+ JUMPTO(SLJIT_JUMP, common->quit_label);+ break;++ case OP_CALLOUT:+ case OP_CALLOUT_STR:+ case OP_FAIL:+ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ set_jumps(current->own_backtracks, LABEL());+ break;++ case OP_VREVERSE:+ compile_vreverse_backtrackingpath(common, current);+ break;++ case OP_THEN_TRAP:+ /* A virtual opcode for then traps. */+ compile_then_trap_backtrackingpath(common, current);+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ current = current->prev;+ }+common->then_trap = save_then_trap;+}++static SLJIT_INLINE void compile_recurse(compiler_common *common)+{+DEFINE_COMPILER;+PCRE2_SPTR cc = common->start + common->currententry->start;+PCRE2_SPTR ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);+PCRE2_SPTR ccend = bracketend(cc) - (1 + LINK_SIZE);+uint32_t recurse_flags = 0;+int private_data_size = get_recurse_data_length(common, ccbegin, ccend, &recurse_flags);+int alt_count, alt_max, local_size;+backtrack_common altbacktrack;+jump_list *match = NULL;+struct sljit_jump *next_alt = NULL;+struct sljit_jump *accept_exit = NULL;+struct sljit_label *quit;+struct sljit_jump *mov_addr = NULL;++/* Recurse captures then. */+common->then_trap = NULL;++SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);++alt_max = no_alternatives(cc);+alt_count = 0;++/* Matching path. */+SLJIT_ASSERT(common->currententry->entry_label == NULL && common->recursive_head_ptr != 0);+common->currententry->entry_label = LABEL();+set_jumps(common->currententry->entry_calls, common->currententry->entry_label);++sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, TMP2, 0);+count_match(common);++local_size = (alt_max > 1) ? 2 : 1;++/* (Reversed) stack layout:+ [private data][return address][optional: str ptr] ... [optional: alternative index][recursive_head_ptr] */++allocate_stack(common, private_data_size + local_size);+/* Save return address. */+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP2, 0);++copy_recurse_data(common, ccbegin, ccend, recurse_copy_from_global, local_size, private_data_size + local_size, recurse_flags);++/* This variable is saved and restored all time when we enter or exit from a recursive context. */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0);++if (recurse_flags & recurse_flag_control_head_found)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);++if (alt_max > 1)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);++memset(&altbacktrack, 0, sizeof(backtrack_common));+common->quit_label = NULL;+common->accept_label = NULL;+common->quit = NULL;+common->accept = NULL;+altbacktrack.cc = ccbegin;+cc += GET(cc, 1);+while (1)+ {+ altbacktrack.top = NULL;+ altbacktrack.own_backtracks = NULL;++ if (altbacktrack.cc != ccbegin)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));++ compile_matchingpath(common, altbacktrack.cc, cc, &altbacktrack);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return;++ allocate_stack(common, (alt_max > 1 || (recurse_flags & recurse_flag_accept_found)) ? 2 : 1);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);++ if (alt_max > 1 || (recurse_flags & recurse_flag_accept_found))+ {+ if (alt_max > 3)+ mov_addr = sljit_emit_mov_addr(compiler, SLJIT_MEM1(STACK_TOP), STACK(1));+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);+ }++ add_jump(compiler, &match, JUMP(SLJIT_JUMP));++ if (alt_count == 0)+ {+ /* Backtracking path entry. */+ SLJIT_ASSERT(common->currententry->backtrack_label == NULL);+ common->currententry->backtrack_label = LABEL();+ set_jumps(common->currententry->backtrack_calls, common->currententry->backtrack_label);++ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, TMP1, 0);++ if (recurse_flags & recurse_flag_accept_found)+ accept_exit = CMP(SLJIT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);++ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ /* Save return address. */+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(local_size - 1), TMP1, 0);++ copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, recurse_flags);++ if (alt_max > 1)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ free_stack(common, 2);++ if (alt_max > 3)+ {+ sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);+ sljit_set_label(mov_addr, LABEL());+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ }+ else+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }+ else+ free_stack(common, (recurse_flags & recurse_flag_accept_found) ? 2 : 1);+ }+ else if (alt_max > 3)+ {+ sljit_set_label(mov_addr, LABEL());+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ }+ else+ {+ JUMPHERE(next_alt);+ if (alt_count + 1 < alt_max)+ {+ SLJIT_ASSERT(alt_count == 1 && alt_max == 3);+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);+ }+ }++ alt_count++;++ compile_backtrackingpath(common, altbacktrack.top);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return;+ set_jumps(altbacktrack.own_backtracks, LABEL());++ if (*cc != OP_ALT)+ break;++ altbacktrack.cc = cc + 1 + LINK_SIZE;+ cc += GET(cc, 1);+ }++/* No alternative is matched. */++quit = LABEL();++copy_recurse_data(common, ccbegin, ccend, recurse_copy_private_to_global, local_size, private_data_size + local_size, recurse_flags);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1));+free_stack(common, private_data_size + local_size);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);++if (common->quit != NULL)+ {+ SLJIT_ASSERT(recurse_flags & recurse_flag_quit_found);++ set_jumps(common->quit, LABEL());+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);+ copy_recurse_data(common, ccbegin, ccend, recurse_copy_shared_to_global, local_size, private_data_size + local_size, recurse_flags);+ JUMPTO(SLJIT_JUMP, quit);+ }++if (recurse_flags & recurse_flag_accept_found)+ {+ JUMPHERE(accept_exit);+ free_stack(common, 2);++ /* Save return address. */+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP1, 0);++ copy_recurse_data(common, ccbegin, ccend, recurse_copy_kept_shared_to_global, local_size, private_data_size + local_size, recurse_flags);++ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1));+ free_stack(common, private_data_size + local_size);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+ OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);+ }++if (common->accept != NULL)+ {+ SLJIT_ASSERT(recurse_flags & recurse_flag_accept_found);++ set_jumps(common->accept, LABEL());++ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);+ OP1(SLJIT_MOV, TMP2, 0, STACK_TOP, 0);++ allocate_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);+ }++set_jumps(match, LABEL());++OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);++copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, recurse_flags);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), STACK(local_size - 1));+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);+}++#undef COMPILE_BACKTRACKINGPATH+#undef CURRENT_AS++#define PUBLIC_JIT_COMPILE_CONFIGURATION_OPTIONS \+ (PCRE2_JIT_INVALID_UTF)++static int jit_compile(pcre2_code *code, sljit_u32 mode)+{+pcre2_real_code *re = (pcre2_real_code *)code;+struct sljit_compiler *compiler;+backtrack_common rootbacktrack;+compiler_common common_data;+compiler_common *common = &common_data;+const sljit_u8 *tables = re->tables;+void *allocator_data = &re->memctl;+int private_data_size;+PCRE2_SPTR ccend;+executable_functions *functions;+void *executable_func;+sljit_uw executable_size;+sljit_uw total_length;+struct sljit_label *mainloop_label = NULL;+struct sljit_label *continue_match_label;+struct sljit_label *empty_match_found_label = NULL;+struct sljit_label *empty_match_backtrack_label = NULL;+struct sljit_label *reset_match_label;+struct sljit_label *quit_label;+struct sljit_jump *jump;+struct sljit_jump *minlength_check_failed = NULL;+struct sljit_jump *empty_match = NULL;+struct sljit_jump *end_anchor_failed = NULL;+jump_list *reqcu_not_found = NULL;++SLJIT_ASSERT(tables);++#if HAS_VIRTUAL_REGISTERS == 1+SLJIT_ASSERT(sljit_get_register_index(SLJIT_GP_REGISTER, TMP3) < 0 && sljit_get_register_index(SLJIT_GP_REGISTER, ARGUMENTS) < 0 && sljit_get_register_index(SLJIT_GP_REGISTER, RETURN_ADDR) < 0);+#elif HAS_VIRTUAL_REGISTERS == 0+SLJIT_ASSERT(sljit_get_register_index(SLJIT_GP_REGISTER, TMP3) >= 0 && sljit_get_register_index(SLJIT_GP_REGISTER, ARGUMENTS) >= 0 && sljit_get_register_index(SLJIT_GP_REGISTER, RETURN_ADDR) >= 0);+#else+#error "Invalid value for HAS_VIRTUAL_REGISTERS"+#endif++memset(&rootbacktrack, 0, sizeof(backtrack_common));+memset(common, 0, sizeof(compiler_common));+common->re = re;+common->name_table = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));+rootbacktrack.cc = common->name_table + re->name_count * re->name_entry_size;++#ifdef SUPPORT_UNICODE+common->invalid_utf = (mode & PCRE2_JIT_INVALID_UTF) != 0;+#endif /* SUPPORT_UNICODE */+mode &= ~PUBLIC_JIT_COMPILE_CONFIGURATION_OPTIONS;++common->start = rootbacktrack.cc;+common->read_only_data_head = NULL;+common->fcc = tables + fcc_offset;+common->lcc = (sljit_sw)(tables + lcc_offset);+common->mode = mode;+common->might_be_empty = (re->minlength == 0) || (re->flags & PCRE2_MATCH_EMPTY);+common->allow_empty_partial = (re->max_lookbehind > 0) || (re->flags & PCRE2_MATCH_EMPTY);+common->nltype = NLTYPE_FIXED;+switch(re->newline_convention)+ {+ case PCRE2_NEWLINE_CR: common->newline = CHAR_CR; break;+ case PCRE2_NEWLINE_LF: common->newline = CHAR_NL; break;+ case PCRE2_NEWLINE_CRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;+ case PCRE2_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;+ case PCRE2_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;+ case PCRE2_NEWLINE_NUL: common->newline = CHAR_NUL; break;+ default: return PCRE2_ERROR_INTERNAL;+ }+common->nlmax = READ_CHAR_MAX;+common->nlmin = 0;+if (re->bsr_convention == PCRE2_BSR_UNICODE)+ common->bsr_nltype = NLTYPE_ANY;+else if (re->bsr_convention == PCRE2_BSR_ANYCRLF)+ common->bsr_nltype = NLTYPE_ANYCRLF;+else+ {+#ifdef BSR_ANYCRLF+ common->bsr_nltype = NLTYPE_ANYCRLF;+#else+ common->bsr_nltype = NLTYPE_ANY;+#endif+ }+common->bsr_nlmax = READ_CHAR_MAX;+common->bsr_nlmin = 0;+common->endonly = (re->overall_options & PCRE2_DOLLAR_ENDONLY) != 0;+common->ctypes = (sljit_sw)(tables + ctypes_offset);+common->name_count = re->name_count;+common->name_entry_size = re->name_entry_size;+common->unset_backref = (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) != 0;+common->alt_circumflex = (re->overall_options & PCRE2_ALT_CIRCUMFLEX) != 0;+#ifdef SUPPORT_UNICODE+/* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */+common->utf = (re->overall_options & PCRE2_UTF) != 0;+common->ucp = (re->overall_options & PCRE2_UCP) != 0;+if (common->utf)+ {+ if (common->nltype == NLTYPE_ANY)+ common->nlmax = 0x2029;+ else if (common->nltype == NLTYPE_ANYCRLF)+ common->nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;+ else+ {+ /* We only care about the first newline character. */+ common->nlmax = common->newline & 0xff;+ }++ if (common->nltype == NLTYPE_FIXED)+ common->nlmin = common->newline & 0xff;+ else+ common->nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;++ if (common->bsr_nltype == NLTYPE_ANY)+ common->bsr_nlmax = 0x2029;+ else+ common->bsr_nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;+ common->bsr_nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;+ }+else+ common->invalid_utf = FALSE;+#endif /* SUPPORT_UNICODE */+ccend = bracketend(common->start);++/* Calculate the local space size on the stack. */+common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw);+common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, allocator_data);+if (!common->optimized_cbracket)+ return PCRE2_ERROR_NOMEMORY;+#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1+memset(common->optimized_cbracket, 0, re->top_bracket + 1);+#else+memset(common->optimized_cbracket, 1, re->top_bracket + 1);+#endif++SLJIT_ASSERT(*common->start == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);+#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 2+common->capture_last_ptr = common->ovector_start;+common->ovector_start += sizeof(sljit_sw);+#endif+if (!check_opcode_types(common, common->start, ccend))+ {+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++/* Checking flags and updating ovector_start. */+if (mode == PCRE2_JIT_COMPLETE && (re->flags & PCRE2_LASTSET) != 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)+ {+ common->req_char_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+if (mode != PCRE2_JIT_COMPLETE)+ {+ common->start_used_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ if (mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ common->hit_start = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+ }+if ((re->overall_options & (PCRE2_FIRSTLINE | PCRE2_USE_OFFSET_LIMIT)) != 0)+ {+ common->match_end_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+common->control_head_ptr = 1;+#endif+if (common->control_head_ptr != 0)+ {+ common->control_head_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+if (common->has_set_som)+ {+ /* Saving the real start pointer is necessary. */+ common->start_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }++/* Aligning ovector to even number of sljit words. */+if ((common->ovector_start & sizeof(sljit_sw)) != 0)+ common->ovector_start += sizeof(sljit_sw);++if (common->start_ptr == 0)+ common->start_ptr = OVECTOR(0);++/* Capturing brackets cannot be optimized if callouts are allowed. */+if (common->capture_last_ptr != 0)+ memset(common->optimized_cbracket, 0, re->top_bracket + 1);++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_s32*)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data);+if (!common->private_data_ptrs)+ {+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }+memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32));++private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);++if ((re->overall_options & PCRE2_ANCHORED) == 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 && !common->has_skip_in_assert_back)+ detect_early_fail(common, common->start, &private_data_size, 0, 0);++set_private_data_ptrs(common, &private_data_size, ccend);++SLJIT_ASSERT(common->early_fail_start_ptr <= common->early_fail_end_ptr);++if (private_data_size > 65536)+ {+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++if (common->has_then)+ {+ 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);+ }++compiler = sljit_create_compiler(allocator_data);+if (!compiler)+ {+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }+common->compiler = compiler;++/* Main pcre2_jit_exec entry. */+SLJIT_ASSERT((private_data_size & (sizeof(sljit_sw) - 1)) == 0);+sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 5, 5, SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS, 0, private_data_size);++/* Register init. */+reset_ovector(common, (re->top_bracket + 1) * 2);+if (common->req_char_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, SLJIT_R0, 0);++OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_S0, 0);+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_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, end));+OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, start));+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);++if (common->early_fail_start_ptr < common->early_fail_end_ptr)+ reset_early_fail(common);++if (mode == PCRE2_JIT_PARTIAL_SOFT)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);+if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);+if (common->control_head_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);++/* Main part of the matching */+if ((re->overall_options & PCRE2_ANCHORED) == 0)+ {+ mainloop_label = mainloop_entry(common);+ continue_match_label = LABEL();+ /* Forward search if possible. */+ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)+ {+ if (mode == PCRE2_JIT_COMPLETE && fast_forward_first_n_chars(common))+ ;+ else if ((re->flags & PCRE2_FIRSTSET) != 0)+ fast_forward_first_char(common);+ else if ((re->flags & PCRE2_STARTLINE) != 0)+ fast_forward_newline(common);+ else if ((re->flags & PCRE2_FIRSTMAPSET) != 0)+ fast_forward_start_bits(common);+ }+ }+else+ continue_match_label = LABEL();++if (mode == PCRE2_JIT_COMPLETE && re->minlength > 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)+ {+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(re->minlength));+ minlength_check_failed = CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0);+ }+if (common->req_char_ptr != 0)+ reqcu_not_found = search_requested_char(common, (PCRE2_UCHAR)(re->last_codeunit), (re->flags & PCRE2_LASTCASELESS) != 0, (re->flags & PCRE2_FIRSTSET) != 0);++/* Store the current STR_PTR in OVECTOR(0). */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);+/* Copy the limit of allowed recursions. */+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, 0);+if (common->fast_forward_bc_ptr != NULL)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1) >> 3, STR_PTR, 0);++if (common->start_ptr != OVECTOR(0))+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0);++/* Copy the beginning of the string. */+if (mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ JUMPHERE(jump);+ }+else if (mode == PCRE2_JIT_PARTIAL_HARD)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);++compile_matchingpath(common, common->start, ccend, &rootbacktrack);+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ {+ sljit_free_compiler(compiler);+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++if ((re->overall_options & PCRE2_ENDANCHORED) != 0)+ end_anchor_failed = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0);++if (common->might_be_empty)+ {+ empty_match = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));+ empty_match_found_label = LABEL();+ }++common->accept_label = LABEL();+if (common->accept != NULL)+ set_jumps(common->accept, common->accept_label);++/* This means we have a match. Update the ovector. */+copy_ovector(common, re->top_bracket + 1);+common->quit_label = common->abort_label = LABEL();+if (common->quit != NULL)+ set_jumps(common->quit, common->quit_label);+if (common->abort != NULL)+ set_jumps(common->abort, common->abort_label);+if (minlength_check_failed != NULL)+ SET_LABEL(minlength_check_failed, common->abort_label);++sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN);+sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++if (common->failed_match != NULL)+ {+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);+ set_jumps(common->failed_match, LABEL());+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+ JUMPTO(SLJIT_JUMP, common->abort_label);+ }++if ((re->overall_options & PCRE2_ENDANCHORED) != 0)+ JUMPHERE(end_anchor_failed);++if (mode != PCRE2_JIT_COMPLETE)+ {+ common->partialmatchlabel = LABEL();+ set_jumps(common->partialmatch, common->partialmatchlabel);+ return_with_partial_match(common, common->quit_label);+ }++if (common->might_be_empty)+ empty_match_backtrack_label = LABEL();+compile_backtrackingpath(common, rootbacktrack.top);+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ {+ sljit_free_compiler(compiler);+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++SLJIT_ASSERT(rootbacktrack.prev == NULL);+reset_match_label = LABEL();++if (mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ /* Update hit_start only in the first time. */+ jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, TMP1, 0);+ JUMPHERE(jump);+ }++/* Check we have remaining characters. */+if ((re->overall_options & PCRE2_ANCHORED) == 0 && 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->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1) >> 3) : common->start_ptr);++if ((re->overall_options & PCRE2_ANCHORED) == 0)+ {+ if (common->ff_newline_shortcut != NULL)+ {+ /* There cannot be more newlines if PCRE2_FIRSTLINE is set. */+ if ((re->overall_options & PCRE2_FIRSTLINE) == 0)+ {+ if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);+ OP1(SLJIT_MOV, STR_END, 0, TMP1, 0);+ CMPTO(SLJIT_LESS, STR_PTR, 0, TMP1, 0, common->ff_newline_shortcut);+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+ }+ else+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut);+ }+ }+ else+ CMPTO(SLJIT_LESS, STR_PTR, 0, (common->match_end_ptr == 0) ? STR_END : TMP1, 0, mainloop_label);+ }++/* No more remaining characters. */+if (reqcu_not_found != NULL)+ set_jumps(reqcu_not_found, LABEL());++if (mode == PCRE2_JIT_PARTIAL_SOFT)+ CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel);++OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+JUMPTO(SLJIT_JUMP, common->quit_label);++flush_stubs(common);++if (common->might_be_empty)+ {+ JUMPHERE(empty_match);+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);+ JUMPTO(SLJIT_NOT_ZERO, empty_match_backtrack_label);+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);+ JUMPTO(SLJIT_ZERO, 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->early_fail_start_ptr = 0;+common->early_fail_end_ptr = 0;+common->currententry = common->entries;+common->local_quit_available = TRUE;+quit_label = common->quit_label;+if (common->currententry != NULL)+ {+ /* A free bit for each private data. */+ common->recurse_bitset_size = ((private_data_size / SSIZE_OF(sw)) + 7) >> 3;+ SLJIT_ASSERT(common->recurse_bitset_size > 0);+ common->recurse_bitset = (sljit_u8*)SLJIT_MALLOC(common->recurse_bitset_size, allocator_data);;++ if (common->recurse_bitset != NULL)+ {+ do+ {+ /* Might add new entries. */+ compile_recurse(common);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ break;+ flush_stubs(common);+ common->currententry = common->currententry->next;+ }+ while (common->currententry != NULL);++ SLJIT_FREE(common->recurse_bitset, allocator_data);+ }++ if (common->currententry != NULL)+ {+ /* The common->recurse_bitset has been freed. */+ SLJIT_ASSERT(sljit_get_compiler_error(compiler) || common->recurse_bitset == NULL);++ sljit_free_compiler(compiler);+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }+ }+common->local_quit_available = FALSE;+common->quit_label = quit_label;++/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */+/* This is a (really) rare case. */+set_jumps(common->stackalloc, LABEL());+/* RETURN_ADDR is not a saved register. */+sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCALS0);++SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);++OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0);+OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);+OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE);+OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack));+OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0);++sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_stack_resize));++jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0);+OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);+OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);++/* Allocation failed. */+JUMPHERE(jump);+/* We break the return address cache here, but this is a really rare case. */+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_JIT_STACKLIMIT);+JUMPTO(SLJIT_JUMP, common->quit_label);++/* Call limit reached. */+set_jumps(common->calllimit, LABEL());+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_MATCHLIMIT);+JUMPTO(SLJIT_JUMP, common->quit_label);++if (common->revertframes != NULL)+ {+ set_jumps(common->revertframes, LABEL());+ do_revertframes(common);+ }+if (common->wordboundary != NULL)+ {+ set_jumps(common->wordboundary, LABEL());+ check_wordboundary(common, FALSE);+ }+if (common->ucp_wordboundary != NULL)+ {+ set_jumps(common->ucp_wordboundary, LABEL());+ check_wordboundary(common, TRUE);+ }+if (common->anynewline != NULL)+ {+ set_jumps(common->anynewline, LABEL());+ check_anynewline(common);+ }+if (common->hspace != NULL)+ {+ set_jumps(common->hspace, LABEL());+ check_hspace(common);+ }+if (common->vspace != NULL)+ {+ set_jumps(common->vspace, LABEL());+ check_vspace(common);+ }+if (common->casefulcmp != NULL)+ {+ set_jumps(common->casefulcmp, LABEL());+ do_casefulcmp(common);+ }+if (common->caselesscmp != NULL)+ {+ set_jumps(common->caselesscmp, LABEL());+ do_caselesscmp(common);+ }+if (common->reset_match != NULL || common->restart_match != NULL)+ {+ if (common->restart_match != NULL)+ {+ set_jumps(common->restart_match, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);+ }++ set_jumps(common->reset_match, LABEL());+ do_reset_match(common, (re->top_bracket + 1) * 2);+ /* The value of restart_match is in TMP1. */+ CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP1, 0, continue_match_label);+ OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);+ JUMPTO(SLJIT_JUMP, reset_match_label);+ }+#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utfreadchar != NULL)+ {+ set_jumps(common->utfreadchar, LABEL());+ do_utfreadchar(common);+ }+if (common->utfreadtype8 != NULL)+ {+ set_jumps(common->utfreadtype8, LABEL());+ do_utfreadtype8(common);+ }+if (common->utfpeakcharback != NULL)+ {+ set_jumps(common->utfpeakcharback, LABEL());+ do_utfpeakcharback(common);+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16+if (common->utfreadchar_invalid != NULL)+ {+ set_jumps(common->utfreadchar_invalid, LABEL());+ do_utfreadchar_invalid(common);+ }+if (common->utfreadnewline_invalid != NULL)+ {+ set_jumps(common->utfreadnewline_invalid, LABEL());+ do_utfreadnewline_invalid(common);+ }+if (common->utfmoveback_invalid)+ {+ set_jumps(common->utfmoveback_invalid, LABEL());+ do_utfmoveback_invalid(common);+ }+if (common->utfpeakcharback_invalid)+ {+ set_jumps(common->utfpeakcharback_invalid, LABEL());+ do_utfpeakcharback_invalid(common);+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16 */+if (common->getucd != NULL)+ {+ set_jumps(common->getucd, LABEL());+ do_getucd(common);+ }+if (common->getucdtype != NULL)+ {+ set_jumps(common->getucdtype, LABEL());+ do_getucdtype(common);+ }+#endif /* SUPPORT_UNICODE */++SLJIT_FREE(common->optimized_cbracket, allocator_data);+SLJIT_FREE(common->private_data_ptrs, allocator_data);++executable_func = sljit_generate_code(compiler, 0, NULL);+executable_size = sljit_get_generated_code_size(compiler);+sljit_free_compiler(compiler);++if (executable_func == NULL)+ {+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++/* Reuse the function descriptor if possible. */+if (re->executable_jit != NULL)+ functions = (executable_functions *)re->executable_jit;+else+ {+ functions = SLJIT_MALLOC(sizeof(executable_functions), allocator_data);+ if (functions == NULL)+ {+ /* This case is highly unlikely since we just recently+ freed a lot of memory. Not impossible though. */+ sljit_free_code(executable_func, NULL);+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }+ memset(functions, 0, sizeof(executable_functions));+ functions->top_bracket = re->top_bracket + 1;+ functions->limit_match = re->limit_match;+ re->executable_jit = functions;+ }++/* Turn mode into an index. */+if (mode == PCRE2_JIT_COMPLETE)+ mode = 0;+else+ mode = (mode == PCRE2_JIT_PARTIAL_SOFT) ? 1 : 2;++SLJIT_ASSERT(mode < JIT_NUMBER_OF_COMPILE_MODES);+functions->executable_funcs[mode] = executable_func;+functions->read_only_data_heads[mode] = common->read_only_data_head;+functions->executable_sizes[mode] = executable_size;+return 0;+}++#endif++/*************************************************+* JIT compile a Regular Expression *+*************************************************/++/* This function used JIT to convert a previously-compiled pattern into machine+code.++Arguments:+ code a compiled pattern+ options JIT option bits++Returns: 0: success or (*NOJIT) was used+ <0: an error code+*/++#define PUBLIC_JIT_COMPILE_OPTIONS \+ (PCRE2_JIT_COMPLETE|PCRE2_JIT_PARTIAL_SOFT|PCRE2_JIT_PARTIAL_HARD|PCRE2_JIT_INVALID_UTF)++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_jit_compile(pcre2_code *code, uint32_t options)+{+pcre2_real_code *re = (pcre2_real_code *)code;+#ifdef SUPPORT_JIT+executable_functions *functions;+static int executable_allocator_is_working = -1;+#endif++if (code == NULL)+ return PCRE2_ERROR_NULL;++if ((options & ~PUBLIC_JIT_COMPILE_OPTIONS) != 0)+ return PCRE2_ERROR_JIT_BADOPTION;++/* Support for invalid UTF was first introduced in JIT, with the option+PCRE2_JIT_INVALID_UTF. Later, support was added to the interpreter, and the+compile-time option PCRE2_MATCH_INVALID_UTF was created. This is now the+preferred feature, with the earlier option deprecated. However, for backward+compatibility, if the earlier option is set, it forces the new option so that+if JIT matching falls back to the interpreter, there is still support for+invalid UTF. However, if this function has already been successfully called+without PCRE2_JIT_INVALID_UTF and without PCRE2_MATCH_INVALID_UTF (meaning that+non-invalid-supporting JIT code was compiled), give an error.++If in the future support for PCRE2_JIT_INVALID_UTF is withdrawn, the following+actions are needed:++ 1. Remove the definition from pcre2.h.in and from the list in+ PUBLIC_JIT_COMPILE_OPTIONS above.++ 2. Replace PCRE2_JIT_INVALID_UTF with a local flag in this module.++ 3. Replace PCRE2_JIT_INVALID_UTF in pcre2_jit_test.c.++ 4. Delete the following short block of code. The setting of "re" and+ "functions" can be moved into the JIT-only block below, but if that is+ done, (void)re and (void)functions will be needed in the non-JIT case, to+ avoid compiler warnings.+*/++#ifdef SUPPORT_JIT+functions = (executable_functions *)re->executable_jit;+#endif++if ((options & PCRE2_JIT_INVALID_UTF) != 0)+ {+ if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) == 0)+ {+#ifdef SUPPORT_JIT+ if (functions != NULL) return PCRE2_ERROR_JIT_BADOPTION;+#endif+ re->overall_options |= PCRE2_MATCH_INVALID_UTF;+ }+ }++/* The above tests are run with and without JIT support. This means that+PCRE2_JIT_INVALID_UTF propagates back into the regex options (ensuring+interpreter support) even in the absence of JIT. But now, if there is no JIT+support, give an error return. */++#ifndef SUPPORT_JIT+return PCRE2_ERROR_JIT_BADOPTION;+#else /* SUPPORT_JIT */++/* There is JIT support. Do the necessary. */++if ((re->flags & PCRE2_NOJIT) != 0) return 0;++if (executable_allocator_is_working == -1)+ {+ /* Checks whether the executable allocator is working. This check+ might run multiple times in multi-threaded environments, but the+ result should not be affected by it. */+ void *ptr = SLJIT_MALLOC_EXEC(32, NULL);+ if (ptr != NULL)+ {+ SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr), NULL);+ executable_allocator_is_working = 1;+ }+ else executable_allocator_is_working = 0;+ }++if (!executable_allocator_is_working) return PCRE2_ERROR_NOMEMORY; if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)
src/c/pcre2/src/pcre2_jit_match.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2018 University of Cambridge+ New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -42,6 +42,12 @@ #error This file must be included from pcre2_jit_compile.c. #endif +#if defined(__has_feature)+#if __has_feature(memory_sanitizer)+#include <sanitizer/msan_interface.h>+#endif /* __has_feature(memory_sanitizer) */+#endif /* defined(__has_feature) */+ #ifdef SUPPORT_JIT static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, jit_function executable_func)@@ -171,12 +177,20 @@ rc = 0; match_data->code = re; match_data->subject = (rc >= 0 || rc == PCRE2_ERROR_PARTIAL)? subject : NULL;+match_data->subject_length = length; match_data->rc = rc; match_data->startchar = arguments.startchar_ptr - subject; match_data->leftchar = 0; match_data->rightchar = 0; match_data->mark = arguments.mark_ptr; match_data->matchedby = PCRE2_MATCHEDBY_JIT;++#if defined(__has_feature)+#if __has_feature(memory_sanitizer)+if (rc > 0)+ __msan_unpoison(match_data->ovector, 2 * rc * sizeof(match_data->ovector[0]));+#endif /* __has_feature(memory_sanitizer) */+#endif /* defined(__has_feature) */ return match_data->rc;
src/c/pcre2/src/pcre2_jit_misc.c view
@@ -110,8 +110,10 @@ (void)gcontext; /* Suppress warning */ #else /* SUPPORT_JIT */ SLJIT_UNUSED_ARG(gcontext);+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) sljit_free_unused_memory_exec();-#endif /* SUPPORT_JIT */+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */+#endif /* SUPPORT_JIT */ } @@ -139,8 +141,8 @@ return NULL; if (startsize > maxsize) startsize = maxsize;-startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);-maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);+startsize = (startsize + STACK_GROWTH_RATE - 1) & (size_t)(~(STACK_GROWTH_RATE - 1));+maxsize = (maxsize + STACK_GROWTH_RATE - 1) & (size_t)(~(STACK_GROWTH_RATE - 1)); jit_stack = PRIV(memctl_malloc)(sizeof(pcre2_real_jit_stack), (pcre2_memctl *)gcontext); if (jit_stack == NULL) return NULL;
src/c/pcre2/src/pcre2_jit_neon_inc.h view
@@ -82,7 +82,12 @@ # endif # endif -static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 *str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)+#if (defined(__GNUC__) && __SANITIZE_ADDRESS__) \+ || (defined(__clang__) \+ && ((__clang_major__ == 3 && __clang_minor__ >= 3) || (__clang_major__ > 3)))+__attribute__((no_sanitize_address))+#endif+static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 **str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars) #undef FF_FUN { quad_word qw;@@ -171,7 +176,7 @@ } # endif -str_ptr += IN_UCHARS(offs1);+*str_ptr += IN_UCHARS(offs1); #endif #if PCRE2_CODE_UNIT_WIDTH != 8@@ -183,11 +188,13 @@ #endif #if defined(FFCPS)-sljit_u8 *p1 = str_ptr - diff;+if (*str_ptr >= str_end)+ return NULL;+sljit_u8 *p1 = *str_ptr - diff; #endif-sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);-str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);-vect_t data = VLD1Q(str_ptr);+sljit_s32 align_offset = ((uint64_t)*str_ptr & 0xf);+*str_ptr = (sljit_u8 *) ((uint64_t)*str_ptr & ~0xf);+vect_t data = VLD1Q(*str_ptr); #if PCRE2_CODE_UNIT_WIDTH != 8 data = VANDQ(data, char_mask); #endif@@ -210,9 +217,9 @@ # endif vect_t data2;-if (p1 < str_ptr)+if (p1 < *str_ptr) {- data2 = VLD1Q(str_ptr - diff);+ data2 = VLD1Q(*str_ptr - diff); #if PCRE2_CODE_UNIT_WIDTH != 8 data2 = VANDQ(data2, char_mask); #endif@@ -240,12 +247,12 @@ qw.dw[0] >>= align_offset * 8; if (qw.dw[0]) {- str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;+ *str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8; goto match; } if (qw.dw[1]) {- str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;+ *str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8; goto match; } }@@ -254,15 +261,15 @@ qw.dw[1] >>= (align_offset - 8) * 8; if (qw.dw[1]) {- str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;+ *str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8; goto match; } }-str_ptr += 16;+*str_ptr += 16; -while (str_ptr < str_end)+while (*str_ptr < str_end) {- vect_t orig_data = VLD1Q(str_ptr);+ vect_t orig_data = VLD1Q(*str_ptr); #if PCRE2_CODE_UNIT_WIDTH != 8 orig_data = VANDQ(orig_data, char_mask); #endif@@ -285,7 +292,7 @@ # if defined (FFCPS_DIFF1) data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1); # else- data2 = VLD1Q(str_ptr - diff);+ data2 = VLD1Q(*str_ptr - diff); # if PCRE2_CODE_UNIT_WIDTH != 8 data2 = VANDQ(data2, char_mask); # endif@@ -310,11 +317,11 @@ VST1Q(qw.mem, eq); if (qw.dw[0])- str_ptr += __builtin_ctzll(qw.dw[0]) / 8;+ *str_ptr += __builtin_ctzll(qw.dw[0]) / 8; else if (qw.dw[1])- str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;+ *str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8; else {- str_ptr += 16;+ *str_ptr += 16; #if defined (FFCPS_DIFF1) prev_data = orig_data; #endif@@ -322,24 +329,24 @@ } match:;- if (str_ptr >= str_end)+ if (*str_ptr >= str_end) /* Failed match. */ return NULL; #if defined(FF_UTF)- if (utf_continue(str_ptr + IN_UCHARS(-offs1)))+ if (utf_continue((PCRE2_SPTR)*str_ptr - offs1)) { /* Not a match. */- str_ptr += IN_UCHARS(1);+ *str_ptr += IN_UCHARS(1); goto restart; } #endif /* Match. */ #if defined (FFCPS)- str_ptr -= IN_UCHARS(offs1);+ *str_ptr -= IN_UCHARS(offs1); #endif- return str_ptr;+ return *str_ptr; } /* Failed match. */
src/c/pcre2/src/pcre2_jit_simd_inc.h view
@@ -42,1817 +42,2314 @@ #if !(defined SUPPORT_VALGRIND) #if ((defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \- || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X))--typedef enum {- vector_compare_match1,- vector_compare_match1i,- vector_compare_match2,-} vector_compare_type;--static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)-{-#if PCRE2_CODE_UNIT_WIDTH == 8-return 15;-#elif PCRE2_CODE_UNIT_WIDTH == 16-return 7;-#elif PCRE2_CODE_UNIT_WIDTH == 32-return 3;-#else-#error "Unsupported unit width"-#endif-}--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-static struct sljit_jump *jump_if_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg)-{-#if PCRE2_CODE_UNIT_WIDTH == 8-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);-return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0x80);-#elif PCRE2_CODE_UNIT_WIDTH == 16-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);-return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00);-#else-#error "Unknown code width"-#endif-}-#endif--#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_S390X */--#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)--static sljit_s32 character_to_int32(PCRE2_UCHAR chr)-{-sljit_u32 value = chr;-#if PCRE2_CODE_UNIT_WIDTH == 8-#define SSE2_COMPARE_TYPE_INDEX 0-return (sljit_s32)((value << 24) | (value << 16) | (value << 8) | value);-#elif PCRE2_CODE_UNIT_WIDTH == 16-#define SSE2_COMPARE_TYPE_INDEX 1-return (sljit_s32)((value << 16) | value);-#elif PCRE2_CODE_UNIT_WIDTH == 32-#define SSE2_COMPARE_TYPE_INDEX 2-return (sljit_s32)(value);-#else-#error "Unsupported unit width"-#endif-}--static void load_from_mem_sse2(struct sljit_compiler *compiler, sljit_s32 dst_xmm_reg, sljit_s32 src_general_reg, sljit_s8 offset)-{-sljit_u8 instruction[5];--SLJIT_ASSERT(dst_xmm_reg < 8);-SLJIT_ASSERT(src_general_reg < 8);--/* MOVDQA xmm1, xmm2/m128 */-instruction[0] = ((sljit_u8)offset & 0xf) == 0 ? 0x66 : 0xf3;-instruction[1] = 0x0f;-instruction[2] = 0x6f;--if (offset == 0)- {- instruction[3] = (dst_xmm_reg << 3) | src_general_reg;- sljit_emit_op_custom(compiler, instruction, 4);- return;- }--instruction[3] = 0x40 | (dst_xmm_reg << 3) | src_general_reg;-instruction[4] = (sljit_u8)offset;-sljit_emit_op_custom(compiler, instruction, 5);-}--static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, vector_compare_type compare_type,- int step, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)-{-sljit_u8 instruction[4];-instruction[0] = 0x66;-instruction[1] = 0x0f;--SLJIT_ASSERT(step >= 0 && step <= 3);--if (compare_type != vector_compare_match2)- {- if (step == 0)- {- if (compare_type == vector_compare_match1i)- {- /* POR xmm1, xmm2/m128 */- /* instruction[0] = 0x66; */- /* instruction[1] = 0x0f; */- instruction[2] = 0xeb;- instruction[3] = 0xc0 | (dst_ind << 3) | cmp2_ind;- sljit_emit_op_custom(compiler, instruction, 4);- }- return;- }-- if (step != 2)- return;-- /* PCMPEQB/W/D xmm1, xmm2/m128 */- /* instruction[0] = 0x66; */- /* instruction[1] = 0x0f; */- instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;- instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;- sljit_emit_op_custom(compiler, instruction, 4);- return;- }--switch (step)- {- case 0:- /* MOVDQA xmm1, xmm2/m128 */- /* instruction[0] = 0x66; */- /* instruction[1] = 0x0f; */- instruction[2] = 0x6f;- instruction[3] = 0xc0 | (tmp_ind << 3) | dst_ind;- sljit_emit_op_custom(compiler, instruction, 4);- return;-- case 1:- /* PCMPEQB/W/D xmm1, xmm2/m128 */- /* instruction[0] = 0x66; */- /* instruction[1] = 0x0f; */- instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;- instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;- sljit_emit_op_custom(compiler, instruction, 4);- return;-- case 2:- /* PCMPEQB/W/D xmm1, xmm2/m128 */- /* instruction[0] = 0x66; */- /* instruction[1] = 0x0f; */- instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;- instruction[3] = 0xc0 | (tmp_ind << 3) | cmp2_ind;- sljit_emit_op_custom(compiler, instruction, 4);- return;-- case 3:- /* POR xmm1, xmm2/m128 */- /* instruction[0] = 0x66; */- /* instruction[1] = 0x0f; */- instruction[2] = 0xeb;- instruction[3] = 0xc0 | (dst_ind << 3) | tmp_ind;- sljit_emit_op_custom(compiler, instruction, 4);- return;- }-}--#define JIT_HAS_FAST_FORWARD_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))--static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)-{-DEFINE_COMPILER;-sljit_u8 instruction[8];-struct sljit_label *start;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-struct sljit_label *restart;-#endif-struct sljit_jump *quit;-struct sljit_jump *partial_quit[2];-vector_compare_type compare_type = vector_compare_match1;-sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);-sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);-sljit_s32 data_ind = 0;-sljit_s32 tmp_ind = 1;-sljit_s32 cmp1_ind = 2;-sljit_s32 cmp2_ind = 3;-sljit_u32 bit = 0;-int i;--SLJIT_UNUSED_ARG(offset);--if (char1 != char2)- {- bit = char1 ^ char2;- compare_type = vector_compare_match1i;-- if (!is_powerof2(bit))- {- bit = 0;- compare_type = vector_compare_match2;- }- }--partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-if (common->mode == PCRE2_JIT_COMPLETE)- add_jump(compiler, &common->failed_match, partial_quit[0]);--/* First part (unaligned start) */--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));--SLJIT_ASSERT(tmp1_reg_ind < 8);--/* MOVD xmm, r/m32 */-instruction[0] = 0x66;-instruction[1] = 0x0f;-instruction[2] = 0x6e;-instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_reg_ind;-sljit_emit_op_custom(compiler, instruction, 4);--if (char1 != char2)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));-- /* MOVD xmm, r/m32 */- instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_reg_ind;- sljit_emit_op_custom(compiler, instruction, 4);- }--OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);--/* PSHUFD xmm1, xmm2/m128, imm8 */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0x70;-instruction[3] = 0xc0 | (cmp1_ind << 3) | cmp1_ind;-instruction[4] = 0;-sljit_emit_op_custom(compiler, instruction, 5);--if (char1 != char2)- {- /* PSHUFD xmm1, xmm2/m128, imm8 */- instruction[3] = 0xc0 | (cmp2_ind << 3) | cmp2_ind;- sljit_emit_op_custom(compiler, instruction, 5);- }--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-restart = LABEL();-#endif-OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);--load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);-for (i = 0; i < 4; i++)- fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);--/* PMOVMSKB reg, xmm */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0xd7;-instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;-sljit_emit_op_custom(compiler, instruction, 4);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);-OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);--quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);--/* Second part (aligned) */-start = LABEL();--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);--partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-if (common->mode == PCRE2_JIT_COMPLETE)- add_jump(compiler, &common->failed_match, partial_quit[1]);--load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);-for (i = 0; i < 4; i++)- fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);--/* PMOVMSKB reg, xmm */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0xd7;-instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;-sljit_emit_op_custom(compiler, instruction, 4);--CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);--JUMPHERE(quit);--/* BSF r32, r/m32 */-instruction[0] = 0x0f;-instruction[1] = 0xbc;-instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;-sljit_emit_op_custom(compiler, instruction, 3);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);--if (common->mode != PCRE2_JIT_COMPLETE)- {- JUMPHERE(partial_quit[0]);- JUMPHERE(partial_quit[1]);- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);- CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);- }-else- add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-if (common->utf && offset > 0)- {- SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);-- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));-- quit = jump_if_utf_char_start(compiler, TMP1);-- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));- OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);- JUMPTO(SLJIT_JUMP, restart);-- JUMPHERE(quit);- }-#endif-}--#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))--static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)-{-DEFINE_COMPILER;-sljit_u8 instruction[8];-struct sljit_label *start;-struct sljit_jump *quit;-jump_list *not_found = NULL;-vector_compare_type compare_type = vector_compare_match1;-sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);-sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);-sljit_s32 data_ind = 0;-sljit_s32 tmp_ind = 1;-sljit_s32 cmp1_ind = 2;-sljit_s32 cmp2_ind = 3;-sljit_u32 bit = 0;-int i;--if (char1 != char2)- {- bit = char1 ^ char2;- compare_type = vector_compare_match1i;-- if (!is_powerof2(bit))- {- bit = 0;- compare_type = vector_compare_match2;- }- }--add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));-OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);-OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);--/* First part (unaligned start) */--OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));--SLJIT_ASSERT(tmp1_reg_ind < 8);--/* MOVD xmm, r/m32 */-instruction[0] = 0x66;-instruction[1] = 0x0f;-instruction[2] = 0x6e;-instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_reg_ind;-sljit_emit_op_custom(compiler, instruction, 4);--if (char1 != char2)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));-- /* MOVD xmm, r/m32 */- instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_reg_ind;- sljit_emit_op_custom(compiler, instruction, 4);- }--OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);--/* PSHUFD xmm1, xmm2/m128, imm8 */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0x70;-instruction[3] = 0xc0 | (cmp1_ind << 3) | cmp1_ind;-instruction[4] = 0;-sljit_emit_op_custom(compiler, instruction, 5);--if (char1 != char2)- {- /* PSHUFD xmm1, xmm2/m128, imm8 */- instruction[3] = 0xc0 | (cmp2_ind << 3) | cmp2_ind;- sljit_emit_op_custom(compiler, instruction, 5);- }--OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);--load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);-for (i = 0; i < 4; i++)- fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);--/* PMOVMSKB reg, xmm */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0xd7;-instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;-sljit_emit_op_custom(compiler, instruction, 4);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);-OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);--quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);--/* Second part (aligned) */-start = LABEL();--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);--add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));--load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);-for (i = 0; i < 4; i++)- fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);--/* PMOVMSKB reg, xmm */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0xd7;-instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;-sljit_emit_op_custom(compiler, instruction, 4);--CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);--JUMPHERE(quit);--/* BSF r32, r/m32 */-instruction[0] = 0x0f;-instruction[1] = 0xbc;-instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;-sljit_emit_op_custom(compiler, instruction, 3);--OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, STR_PTR, 0);-add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));--OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);-return not_found;-}--#ifndef _WIN64--#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))--static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,- PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)-{-DEFINE_COMPILER;-sljit_u8 instruction[8];-vector_compare_type compare1_type = vector_compare_match1;-vector_compare_type compare2_type = vector_compare_match1;-sljit_u32 bit1 = 0;-sljit_u32 bit2 = 0;-sljit_u32 diff = IN_UCHARS(offs1 - offs2);-sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);-sljit_s32 tmp2_reg_ind = sljit_get_register_index(TMP2);-sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);-sljit_s32 data1_ind = 0;-sljit_s32 data2_ind = 1;-sljit_s32 tmp1_ind = 2;-sljit_s32 tmp2_ind = 3;-sljit_s32 cmp1a_ind = 4;-sljit_s32 cmp1b_ind = 5;-sljit_s32 cmp2a_ind = 6;-sljit_s32 cmp2b_ind = 7;-struct sljit_label *start;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-struct sljit_label *restart;-#endif-struct sljit_jump *jump[2];-int i;--SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);-SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));-SLJIT_ASSERT(tmp1_reg_ind < 8 && tmp2_reg_ind == 1);--/* Initialize. */-if (common->match_end_ptr != 0)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);- OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));-- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, STR_END, 0);- CMOV(SLJIT_LESS, STR_END, TMP1, 0);- }--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));--/* MOVD xmm, r/m32 */-instruction[0] = 0x66;-instruction[1] = 0x0f;-instruction[2] = 0x6e;--if (char1a == char1b)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));-else- {- bit1 = char1a ^ char1b;- if (is_powerof2(bit1))- {- compare1_type = vector_compare_match1i;- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a | bit1));- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit1));- }- else- {- compare1_type = vector_compare_match2;- bit1 = 0;- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char1b));- }- }--instruction[3] = 0xc0 | (cmp1a_ind << 3) | tmp1_reg_ind;-sljit_emit_op_custom(compiler, instruction, 4);--if (char1a != char1b)- {- instruction[3] = 0xc0 | (cmp1b_ind << 3) | tmp2_reg_ind;- sljit_emit_op_custom(compiler, instruction, 4);- }--if (char2a == char2b)- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));-else- {- bit2 = char2a ^ char2b;- if (is_powerof2(bit2))- {- compare2_type = vector_compare_match1i;- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a | bit2));- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit2));- }- else- {- compare2_type = vector_compare_match2;- bit2 = 0;- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char2b));- }- }--instruction[3] = 0xc0 | (cmp2a_ind << 3) | tmp1_reg_ind;-sljit_emit_op_custom(compiler, instruction, 4);--if (char2a != char2b)- {- instruction[3] = 0xc0 | (cmp2b_ind << 3) | tmp2_reg_ind;- sljit_emit_op_custom(compiler, instruction, 4);- }--/* PSHUFD xmm1, xmm2/m128, imm8 */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0x70;-instruction[4] = 0;--instruction[3] = 0xc0 | (cmp1a_ind << 3) | cmp1a_ind;-sljit_emit_op_custom(compiler, instruction, 5);--if (char1a != char1b)- {- instruction[3] = 0xc0 | (cmp1b_ind << 3) | cmp1b_ind;- sljit_emit_op_custom(compiler, instruction, 5);- }--instruction[3] = 0xc0 | (cmp2a_ind << 3) | cmp2a_ind;-sljit_emit_op_custom(compiler, instruction, 5);--if (char2a != char2b)- {- instruction[3] = 0xc0 | (cmp2b_ind << 3) | cmp2b_ind;- sljit_emit_op_custom(compiler, instruction, 5);- }--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-restart = LABEL();-#endif--OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, diff);-OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);-OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);--load_from_mem_sse2(compiler, data1_ind, str_ptr_reg_ind, 0);--jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0);--load_from_mem_sse2(compiler, data2_ind, str_ptr_reg_ind, -(sljit_s8)diff);-jump[1] = JUMP(SLJIT_JUMP);--JUMPHERE(jump[0]);--/* MOVDQA xmm1, xmm2/m128 */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0x6f;-instruction[3] = 0xc0 | (data2_ind << 3) | data1_ind;-sljit_emit_op_custom(compiler, instruction, 4);--/* PSLLDQ xmm1, imm8 */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0x73;-instruction[3] = 0xc0 | (7 << 3) | data2_ind;-instruction[4] = diff;-sljit_emit_op_custom(compiler, instruction, 5);--JUMPHERE(jump[1]);--OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);--for (i = 0; i < 4; i++)- {- fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);- fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);- }--/* PAND xmm1, xmm2/m128 */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0xdb;-instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;-sljit_emit_op_custom(compiler, instruction, 4);--/* PMOVMSKB reg, xmm */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0xd7;-instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | 0;-sljit_emit_op_custom(compiler, instruction, 4);--/* Ignore matches before the first STR_PTR. */-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);-OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);--jump[0] = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);--/* Main loop. */-start = LABEL();--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));--load_from_mem_sse2(compiler, data1_ind, str_ptr_reg_ind, 0);-load_from_mem_sse2(compiler, data2_ind, str_ptr_reg_ind, -(sljit_s8)diff);--for (i = 0; i < 4; i++)- {- fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp2_ind);- fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp1_ind);- }--/* PAND xmm1, xmm2/m128 */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0xdb;-instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;-sljit_emit_op_custom(compiler, instruction, 4);--/* PMOVMSKB reg, xmm */-/* instruction[0] = 0x66; */-/* instruction[1] = 0x0f; */-instruction[2] = 0xd7;-instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | 0;-sljit_emit_op_custom(compiler, instruction, 4);--CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);--JUMPHERE(jump[0]);--/* BSF r32, r/m32 */-instruction[0] = 0x0f;-instruction[1] = 0xbc;-instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;-sljit_emit_op_custom(compiler, instruction, 3);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);--add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-if (common->utf)- {- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));-- jump[0] = jump_if_utf_char_start(compiler, TMP1);-- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart);-- add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP));-- JUMPHERE(jump[0]);- }-#endif--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));--if (common->match_end_ptr != 0)- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);-}--#endif /* !_WIN64 */--#undef SSE2_COMPARE_TYPE_INDEX--#endif /* SLJIT_CONFIG_X86 */--#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 && (defined __ARM_NEON || defined __ARM_NEON__))--#include <arm_neon.h>--typedef union {- unsigned int x;- struct { unsigned char c1, c2, c3, c4; } c;-} int_char;--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-static SLJIT_INLINE int utf_continue(sljit_u8 *s)-{-#if PCRE2_CODE_UNIT_WIDTH == 8-return (*s & 0xc0) == 0x80;-#elif PCRE2_CODE_UNIT_WIDTH == 16-return (*s & 0xfc00) == 0xdc00;-#else-#error "Unknown code width"-#endif-}-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */--#if PCRE2_CODE_UNIT_WIDTH == 8-# define VECTOR_FACTOR 16-# define vect_t uint8x16_t-# define VLD1Q(X) vld1q_u8((sljit_u8 *)(X))-# define VCEQQ vceqq_u8-# define VORRQ vorrq_u8-# define VST1Q vst1q_u8-# define VDUPQ vdupq_n_u8-# define VEXTQ vextq_u8-# define VANDQ vandq_u8-typedef union {- uint8_t mem[16];- uint64_t dw[2];-} quad_word;-#elif PCRE2_CODE_UNIT_WIDTH == 16-# define VECTOR_FACTOR 8-# define vect_t uint16x8_t-# define VLD1Q(X) vld1q_u16((sljit_u16 *)(X))-# define VCEQQ vceqq_u16-# define VORRQ vorrq_u16-# define VST1Q vst1q_u16-# define VDUPQ vdupq_n_u16-# define VEXTQ vextq_u16-# define VANDQ vandq_u16-typedef union {- uint16_t mem[8];- uint64_t dw[2];-} quad_word;-#else-# define VECTOR_FACTOR 4-# define vect_t uint32x4_t-# define VLD1Q(X) vld1q_u32((sljit_u32 *)(X))-# define VCEQQ vceqq_u32-# define VORRQ vorrq_u32-# define VST1Q vst1q_u32-# define VDUPQ vdupq_n_u32-# define VEXTQ vextq_u32-# define VANDQ vandq_u32-typedef union {- uint32_t mem[4];- uint64_t dw[2];-} quad_word;-#endif--#define FFCS-#include "pcre2_jit_neon_inc.h"-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-# define FF_UTF-# include "pcre2_jit_neon_inc.h"-# undef FF_UTF-#endif-#undef FFCS--#define FFCS_2-#include "pcre2_jit_neon_inc.h"-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-# define FF_UTF-# include "pcre2_jit_neon_inc.h"-# undef FF_UTF-#endif-#undef FFCS_2--#define FFCS_MASK-#include "pcre2_jit_neon_inc.h"-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-# define FF_UTF-# include "pcre2_jit_neon_inc.h"-# undef FF_UTF-#endif-#undef FFCS_MASK--#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1--static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)-{-DEFINE_COMPILER;-int_char ic;-struct sljit_jump *partial_quit;-/* Save temporary registers. */-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP3, 0);--/* Prepare function arguments */-OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);-OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0);-OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, offset);--if (char1 == char2)- {- ic.c.c1 = char1;- ic.c.c2 = char2;- OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf && offset > 0)- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_utf));- else- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs));-#else- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs));-#endif- }-else- {- PCRE2_UCHAR mask = char1 ^ char2;- if (is_powerof2(mask))- {- ic.c.c1 = char1 | mask;- ic.c.c2 = mask;- OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf && offset > 0)- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask_utf));- else- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask));-#else- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask));-#endif- }- else- {- ic.c.c1 = char1;- ic.c.c2 = char2;- OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf && offset > 0)- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2_utf));- else- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2));-#else- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2));-#endif- }- }-/* Restore registers. */-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);-OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);--/* Check return value. */-partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);-if (common->mode == PCRE2_JIT_COMPLETE)- add_jump(compiler, &common->failed_match, partial_quit);--/* Fast forward STR_PTR to the result of memchr. */-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);--if (common->mode != PCRE2_JIT_COMPLETE)- JUMPHERE(partial_quit);-}--typedef enum {- compare_match1,- compare_match1i,- compare_match2,-} compare_type;--static inline vect_t fast_forward_char_pair_compare(compare_type ctype, vect_t dst, vect_t cmp1, vect_t cmp2)-{-if (ctype == compare_match2)- {- vect_t tmp = dst;- dst = VCEQQ(dst, cmp1);- tmp = VCEQQ(tmp, cmp2);- dst = VORRQ(dst, tmp);- return dst;- }--if (ctype == compare_match1i)- dst = VORRQ(dst, cmp2);-dst = VCEQQ(dst, cmp1);-return dst;-}--static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)-{-#if PCRE2_CODE_UNIT_WIDTH == 8-return 15;-#elif PCRE2_CODE_UNIT_WIDTH == 16-return 7;-#elif PCRE2_CODE_UNIT_WIDTH == 32-return 3;-#else-#error "Unsupported unit width"-#endif-}--/* ARM doesn't have a shift left across lanes. */-static SLJIT_INLINE vect_t shift_left_n_lanes(vect_t a, sljit_u8 n)-{-vect_t zero = VDUPQ(0);-SLJIT_ASSERT(0 < n && n < VECTOR_FACTOR);-/* VEXTQ takes an immediate as last argument. */-#define C(X) case X: return VEXTQ(zero, a, VECTOR_FACTOR - X);-switch (n)- {- C(1); C(2); C(3);-#if PCRE2_CODE_UNIT_WIDTH != 32- C(4); C(5); C(6); C(7);-# if PCRE2_CODE_UNIT_WIDTH != 16- C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15);-# endif-#endif- default:- /* Based on the ASSERT(0 < n && n < VECTOR_FACTOR) above, this won't- happen. The return is still here for compilers to not warn. */- return a;- }-}--#define FFCPS-#define FFCPS_DIFF1-#define FFCPS_CHAR1A2A--#define FFCPS_0-#include "pcre2_jit_neon_inc.h"-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-# define FF_UTF-# include "pcre2_jit_neon_inc.h"-# undef FF_UTF-#endif-#undef FFCPS_0--#undef FFCPS_CHAR1A2A--#define FFCPS_1-#include "pcre2_jit_neon_inc.h"-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-# define FF_UTF-# include "pcre2_jit_neon_inc.h"-# undef FF_UTF-#endif-#undef FFCPS_1--#undef FFCPS_DIFF1--#define FFCPS_DEFAULT-#include "pcre2_jit_neon_inc.h"-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-# define FF_UTF-# include "pcre2_jit_neon_inc.h"-# undef FF_UTF-#endif-#undef FFCPS--#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1--static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,- PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)-{-DEFINE_COMPILER;-sljit_u32 diff = IN_UCHARS(offs1 - offs2);-struct sljit_jump *partial_quit;-int_char ic;-SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);-SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));-SLJIT_ASSERT(compiler->scratches == 5);--/* Save temporary register STR_PTR. */-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);--/* Prepare arguments for the function call. */-if (common->match_end_ptr == 0)- OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);-else- {- OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);- OP2(SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));-- OP2U(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, SLJIT_R0, 0);- CMOV(SLJIT_LESS, SLJIT_R0, STR_END, 0);- }--OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0); -OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_IMM, offs1);-OP1(SLJIT_MOV_S32, SLJIT_R3, 0, SLJIT_IMM, offs2);-ic.c.c1 = char1a;-ic.c.c2 = char1b;-ic.c.c3 = char2a;-ic.c.c4 = char2b;-OP1(SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_IMM, ic.x);--if (diff == 1) {- if (char1a == char1b && char2a == char2b) {-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf)- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_0_utf));- else-#endif- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_0));- } else {-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf)- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_1_utf));- else-#endif- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_1));- }-} else {-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32- if (common->utf)- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_default_utf));- else-#endif- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_default));-}--/* Restore STR_PTR register. */-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);--/* Check return value. */-partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);-add_jump(compiler, &common->failed_match, partial_quit);--/* Fast forward STR_PTR to the result of memchr. */-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);--JUMPHERE(partial_quit);-}--#endif /* SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 */--#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)--#if PCRE2_CODE_UNIT_WIDTH == 8-#define VECTOR_ELEMENT_SIZE 0-#elif PCRE2_CODE_UNIT_WIDTH == 16-#define VECTOR_ELEMENT_SIZE 1-#elif PCRE2_CODE_UNIT_WIDTH == 32-#define VECTOR_ELEMENT_SIZE 2-#else-#error "Unsupported unit width"-#endif--static void load_from_mem_vector(struct sljit_compiler *compiler, BOOL vlbb, sljit_s32 dst_vreg,- sljit_s32 base_reg, sljit_s32 index_reg)-{-sljit_u16 instruction[3];--instruction[0] = (sljit_u16)(0xe700 | (dst_vreg << 4) | index_reg);-instruction[1] = (sljit_u16)(base_reg << 12);-instruction[2] = (sljit_u16)((0x8 << 8) | (vlbb ? 0x07 : 0x06));--sljit_emit_op_custom(compiler, instruction, 6);-}--#if PCRE2_CODE_UNIT_WIDTH == 32--static void replicate_imm_vector(struct sljit_compiler *compiler, int step, sljit_s32 dst_vreg,- PCRE2_UCHAR chr, sljit_s32 tmp_general_reg)-{-sljit_u16 instruction[3];--SLJIT_ASSERT(step >= 0 && step <= 1);--if (chr < 0x7fff)- {- if (step == 1)- return;-- /* VREPI */- instruction[0] = (sljit_u16)(0xe700 | (dst_vreg << 4));- instruction[1] = (sljit_u16)chr;- instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45);- sljit_emit_op_custom(compiler, instruction, 6);- return;- }--if (step == 0)- {- OP1(SLJIT_MOV, tmp_general_reg, 0, SLJIT_IMM, chr);-- /* VLVG */- instruction[0] = (sljit_u16)(0xe700 | (dst_vreg << 4) | sljit_get_register_index(tmp_general_reg));- instruction[1] = 0;- instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x22);- sljit_emit_op_custom(compiler, instruction, 6);- return;- }--/* VREP */-instruction[0] = (sljit_u16)(0xe700 | (dst_vreg << 4) | dst_vreg);-instruction[1] = 0;-instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xc << 8) | 0x4d);-sljit_emit_op_custom(compiler, instruction, 6);-}--#endif--static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, vector_compare_type compare_type,- int step, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)-{-sljit_u16 instruction[3];--SLJIT_ASSERT(step >= 0 && step <= 2);--if (step == 1)- {- /* VCEQ */- instruction[0] = (sljit_u16)(0xe700 | (dst_ind << 4) | dst_ind);- instruction[1] = (sljit_u16)(cmp1_ind << 12);- instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0xf8);- sljit_emit_op_custom(compiler, instruction, 6);- return;- }--if (compare_type != vector_compare_match2)- {- if (step == 0 && compare_type == vector_compare_match1i)- {- /* VO */- instruction[0] = (sljit_u16)(0xe700 | (dst_ind << 4) | dst_ind);- instruction[1] = (sljit_u16)(cmp2_ind << 12);- instruction[2] = (sljit_u16)((0xe << 8) | 0x6a);- sljit_emit_op_custom(compiler, instruction, 6);- }- return;- }--switch (step)- {- case 0:- /* VCEQ */- instruction[0] = (sljit_u16)(0xe700 | (tmp_ind << 4) | dst_ind);- instruction[1] = (sljit_u16)(cmp2_ind << 12);- instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0xf8);- sljit_emit_op_custom(compiler, instruction, 6);- return;-- case 2:- /* VO */- instruction[0] = (sljit_u16)(0xe700 | (dst_ind << 4) | dst_ind);- instruction[1] = (sljit_u16)(tmp_ind << 12);- instruction[2] = (sljit_u16)((0xe << 8) | 0x6a);- sljit_emit_op_custom(compiler, instruction, 6);- return;- }-}--#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1--static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)-{-DEFINE_COMPILER;-sljit_u16 instruction[3];-struct sljit_label *start;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-struct sljit_label *restart;-#endif-struct sljit_jump *quit;-struct sljit_jump *partial_quit[2];-vector_compare_type compare_type = vector_compare_match1;-sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);-sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);-sljit_s32 data_ind = 0;-sljit_s32 tmp_ind = 1;-sljit_s32 cmp1_ind = 2;-sljit_s32 cmp2_ind = 3;-sljit_s32 zero_ind = 4;-sljit_u32 bit = 0;-int i;--SLJIT_UNUSED_ARG(offset);--if (char1 != char2)- {- bit = char1 ^ char2;- compare_type = vector_compare_match1i;-- if (!is_powerof2(bit))- {- bit = 0;- compare_type = vector_compare_match2;- }- }--partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-if (common->mode == PCRE2_JIT_COMPLETE)- add_jump(compiler, &common->failed_match, partial_quit[0]);--/* First part (unaligned start) */--OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 16);--#if PCRE2_CODE_UNIT_WIDTH != 32--/* VREPI */-instruction[0] = (sljit_u16)(0xe700 | (cmp1_ind << 4));-instruction[1] = (sljit_u16)(char1 | bit);-instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45);-sljit_emit_op_custom(compiler, instruction, 6);--if (char1 != char2)- {- /* VREPI */- instruction[0] = (sljit_u16)(0xe700 | (cmp2_ind << 4));- instruction[1] = (sljit_u16)(bit != 0 ? bit : char2);- /* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */- sljit_emit_op_custom(compiler, instruction, 6);- }--#else /* PCRE2_CODE_UNIT_WIDTH == 32 */--for (int i = 0; i < 2; i++)- {- replicate_imm_vector(compiler, i, cmp1_ind, char1 | bit, TMP1);-- if (char1 != char2)- replicate_imm_vector(compiler, i, cmp2_ind, bit != 0 ? bit : char2, TMP1);- }--#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */--if (compare_type == vector_compare_match2)- {- /* VREPI */- instruction[0] = (sljit_u16)(0xe700 | (zero_ind << 4));- instruction[1] = 0;- instruction[2] = (sljit_u16)((0x8 << 8) | 0x45);- sljit_emit_op_custom(compiler, instruction, 6);- }--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-restart = LABEL();-#endif--load_from_mem_vector(compiler, TRUE, data_ind, str_ptr_reg_ind, 0);-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, ~15);--if (compare_type != vector_compare_match2)- {- if (compare_type == vector_compare_match1i)- fast_forward_char_pair_sse2_compare(compiler, compare_type, 0, data_ind, cmp1_ind, cmp2_ind, tmp_ind);-- /* VFEE */- instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);- instruction[1] = (sljit_u16)((cmp1_ind << 12) | (1 << 4));- instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0x80);- sljit_emit_op_custom(compiler, instruction, 6);- }-else- {- for (i = 0; i < 3; i++)- fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);-- /* VFENE */- instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);- instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));- instruction[2] = (sljit_u16)((0xe << 8) | 0x81);- sljit_emit_op_custom(compiler, instruction, 6);- }--/* VLGVB */-instruction[0] = (sljit_u16)(0xe700 | (tmp1_reg_ind << 4) | data_ind);-instruction[1] = 7;-instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);-sljit_emit_op_custom(compiler, instruction, 6);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);-quit = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);--OP2(SLJIT_SUB, STR_PTR, 0, TMP2, 0, SLJIT_IMM, 16);--/* Second part (aligned) */-start = LABEL();--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);--partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);-if (common->mode == PCRE2_JIT_COMPLETE)- add_jump(compiler, &common->failed_match, partial_quit[1]);--load_from_mem_vector(compiler, TRUE, data_ind, str_ptr_reg_ind, 0);--if (compare_type != vector_compare_match2)- {- if (compare_type == vector_compare_match1i)- fast_forward_char_pair_sse2_compare(compiler, compare_type, 0, data_ind, cmp1_ind, cmp2_ind, tmp_ind);-- /* VFEE */- instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);- instruction[1] = (sljit_u16)((cmp1_ind << 12) | (1 << 4));- instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0x80);- sljit_emit_op_custom(compiler, instruction, 6);- }-else- {- for (i = 0; i < 3; i++)- fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);-- /* VFENE */- instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);- instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));- instruction[2] = (sljit_u16)((0xe << 8) | 0x81);- sljit_emit_op_custom(compiler, instruction, 6);- }--sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);-JUMPTO(SLJIT_OVERFLOW, start);--/* VLGVB */-instruction[0] = (sljit_u16)(0xe700 | (tmp1_reg_ind << 4) | data_ind);-instruction[1] = 7;-instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);-sljit_emit_op_custom(compiler, instruction, 6);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);--JUMPHERE(quit);--if (common->mode != PCRE2_JIT_COMPLETE)- {- JUMPHERE(partial_quit[0]);- JUMPHERE(partial_quit[1]);- OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);- CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);- }-else- add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-if (common->utf && offset > 0)- {- SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);-- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));-- quit = jump_if_utf_char_start(compiler, TMP1);-- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));-- OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 16);- JUMPTO(SLJIT_JUMP, restart);-- JUMPHERE(quit);- }-#endif-}--#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD 1--static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)-{-DEFINE_COMPILER;-sljit_u16 instruction[3];-struct sljit_label *start;-struct sljit_jump *quit;-jump_list *not_found = NULL;-vector_compare_type compare_type = vector_compare_match1;-sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);-sljit_s32 tmp3_reg_ind = sljit_get_register_index(TMP3);-sljit_s32 data_ind = 0;-sljit_s32 tmp_ind = 1;-sljit_s32 cmp1_ind = 2;-sljit_s32 cmp2_ind = 3;-sljit_s32 zero_ind = 4;-sljit_u32 bit = 0;-int i;--if (char1 != char2)- {- bit = char1 ^ char2;- compare_type = vector_compare_match1i;-- if (!is_powerof2(bit))- {- bit = 0;- compare_type = vector_compare_match2;- }- }--add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));--/* First part (unaligned start) */--OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, 16);--#if PCRE2_CODE_UNIT_WIDTH != 32--/* VREPI */-instruction[0] = (sljit_u16)(0xe700 | (cmp1_ind << 4));-instruction[1] = (sljit_u16)(char1 | bit);-instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45);-sljit_emit_op_custom(compiler, instruction, 6);--if (char1 != char2)- {- /* VREPI */- instruction[0] = (sljit_u16)(0xe700 | (cmp2_ind << 4));- instruction[1] = (sljit_u16)(bit != 0 ? bit : char2);- /* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */- sljit_emit_op_custom(compiler, instruction, 6);- }--#else /* PCRE2_CODE_UNIT_WIDTH == 32 */--for (int i = 0; i < 2; i++)- {- replicate_imm_vector(compiler, i, cmp1_ind, char1 | bit, TMP3);-- if (char1 != char2)- replicate_imm_vector(compiler, i, cmp2_ind, bit != 0 ? bit : char2, TMP3);- }--#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */--if (compare_type == vector_compare_match2)- {- /* VREPI */- instruction[0] = (sljit_u16)(0xe700 | (zero_ind << 4));- instruction[1] = 0;- instruction[2] = (sljit_u16)((0x8 << 8) | 0x45);- sljit_emit_op_custom(compiler, instruction, 6);- }--load_from_mem_vector(compiler, TRUE, data_ind, tmp1_reg_ind, 0);-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, ~15);--if (compare_type != vector_compare_match2)- {- if (compare_type == vector_compare_match1i)- fast_forward_char_pair_sse2_compare(compiler, compare_type, 0, data_ind, cmp1_ind, cmp2_ind, tmp_ind);-- /* VFEE */- instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);- instruction[1] = (sljit_u16)((cmp1_ind << 12) | (1 << 4));- instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0x80);- sljit_emit_op_custom(compiler, instruction, 6);- }-else- {- for (i = 0; i < 3; i++)- fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);-- /* VFENE */- instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);- instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));- instruction[2] = (sljit_u16)((0xe << 8) | 0x81);- sljit_emit_op_custom(compiler, instruction, 6);- }--/* VLGVB */-instruction[0] = (sljit_u16)(0xe700 | (tmp3_reg_ind << 4) | data_ind);-instruction[1] = 7;-instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);-sljit_emit_op_custom(compiler, instruction, 6);--OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);-quit = CMP(SLJIT_LESS, TMP1, 0, TMP2, 0);--OP2(SLJIT_SUB, TMP1, 0, TMP2, 0, SLJIT_IMM, 16);--/* Second part (aligned) */-start = LABEL();--OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 16);--add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));--load_from_mem_vector(compiler, TRUE, data_ind, tmp1_reg_ind, 0);--if (compare_type != vector_compare_match2)- {- if (compare_type == vector_compare_match1i)- fast_forward_char_pair_sse2_compare(compiler, compare_type, 0, data_ind, cmp1_ind, cmp2_ind, tmp_ind);-- /* VFEE */- instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);- instruction[1] = (sljit_u16)((cmp1_ind << 12) | (1 << 4));- instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0x80);- sljit_emit_op_custom(compiler, instruction, 6);- }-else- {- for (i = 0; i < 3; i++)- fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);-- /* VFENE */- instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);- instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));- instruction[2] = (sljit_u16)((0xe << 8) | 0x81);- sljit_emit_op_custom(compiler, instruction, 6);- }--sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);-JUMPTO(SLJIT_OVERFLOW, start);--/* VLGVB */-instruction[0] = (sljit_u16)(0xe700 | (tmp3_reg_ind << 4) | data_ind);-instruction[1] = 7;-instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);-sljit_emit_op_custom(compiler, instruction, 6);--OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);--JUMPHERE(quit);-add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));--return not_found;-}--#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1--static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,- PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)-{-DEFINE_COMPILER;-sljit_u16 instruction[3];-struct sljit_label *start;-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-struct sljit_label *restart;-#endif-struct sljit_jump *quit;-struct sljit_jump *jump[2];-vector_compare_type compare1_type = vector_compare_match1;-vector_compare_type compare2_type = vector_compare_match1;-sljit_u32 bit1 = 0;-sljit_u32 bit2 = 0;-sljit_s32 diff = IN_UCHARS(offs2 - offs1);-sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);-sljit_s32 tmp2_reg_ind = sljit_get_register_index(TMP2);-sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);-sljit_s32 data1_ind = 0;-sljit_s32 data2_ind = 1;-sljit_s32 tmp1_ind = 2;-sljit_s32 tmp2_ind = 3;-sljit_s32 cmp1a_ind = 4;-sljit_s32 cmp1b_ind = 5;-sljit_s32 cmp2a_ind = 6;-sljit_s32 cmp2b_ind = 7;-sljit_s32 zero_ind = 8;-int i;--SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);-SLJIT_ASSERT(-diff <= (sljit_s32)IN_UCHARS(max_fast_forward_char_pair_offset()));-SLJIT_ASSERT(tmp1_reg_ind != 0 && tmp2_reg_ind != 0);--if (char1a != char1b)- {- bit1 = char1a ^ char1b;- compare1_type = vector_compare_match1i;-- if (!is_powerof2(bit1))- {- bit1 = 0;- compare1_type = vector_compare_match2;- }- }--if (char2a != char2b)- {- bit2 = char2a ^ char2b;- compare2_type = vector_compare_match1i;-- if (!is_powerof2(bit2))- {- bit2 = 0;- compare2_type = vector_compare_match2;- }- }--/* Initialize. */-if (common->match_end_ptr != 0)- {- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);- OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));-- OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, STR_END, 0);- CMOV(SLJIT_LESS, STR_END, TMP1, 0);- }--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));-OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, ~15);--#if PCRE2_CODE_UNIT_WIDTH != 32--OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, -diff);--/* VREPI */-instruction[0] = (sljit_u16)(0xe700 | (cmp1a_ind << 4));-instruction[1] = (sljit_u16)(char1a | bit1);-instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45);-sljit_emit_op_custom(compiler, instruction, 6);--if (char1a != char1b)- {- /* VREPI */- instruction[0] = (sljit_u16)(0xe700 | (cmp1b_ind << 4));- instruction[1] = (sljit_u16)(bit1 != 0 ? bit1 : char1b);- /* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */- sljit_emit_op_custom(compiler, instruction, 6);- }--/* VREPI */-instruction[0] = (sljit_u16)(0xe700 | (cmp2a_ind << 4));-instruction[1] = (sljit_u16)(char2a | bit2);-/* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */-sljit_emit_op_custom(compiler, instruction, 6);--if (char2a != char2b)- {- /* VREPI */- instruction[0] = (sljit_u16)(0xe700 | (cmp2b_ind << 4));- instruction[1] = (sljit_u16)(bit2 != 0 ? bit2 : char2b);- /* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */- sljit_emit_op_custom(compiler, instruction, 6);- }--#else /* PCRE2_CODE_UNIT_WIDTH == 32 */--for (int i = 0; i < 2; i++)- {- replicate_imm_vector(compiler, i, cmp1a_ind, char1a | bit1, TMP1);-- if (char1a != char1b)- replicate_imm_vector(compiler, i, cmp1b_ind, bit1 != 0 ? bit1 : char1b, TMP1);-- replicate_imm_vector(compiler, i, cmp2a_ind, char2a | bit2, TMP1);-- if (char2a != char2b)- replicate_imm_vector(compiler, i, cmp2b_ind, bit2 != 0 ? bit2 : char2b, TMP1);- }--OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, -diff);--#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */--/* VREPI */-instruction[0] = (sljit_u16)(0xe700 | (zero_ind << 4));-instruction[1] = 0;-instruction[2] = (sljit_u16)((0x8 << 8) | 0x45);-sljit_emit_op_custom(compiler, instruction, 6);--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-restart = LABEL();-#endif--jump[0] = CMP(SLJIT_LESS, TMP1, 0, TMP2, 0);-load_from_mem_vector(compiler, TRUE, data2_ind, tmp1_reg_ind, 0);-jump[1] = JUMP(SLJIT_JUMP);-JUMPHERE(jump[0]);-load_from_mem_vector(compiler, FALSE, data2_ind, tmp1_reg_ind, 0);-JUMPHERE(jump[1]);--load_from_mem_vector(compiler, TRUE, data1_ind, str_ptr_reg_ind, 0);-OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 16);--for (i = 0; i < 3; i++)- {- fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);- fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);- }--/* VN */-instruction[0] = (sljit_u16)(0xe700 | (data1_ind << 4) | data1_ind);-instruction[1] = (sljit_u16)(data2_ind << 12);-instruction[2] = (sljit_u16)((0xe << 8) | 0x68);-sljit_emit_op_custom(compiler, instruction, 6);--/* VFENE */-instruction[0] = (sljit_u16)(0xe700 | (data1_ind << 4) | data1_ind);-instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));-instruction[2] = (sljit_u16)((0xe << 8) | 0x81);-sljit_emit_op_custom(compiler, instruction, 6);--/* VLGVB */-instruction[0] = (sljit_u16)(0xe700 | (tmp1_reg_ind << 4) | data1_ind);-instruction[1] = 7;-instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);-sljit_emit_op_custom(compiler, instruction, 6);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);-quit = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);--OP2(SLJIT_SUB, STR_PTR, 0, TMP2, 0, SLJIT_IMM, 16);-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, diff);--/* Main loop. */-start = LABEL();--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));--load_from_mem_vector(compiler, FALSE, data1_ind, str_ptr_reg_ind, 0);-load_from_mem_vector(compiler, FALSE, data2_ind, str_ptr_reg_ind, tmp1_reg_ind);--for (i = 0; i < 3; i++)- {- fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);- fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);- }--/* VN */-instruction[0] = (sljit_u16)(0xe700 | (data1_ind << 4) | data1_ind);-instruction[1] = (sljit_u16)(data2_ind << 12);-instruction[2] = (sljit_u16)((0xe << 8) | 0x68);-sljit_emit_op_custom(compiler, instruction, 6);--/* VFENE */-instruction[0] = (sljit_u16)(0xe700 | (data1_ind << 4) | data1_ind);-instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));-instruction[2] = (sljit_u16)((0xe << 8) | 0x81);-sljit_emit_op_custom(compiler, instruction, 6);--sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);-JUMPTO(SLJIT_OVERFLOW, start);--/* VLGVB */-instruction[0] = (sljit_u16)(0xe700 | (tmp2_reg_ind << 4) | data1_ind);-instruction[1] = 7;-instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);-sljit_emit_op_custom(compiler, instruction, 6);--OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);--JUMPHERE(quit);--add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));--#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32-if (common->utf)- {- SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);-- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));-- quit = jump_if_utf_char_start(compiler, TMP1);-- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));- add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));-- /* TMP1 contains diff. */- OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, ~15);- OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, -diff);- JUMPTO(SLJIT_JUMP, restart);-- JUMPHERE(quit);- }-#endif--OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));--if (common->match_end_ptr != 0)- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);-}--#endif /* SLJIT_CONFIG_S390X */+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \+ || (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64))++typedef enum {+ vector_compare_match1,+ vector_compare_match1i,+ vector_compare_match2,+} vector_compare_type;++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+static SLJIT_INLINE sljit_s32 max_fast_forward_char_pair_offset(void)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+/* The AVX2 code path is currently disabled. */+/* return sljit_has_cpu_feature(SLJIT_HAS_AVX2) ? 31 : 15; */+return 15;+#elif PCRE2_CODE_UNIT_WIDTH == 16+/* The AVX2 code path is currently disabled. */+/* return sljit_has_cpu_feature(SLJIT_HAS_AVX2) ? 15 : 7; */+return 7;+#elif PCRE2_CODE_UNIT_WIDTH == 32+/* The AVX2 code path is currently disabled. */+/* return sljit_has_cpu_feature(SLJIT_HAS_AVX2) ? 7 : 3; */+return 3;+#else+#error "Unsupported unit width"+#endif+}+#else /* !SLJIT_CONFIG_X86 */+static SLJIT_INLINE sljit_s32 max_fast_forward_char_pair_offset(void)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+return 15;+#elif PCRE2_CODE_UNIT_WIDTH == 16+return 7;+#elif PCRE2_CODE_UNIT_WIDTH == 32+return 3;+#else+#error "Unsupported unit width"+#endif+}+#endif /* SLJIT_CONFIG_X86 */++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+static struct sljit_jump *jump_if_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);+return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0x80);+#elif PCRE2_CODE_UNIT_WIDTH == 16+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);+return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00);+#else+#error "Unknown code width"+#endif+}+#endif++#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_S390X */++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)++static sljit_s32 character_to_int32(PCRE2_UCHAR chr)+{+sljit_u32 value = chr;+#if PCRE2_CODE_UNIT_WIDTH == 8+#define SIMD_COMPARE_TYPE_INDEX 0+return (sljit_s32)((value << 24) | (value << 16) | (value << 8) | value);+#elif PCRE2_CODE_UNIT_WIDTH == 16+#define SIMD_COMPARE_TYPE_INDEX 1+return (sljit_s32)((value << 16) | value);+#elif PCRE2_CODE_UNIT_WIDTH == 32+#define SIMD_COMPARE_TYPE_INDEX 2+return (sljit_s32)(value);+#else+#error "Unsupported unit width"+#endif+}++static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, vector_compare_type compare_type,+ sljit_s32 reg_type, int step, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)+{+sljit_u8 instruction[4];++if (reg_type == SLJIT_SIMD_REG_128)+ {+ instruction[0] = 0x66;+ instruction[1] = 0x0f;+ }+else+ {+ /* Two byte VEX prefix. */+ instruction[0] = 0xc5;+ instruction[1] = 0xfd;+ }++SLJIT_ASSERT(step >= 0 && step <= 3);++if (compare_type != vector_compare_match2)+ {+ if (step == 0)+ {+ if (compare_type == vector_compare_match1i)+ {+ /* POR xmm1, xmm2/m128 */+ if (reg_type == SLJIT_SIMD_REG_256)+ instruction[1] ^= (dst_ind << 3);++ /* Prefix is filled. */+ instruction[2] = 0xeb;+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp2_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ }+ return;+ }++ if (step != 2)+ return;++ /* PCMPEQB/W/D xmm1, xmm2/m128 */+ if (reg_type == SLJIT_SIMD_REG_256)+ instruction[1] ^= (dst_ind << 3);++ /* Prefix is filled. */+ instruction[2] = 0x74 + SIMD_COMPARE_TYPE_INDEX;+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;+ }++if (reg_type == SLJIT_SIMD_REG_256)+ {+ if (step == 2)+ return;++ if (step == 0)+ {+ step = 2;+ instruction[1] ^= (dst_ind << 3);+ }+ }++switch (step)+ {+ case 0:+ SLJIT_ASSERT(reg_type == SLJIT_SIMD_REG_128);++ /* MOVDQA xmm1, xmm2/m128 */+ /* Prefix is filled. */+ instruction[2] = 0x6f;+ instruction[3] = 0xc0 | (tmp_ind << 3) | dst_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;++ case 1:+ /* PCMPEQB/W/D xmm1, xmm2/m128 */+ if (reg_type == SLJIT_SIMD_REG_256)+ instruction[1] ^= (dst_ind << 3);++ /* Prefix is filled. */+ instruction[2] = 0x74 + SIMD_COMPARE_TYPE_INDEX;+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;++ case 2:+ /* PCMPEQB/W/D xmm1, xmm2/m128 */+ /* Prefix is filled. */+ instruction[2] = 0x74 + SIMD_COMPARE_TYPE_INDEX;+ instruction[3] = 0xc0 | (tmp_ind << 3) | cmp2_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;++ case 3:+ /* POR xmm1, xmm2/m128 */+ if (reg_type == SLJIT_SIMD_REG_256)+ instruction[1] ^= (dst_ind << 3);++ /* Prefix is filled. */+ instruction[2] = 0xeb;+ instruction[3] = 0xc0 | (dst_ind << 3) | tmp_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;+ }+}++#define JIT_HAS_FAST_FORWARD_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SIMD))++static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)+{+DEFINE_COMPILER;+sljit_u8 instruction[8];+/* The AVX2 code path is currently disabled. */+/* sljit_s32 reg_type = sljit_has_cpu_feature(SLJIT_HAS_AVX2) ? SLJIT_SIMD_REG_256 : SLJIT_SIMD_REG_128; */+sljit_s32 reg_type = SLJIT_SIMD_REG_128;+sljit_s32 value;+struct sljit_label *start;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *restart;+#endif+struct sljit_jump *quit;+struct sljit_jump *partial_quit[2];+vector_compare_type compare_type = vector_compare_match1;+sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);+sljit_s32 data_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0);+sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1);+sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR2);+sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR3);+sljit_u32 bit = 0;+int i;++SLJIT_UNUSED_ARG(offset);++if (char1 != char2)+ {+ bit = char1 ^ char2;+ compare_type = vector_compare_match1i;++ if (!is_powerof2(bit))+ {+ bit = 0;+ compare_type = vector_compare_match2;+ }+ }++partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit[0]);++/* First part (unaligned start) */+value = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_LANE_ZERO;+sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR1, 0, SLJIT_IMM, character_to_int32(char1 | bit));++if (char1 != char2)+ sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));++OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);++sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR1, SLJIT_FR1, 0);++if (char1 != char2)+ sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+restart = LABEL();+#endif++value = (reg_type == SLJIT_SIMD_REG_256) ? 0x1f : 0xf;+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~value);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, value);++value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);++for (i = 0; i < 4; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);++quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* Second part (aligned) */+start = LABEL();++value = (reg_type == SLJIT_SIMD_REG_256) ? 32 : 16;+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value);++partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit[1]);++value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);+for (i = 0; i < 4; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(quit);++SLJIT_ASSERT(tmp1_reg_ind < 8);+/* BSF r32, r/m32 */+instruction[0] = 0x0f;+instruction[1] = 0xbc;+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 3);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);++if (common->mode != PCRE2_JIT_COMPLETE)+ {+ JUMPHERE(partial_quit[0]);+ JUMPHERE(partial_quit[1]);+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);+ SELECT(SLJIT_GREATER, STR_PTR, STR_END, 0, STR_PTR);+ }+else+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && offset > 0)+ {+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));++ quit = jump_if_utf_char_start(compiler, TMP1);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, restart);++ JUMPHERE(quit);+ }+#endif+}++#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SIMD))++static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)+{+DEFINE_COMPILER;+sljit_u8 instruction[8];+/* The AVX2 code path is currently disabled. */+/* sljit_s32 reg_type = sljit_has_cpu_feature(SLJIT_HAS_AVX2) ? SLJIT_SIMD_REG_256 : SLJIT_SIMD_REG_128; */+sljit_s32 reg_type = SLJIT_SIMD_REG_128;+sljit_s32 value;+struct sljit_label *start;+struct sljit_jump *quit;+jump_list *not_found = NULL;+vector_compare_type compare_type = vector_compare_match1;+sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);+sljit_s32 data_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0);+sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1);+sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR2);+sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR3);+sljit_u32 bit = 0;+int i;++if (char1 != char2)+ {+ bit = char1 ^ char2;+ compare_type = vector_compare_match1i;++ if (!is_powerof2(bit))+ {+ bit = 0;+ compare_type = vector_compare_match2;+ }+ }++add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));+OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);+OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);++/* First part (unaligned start) */++value = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_LANE_ZERO;+sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR1, 0, SLJIT_IMM, character_to_int32(char1 | bit));++if (char1 != char2)+ sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));++OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);++sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR1, SLJIT_FR1, 0);++if (char1 != char2)+ sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0);++value = (reg_type == SLJIT_SIMD_REG_256) ? 0x1f : 0xf;+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~value);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, value);++value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);++for (i = 0; i < 4; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);++quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* Second part (aligned) */+start = LABEL();++value = (reg_type == SLJIT_SIMD_REG_256) ? 32 : 16;+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value);++add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);++for (i = 0; i < 4; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(quit);++SLJIT_ASSERT(tmp1_reg_ind < 8);+/* BSF r32, r/m32 */+instruction[0] = 0x0f;+instruction[1] = 0xbc;+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 3);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, STR_PTR, 0);+add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));++OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+return not_found;+}++#ifndef _WIN64++#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SIMD))++static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)+{+DEFINE_COMPILER;+sljit_u8 instruction[8];+/* The AVX2 code path is currently disabled. */+/* sljit_s32 reg_type = sljit_has_cpu_feature(SLJIT_HAS_AVX2) ? SLJIT_SIMD_REG_256 : SLJIT_SIMD_REG_128; */+sljit_s32 reg_type = SLJIT_SIMD_REG_128;+sljit_s32 value;+vector_compare_type compare1_type = vector_compare_match1;+vector_compare_type compare2_type = vector_compare_match1;+sljit_u32 bit1 = 0;+sljit_u32 bit2 = 0;+sljit_u32 diff = IN_UCHARS(offs1 - offs2);+sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);+sljit_s32 data1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0);+sljit_s32 data2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1);+sljit_s32 cmp1a_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR2);+sljit_s32 cmp2a_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR3);+sljit_s32 cmp1b_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR4);+sljit_s32 cmp2b_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR5);+sljit_s32 tmp1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR6);+sljit_s32 tmp2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_TMP_FR0);+struct sljit_label *start;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *restart;+#endif+struct sljit_jump *jump[2];+int i;++SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2 && offs2 >= 0);+SLJIT_ASSERT(diff <= (unsigned)IN_UCHARS(max_fast_forward_char_pair_offset()));++/* Initialize. */+if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));++ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, STR_END, 0);+ SELECT(SLJIT_LESS, STR_END, TMP1, 0, STR_END);+ }++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++if (char1a == char1b)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));+else+ {+ bit1 = char1a ^ char1b;+ if (is_powerof2(bit1))+ {+ compare1_type = vector_compare_match1i;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a | bit1));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit1));+ }+ else+ {+ compare1_type = vector_compare_match2;+ bit1 = 0;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char1b));+ }+ }++value = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_LANE_ZERO;+sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR2, 0, TMP1, 0);++if (char1a != char1b)+ sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR4, 0, TMP2, 0);++if (char2a == char2b)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));+else+ {+ bit2 = char2a ^ char2b;+ if (is_powerof2(bit2))+ {+ compare2_type = vector_compare_match1i;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a | bit2));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit2));+ }+ else+ {+ compare2_type = vector_compare_match2;+ bit2 = 0;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char2b));+ }+ }++sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR3, 0, TMP1, 0);++if (char2a != char2b)+ sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR5, 0, TMP2, 0);++sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0);+if (char1a != char1b)+ sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR4, SLJIT_FR4, 0);++sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR3, SLJIT_FR3, 0);+if (char2a != char2b)+ sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR5, SLJIT_FR5, 0);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+restart = LABEL();+#endif++OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, diff);+OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);+value = (reg_type == SLJIT_SIMD_REG_256) ? ~0x1f : ~0xf;+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value);++value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);++jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0);++sljit_emit_simd_mov(compiler, reg_type, SLJIT_FR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);+jump[1] = JUMP(SLJIT_JUMP);++JUMPHERE(jump[0]);++if (reg_type == SLJIT_SIMD_REG_256)+ {+ if (diff != 16)+ {+ /* PSLLDQ ymm1, ymm2, imm8 */+ instruction[0] = 0xc5;+ instruction[1] = (sljit_u8)(0xf9 ^ (data2_ind << 3));+ instruction[2] = 0x73;+ instruction[3] = 0xc0 | (7 << 3) | data1_ind;+ instruction[4] = diff & 0xf;+ sljit_emit_op_custom(compiler, instruction, 5);+ }++ instruction[0] = 0xc4;+ instruction[1] = 0xe3;+ if (diff < 16)+ {+ /* VINSERTI128 xmm1, xmm2, xmm3/m128 */+ /* instruction[0] = 0xc4; */+ /* instruction[1] = 0xe3; */+ instruction[2] = (sljit_u8)(0x7d ^ (data2_ind << 3));+ instruction[3] = 0x38;+ SLJIT_ASSERT(sljit_get_register_index(SLJIT_GP_REGISTER, STR_PTR) <= 7);+ instruction[4] = 0x40 | (data2_ind << 3) | sljit_get_register_index(SLJIT_GP_REGISTER, STR_PTR);+ instruction[5] = (sljit_u8)(16 - diff);+ instruction[6] = 1;+ sljit_emit_op_custom(compiler, instruction, 7);+ }+ else+ {+ /* VPERM2I128 xmm1, xmm2, xmm3/m128 */+ /* instruction[0] = 0xc4; */+ /* instruction[1] = 0xe3; */+ value = (diff == 16) ? data1_ind : data2_ind;+ instruction[2] = (sljit_u8)(0x7d ^ (value << 3));+ instruction[3] = 0x46;+ instruction[4] = 0xc0 | (data2_ind << 3) | value;+ instruction[5] = 0x08;+ sljit_emit_op_custom(compiler, instruction, 6);+ }+ }+else+ {+ /* MOVDQA xmm1, xmm2/m128 */+ instruction[0] = 0x66;+ instruction[1] = 0x0f;+ instruction[2] = 0x6f;+ instruction[3] = 0xc0 | (data2_ind << 3) | data1_ind;+ sljit_emit_op_custom(compiler, instruction, 4);++ /* PSLLDQ xmm1, imm8 */+ /* instruction[0] = 0x66; */+ /* instruction[1] = 0x0f; */+ instruction[2] = 0x73;+ instruction[3] = 0xc0 | (7 << 3) | data2_ind;+ instruction[4] = diff;+ sljit_emit_op_custom(compiler, instruction, 5);+ }++JUMPHERE(jump[1]);++value = (reg_type == SLJIT_SIMD_REG_256) ? 0x1f : 0xf;+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, value);++for (i = 0; i < 4; i++)+ {+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, reg_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, reg_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);+ }++sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_FR0, SLJIT_FR0, SLJIT_FR1);+sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);++/* Ignore matches before the first STR_PTR. */+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);++jump[0] = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* Main loop. */+start = LABEL();++value = (reg_type == SLJIT_SIMD_REG_256) ? 32 : 16;+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value);+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);+sljit_emit_simd_mov(compiler, reg_type, SLJIT_FR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);++for (i = 0; i < 4; i++)+ {+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, reg_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp2_ind);+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, reg_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp1_ind);+ }++sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_FR0, SLJIT_FR0, SLJIT_FR1);+sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);++CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(jump[0]);++SLJIT_ASSERT(tmp1_reg_ind < 8);+/* BSF r32, r/m32 */+instruction[0] = 0x0f;+instruction[1] = 0xbc;+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 3);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);++add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));++ jump[0] = jump_if_utf_char_start(compiler, TMP1);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart);++ add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP));++ JUMPHERE(jump[0]);+ }+#endif++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+}++#endif /* !_WIN64 */++#undef SIMD_COMPARE_TYPE_INDEX++#endif /* SLJIT_CONFIG_X86 */++#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 && (defined __ARM_NEON || defined __ARM_NEON__))++#include <arm_neon.h>++typedef union {+ unsigned int x;+ struct { unsigned char c1, c2, c3, c4; } c;+} int_char;++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+static SLJIT_INLINE int utf_continue(PCRE2_SPTR s)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+return (*s & 0xc0) == 0x80;+#elif PCRE2_CODE_UNIT_WIDTH == 16+return (*s & 0xfc00) == 0xdc00;+#else+#error "Unknown code width"+#endif+}+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */++#if PCRE2_CODE_UNIT_WIDTH == 8+# define VECTOR_FACTOR 16+# define vect_t uint8x16_t+# define VLD1Q(X) vld1q_u8((sljit_u8 *)(X))+# define VCEQQ vceqq_u8+# define VORRQ vorrq_u8+# define VST1Q vst1q_u8+# define VDUPQ vdupq_n_u8+# define VEXTQ vextq_u8+# define VANDQ vandq_u8+typedef union {+ uint8_t mem[16];+ uint64_t dw[2];+} quad_word;+#elif PCRE2_CODE_UNIT_WIDTH == 16+# define VECTOR_FACTOR 8+# define vect_t uint16x8_t+# define VLD1Q(X) vld1q_u16((sljit_u16 *)(X))+# define VCEQQ vceqq_u16+# define VORRQ vorrq_u16+# define VST1Q vst1q_u16+# define VDUPQ vdupq_n_u16+# define VEXTQ vextq_u16+# define VANDQ vandq_u16+typedef union {+ uint16_t mem[8];+ uint64_t dw[2];+} quad_word;+#else+# define VECTOR_FACTOR 4+# define vect_t uint32x4_t+# define VLD1Q(X) vld1q_u32((sljit_u32 *)(X))+# define VCEQQ vceqq_u32+# define VORRQ vorrq_u32+# define VST1Q vst1q_u32+# define VDUPQ vdupq_n_u32+# define VEXTQ vextq_u32+# define VANDQ vandq_u32+typedef union {+ uint32_t mem[4];+ uint64_t dw[2];+} quad_word;+#endif++#define FFCS+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCS++#define FFCS_2+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCS_2++#define FFCS_MASK+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCS_MASK++#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1++static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)+{+DEFINE_COMPILER;+int_char ic;+struct sljit_jump *partial_quit, *quit;+/* Save temporary registers. */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP3, 0);++/* Prepare function arguments */+OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);+GET_LOCAL_BASE(SLJIT_R1, 0, LOCALS0);+OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, offset);++if (char1 == char2)+ {+ ic.c.c1 = char1;+ ic.c.c2 = char2;+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf && offset > 0)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_utf));+ else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs));+#else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs));+#endif+ }+else+ {+ PCRE2_UCHAR mask = char1 ^ char2;+ if (is_powerof2(mask))+ {+ ic.c.c1 = char1 | mask;+ ic.c.c2 = mask;+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf && offset > 0)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask_utf));+ else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask));+#else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask));+#endif+ }+ else+ {+ ic.c.c1 = char1;+ ic.c.c2 = char2;+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf && offset > 0)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2_utf));+ else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2));+#else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2));+#endif+ }+ }+/* Restore registers. */+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);++/* Check return value. */+partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit);++/* Fast forward STR_PTR to the result of memchr. */+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);+if (common->mode != PCRE2_JIT_COMPLETE)+ {+ quit = CMP(SLJIT_NOT_ZERO, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+ JUMPHERE(partial_quit);+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);+ SELECT(SLJIT_GREATER, STR_PTR, STR_END, 0, STR_PTR);+ JUMPHERE(quit);+ }+}++typedef enum {+ compare_match1,+ compare_match1i,+ compare_match2,+} compare_type;++static inline vect_t fast_forward_char_pair_compare(compare_type ctype, vect_t dst, vect_t cmp1, vect_t cmp2)+{+if (ctype == compare_match2)+ {+ vect_t tmp = dst;+ dst = VCEQQ(dst, cmp1);+ tmp = VCEQQ(tmp, cmp2);+ dst = VORRQ(dst, tmp);+ return dst;+ }++if (ctype == compare_match1i)+ dst = VORRQ(dst, cmp2);+dst = VCEQQ(dst, cmp1);+return dst;+}++static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+return 15;+#elif PCRE2_CODE_UNIT_WIDTH == 16+return 7;+#elif PCRE2_CODE_UNIT_WIDTH == 32+return 3;+#else+#error "Unsupported unit width"+#endif+}++/* ARM doesn't have a shift left across lanes. */+static SLJIT_INLINE vect_t shift_left_n_lanes(vect_t a, sljit_u8 n)+{+vect_t zero = VDUPQ(0);+SLJIT_ASSERT(0 < n && n < VECTOR_FACTOR);+/* VEXTQ takes an immediate as last argument. */+#define C(X) case X: return VEXTQ(zero, a, VECTOR_FACTOR - X);+switch (n)+ {+ C(1); C(2); C(3);+#if PCRE2_CODE_UNIT_WIDTH != 32+ C(4); C(5); C(6); C(7);+# if PCRE2_CODE_UNIT_WIDTH != 16+ C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15);+# endif+#endif+ default:+ /* Based on the ASSERT(0 < n && n < VECTOR_FACTOR) above, this won't+ happen. The return is still here for compilers to not warn. */+ return a;+ }+}++#define FFCPS+#define FFCPS_DIFF1+#define FFCPS_CHAR1A2A++#define FFCPS_0+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCPS_0++#undef FFCPS_CHAR1A2A++#define FFCPS_1+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCPS_1++#undef FFCPS_DIFF1++#define FFCPS_DEFAULT+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCPS++#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1++static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)+{+DEFINE_COMPILER;+sljit_u32 diff = IN_UCHARS(offs1 - offs2);+struct sljit_jump *partial_quit;+int_char ic;+SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);+SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));+SLJIT_ASSERT(compiler->scratches == 5);++/* Save temporary register STR_PTR. */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);++/* Prepare arguments for the function call. */+if (common->match_end_ptr == 0)+ OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);+else+ {+ OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP2(SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));++ OP2U(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, SLJIT_R0, 0);+ SELECT(SLJIT_LESS, SLJIT_R0, STR_END, 0, SLJIT_R0);+ }++GET_LOCAL_BASE(SLJIT_R1, 0, LOCALS0);+OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_IMM, offs1);+OP1(SLJIT_MOV_S32, SLJIT_R3, 0, SLJIT_IMM, offs2);+ic.c.c1 = char1a;+ic.c.c2 = char1b;+ic.c.c3 = char2a;+ic.c.c4 = char2b;+OP1(SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_IMM, ic.x);++if (diff == 1) {+ if (char1a == char1b && char2a == char2b) {+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_0_utf));+ else+#endif+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_0));+ } else {+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_1_utf));+ else+#endif+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_1));+ }+} else {+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_default_utf));+ else+#endif+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_default));+}++/* Restore STR_PTR register. */+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);++/* Check return value. */+partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+add_jump(compiler, &common->failed_match, partial_quit);++/* Fast forward STR_PTR to the result of memchr. */+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);++JUMPHERE(partial_quit);+}++#endif /* SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 */++#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)++#if PCRE2_CODE_UNIT_WIDTH == 8+#define VECTOR_ELEMENT_SIZE 0+#elif PCRE2_CODE_UNIT_WIDTH == 16+#define VECTOR_ELEMENT_SIZE 1+#elif PCRE2_CODE_UNIT_WIDTH == 32+#define VECTOR_ELEMENT_SIZE 2+#else+#error "Unsupported unit width"+#endif++static void load_from_mem_vector(struct sljit_compiler *compiler, BOOL vlbb, sljit_s32 dst_vreg,+ sljit_s32 base_reg, sljit_s32 index_reg)+{+sljit_u16 instruction[3];++instruction[0] = (sljit_u16)(0xe700 | (dst_vreg << 4) | index_reg);+instruction[1] = (sljit_u16)(base_reg << 12);+instruction[2] = (sljit_u16)((0x8 << 8) | (vlbb ? 0x07 : 0x06));++sljit_emit_op_custom(compiler, instruction, 6);+}++#if PCRE2_CODE_UNIT_WIDTH == 32++static void replicate_imm_vector(struct sljit_compiler *compiler, int step, sljit_s32 dst_vreg,+ PCRE2_UCHAR chr, sljit_s32 tmp_general_reg)+{+sljit_u16 instruction[3];++SLJIT_ASSERT(step >= 0 && step <= 1);++if (chr < 0x7fff)+ {+ if (step == 1)+ return;++ /* VREPI */+ instruction[0] = (sljit_u16)(0xe700 | (dst_vreg << 4));+ instruction[1] = (sljit_u16)chr;+ instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45);+ sljit_emit_op_custom(compiler, instruction, 6);+ return;+ }++if (step == 0)+ {+ OP1(SLJIT_MOV, tmp_general_reg, 0, SLJIT_IMM, chr);++ /* VLVG */+ instruction[0] = (sljit_u16)(0xe700 | (dst_vreg << 4) | sljit_get_register_index(SLJIT_GP_REGISTER, tmp_general_reg));+ instruction[1] = 0;+ instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x22);+ sljit_emit_op_custom(compiler, instruction, 6);+ return;+ }++/* VREP */+instruction[0] = (sljit_u16)(0xe700 | (dst_vreg << 4) | dst_vreg);+instruction[1] = 0;+instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xc << 8) | 0x4d);+sljit_emit_op_custom(compiler, instruction, 6);+}++#endif++static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, vector_compare_type compare_type,+ int step, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)+{+sljit_u16 instruction[3];++SLJIT_ASSERT(step >= 0 && step <= 2);++if (step == 1)+ {+ /* VCEQ */+ instruction[0] = (sljit_u16)(0xe700 | (dst_ind << 4) | dst_ind);+ instruction[1] = (sljit_u16)(cmp1_ind << 12);+ instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0xf8);+ sljit_emit_op_custom(compiler, instruction, 6);+ return;+ }++if (compare_type != vector_compare_match2)+ {+ if (step == 0 && compare_type == vector_compare_match1i)+ {+ /* VO */+ instruction[0] = (sljit_u16)(0xe700 | (dst_ind << 4) | dst_ind);+ instruction[1] = (sljit_u16)(cmp2_ind << 12);+ instruction[2] = (sljit_u16)((0xe << 8) | 0x6a);+ sljit_emit_op_custom(compiler, instruction, 6);+ }+ return;+ }++switch (step)+ {+ case 0:+ /* VCEQ */+ instruction[0] = (sljit_u16)(0xe700 | (tmp_ind << 4) | dst_ind);+ instruction[1] = (sljit_u16)(cmp2_ind << 12);+ instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0xf8);+ sljit_emit_op_custom(compiler, instruction, 6);+ return;++ case 2:+ /* VO */+ instruction[0] = (sljit_u16)(0xe700 | (dst_ind << 4) | dst_ind);+ instruction[1] = (sljit_u16)(tmp_ind << 12);+ instruction[2] = (sljit_u16)((0xe << 8) | 0x6a);+ sljit_emit_op_custom(compiler, instruction, 6);+ return;+ }+}++#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1++static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)+{+DEFINE_COMPILER;+sljit_u16 instruction[3];+struct sljit_label *start;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *restart;+#endif+struct sljit_jump *quit;+struct sljit_jump *partial_quit[2];+vector_compare_type compare_type = vector_compare_match1;+sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, STR_PTR);+sljit_s32 data_ind = 0;+sljit_s32 tmp_ind = 1;+sljit_s32 cmp1_ind = 2;+sljit_s32 cmp2_ind = 3;+sljit_s32 zero_ind = 4;+sljit_u32 bit = 0;+int i;++SLJIT_UNUSED_ARG(offset);++if (char1 != char2)+ {+ bit = char1 ^ char2;+ compare_type = vector_compare_match1i;++ if (!is_powerof2(bit))+ {+ bit = 0;+ compare_type = vector_compare_match2;+ }+ }++partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit[0]);++/* First part (unaligned start) */++OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 16);++#if PCRE2_CODE_UNIT_WIDTH != 32++/* VREPI */+instruction[0] = (sljit_u16)(0xe700 | (cmp1_ind << 4));+instruction[1] = (sljit_u16)(char1 | bit);+instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45);+sljit_emit_op_custom(compiler, instruction, 6);++if (char1 != char2)+ {+ /* VREPI */+ instruction[0] = (sljit_u16)(0xe700 | (cmp2_ind << 4));+ instruction[1] = (sljit_u16)(bit != 0 ? bit : char2);+ /* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */+ sljit_emit_op_custom(compiler, instruction, 6);+ }++#else /* PCRE2_CODE_UNIT_WIDTH == 32 */++for (int i = 0; i < 2; i++)+ {+ replicate_imm_vector(compiler, i, cmp1_ind, char1 | bit, TMP1);++ if (char1 != char2)+ replicate_imm_vector(compiler, i, cmp2_ind, bit != 0 ? bit : char2, TMP1);+ }++#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */++if (compare_type == vector_compare_match2)+ {+ /* VREPI */+ instruction[0] = (sljit_u16)(0xe700 | (zero_ind << 4));+ instruction[1] = 0;+ instruction[2] = (sljit_u16)((0x8 << 8) | 0x45);+ sljit_emit_op_custom(compiler, instruction, 6);+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+restart = LABEL();+#endif++load_from_mem_vector(compiler, TRUE, data_ind, str_ptr_reg_ind, 0);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, ~15);++if (compare_type != vector_compare_match2)+ {+ if (compare_type == vector_compare_match1i)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, 0, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++ /* VFEE */+ instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);+ instruction[1] = (sljit_u16)((cmp1_ind << 12) | (1 << 4));+ instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0x80);+ sljit_emit_op_custom(compiler, instruction, 6);+ }+else+ {+ for (i = 0; i < 3; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++ /* VFENE */+ instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);+ instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));+ instruction[2] = (sljit_u16)((0xe << 8) | 0x81);+ sljit_emit_op_custom(compiler, instruction, 6);+ }++/* VLGVB */+instruction[0] = (sljit_u16)(0xe700 | (tmp1_reg_ind << 4) | data_ind);+instruction[1] = 7;+instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);+sljit_emit_op_custom(compiler, instruction, 6);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+quit = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);++OP2(SLJIT_SUB, STR_PTR, 0, TMP2, 0, SLJIT_IMM, 16);++/* Second part (aligned) */+start = LABEL();++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);++partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit[1]);++load_from_mem_vector(compiler, TRUE, data_ind, str_ptr_reg_ind, 0);++if (compare_type != vector_compare_match2)+ {+ if (compare_type == vector_compare_match1i)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, 0, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++ /* VFEE */+ instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);+ instruction[1] = (sljit_u16)((cmp1_ind << 12) | (1 << 4));+ instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0x80);+ sljit_emit_op_custom(compiler, instruction, 6);+ }+else+ {+ for (i = 0; i < 3; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++ /* VFENE */+ instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);+ instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));+ instruction[2] = (sljit_u16)((0xe << 8) | 0x81);+ sljit_emit_op_custom(compiler, instruction, 6);+ }++sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);+JUMPTO(SLJIT_OVERFLOW, start);++/* VLGVB */+instruction[0] = (sljit_u16)(0xe700 | (tmp1_reg_ind << 4) | data_ind);+instruction[1] = 7;+instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);+sljit_emit_op_custom(compiler, instruction, 6);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);++JUMPHERE(quit);++if (common->mode != PCRE2_JIT_COMPLETE)+ {+ JUMPHERE(partial_quit[0]);+ JUMPHERE(partial_quit[1]);+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);+ SELECT(SLJIT_GREATER, STR_PTR, STR_END, 0, STR_PTR);+ }+else+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && offset > 0)+ {+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));++ quit = jump_if_utf_char_start(compiler, TMP1);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 16);+ JUMPTO(SLJIT_JUMP, restart);++ JUMPHERE(quit);+ }+#endif+}++#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD 1++static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)+{+DEFINE_COMPILER;+sljit_u16 instruction[3];+struct sljit_label *start;+struct sljit_jump *quit;+jump_list *not_found = NULL;+vector_compare_type compare_type = vector_compare_match1;+sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);+sljit_s32 tmp3_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP3);+sljit_s32 data_ind = 0;+sljit_s32 tmp_ind = 1;+sljit_s32 cmp1_ind = 2;+sljit_s32 cmp2_ind = 3;+sljit_s32 zero_ind = 4;+sljit_u32 bit = 0;+int i;++if (char1 != char2)+ {+ bit = char1 ^ char2;+ compare_type = vector_compare_match1i;++ if (!is_powerof2(bit))+ {+ bit = 0;+ compare_type = vector_compare_match2;+ }+ }++add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));++/* First part (unaligned start) */++OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, 16);++#if PCRE2_CODE_UNIT_WIDTH != 32++/* VREPI */+instruction[0] = (sljit_u16)(0xe700 | (cmp1_ind << 4));+instruction[1] = (sljit_u16)(char1 | bit);+instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45);+sljit_emit_op_custom(compiler, instruction, 6);++if (char1 != char2)+ {+ /* VREPI */+ instruction[0] = (sljit_u16)(0xe700 | (cmp2_ind << 4));+ instruction[1] = (sljit_u16)(bit != 0 ? bit : char2);+ /* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */+ sljit_emit_op_custom(compiler, instruction, 6);+ }++#else /* PCRE2_CODE_UNIT_WIDTH == 32 */++for (int i = 0; i < 2; i++)+ {+ replicate_imm_vector(compiler, i, cmp1_ind, char1 | bit, TMP3);++ if (char1 != char2)+ replicate_imm_vector(compiler, i, cmp2_ind, bit != 0 ? bit : char2, TMP3);+ }++#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */++if (compare_type == vector_compare_match2)+ {+ /* VREPI */+ instruction[0] = (sljit_u16)(0xe700 | (zero_ind << 4));+ instruction[1] = 0;+ instruction[2] = (sljit_u16)((0x8 << 8) | 0x45);+ sljit_emit_op_custom(compiler, instruction, 6);+ }++load_from_mem_vector(compiler, TRUE, data_ind, tmp1_reg_ind, 0);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, ~15);++if (compare_type != vector_compare_match2)+ {+ if (compare_type == vector_compare_match1i)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, 0, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++ /* VFEE */+ instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);+ instruction[1] = (sljit_u16)((cmp1_ind << 12) | (1 << 4));+ instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0x80);+ sljit_emit_op_custom(compiler, instruction, 6);+ }+else+ {+ for (i = 0; i < 3; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++ /* VFENE */+ instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);+ instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));+ instruction[2] = (sljit_u16)((0xe << 8) | 0x81);+ sljit_emit_op_custom(compiler, instruction, 6);+ }++/* VLGVB */+instruction[0] = (sljit_u16)(0xe700 | (tmp3_reg_ind << 4) | data_ind);+instruction[1] = 7;+instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);+sljit_emit_op_custom(compiler, instruction, 6);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);+quit = CMP(SLJIT_LESS, TMP1, 0, TMP2, 0);++OP2(SLJIT_SUB, TMP1, 0, TMP2, 0, SLJIT_IMM, 16);++/* Second part (aligned) */+start = LABEL();++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 16);++add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));++load_from_mem_vector(compiler, TRUE, data_ind, tmp1_reg_ind, 0);++if (compare_type != vector_compare_match2)+ {+ if (compare_type == vector_compare_match1i)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, 0, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++ /* VFEE */+ instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);+ instruction[1] = (sljit_u16)((cmp1_ind << 12) | (1 << 4));+ instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0xe << 8) | 0x80);+ sljit_emit_op_custom(compiler, instruction, 6);+ }+else+ {+ for (i = 0; i < 3; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++ /* VFENE */+ instruction[0] = (sljit_u16)(0xe700 | (data_ind << 4) | data_ind);+ instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));+ instruction[2] = (sljit_u16)((0xe << 8) | 0x81);+ sljit_emit_op_custom(compiler, instruction, 6);+ }++sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);+JUMPTO(SLJIT_OVERFLOW, start);++/* VLGVB */+instruction[0] = (sljit_u16)(0xe700 | (tmp3_reg_ind << 4) | data_ind);+instruction[1] = 7;+instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);+sljit_emit_op_custom(compiler, instruction, 6);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);++JUMPHERE(quit);+add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));++return not_found;+}++#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1++static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)+{+DEFINE_COMPILER;+sljit_u16 instruction[3];+struct sljit_label *start;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *restart;+#endif+struct sljit_jump *quit;+struct sljit_jump *jump[2];+vector_compare_type compare1_type = vector_compare_match1;+vector_compare_type compare2_type = vector_compare_match1;+sljit_u32 bit1 = 0;+sljit_u32 bit2 = 0;+sljit_s32 diff = IN_UCHARS(offs2 - offs1);+sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);+sljit_s32 tmp2_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP2);+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, STR_PTR);+sljit_s32 data1_ind = 0;+sljit_s32 data2_ind = 1;+sljit_s32 tmp1_ind = 2;+sljit_s32 tmp2_ind = 3;+sljit_s32 cmp1a_ind = 4;+sljit_s32 cmp1b_ind = 5;+sljit_s32 cmp2a_ind = 6;+sljit_s32 cmp2b_ind = 7;+sljit_s32 zero_ind = 8;+int i;++SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);+SLJIT_ASSERT(-diff <= (sljit_s32)IN_UCHARS(max_fast_forward_char_pair_offset()));+SLJIT_ASSERT(tmp1_reg_ind != 0 && tmp2_reg_ind != 0);++if (char1a != char1b)+ {+ bit1 = char1a ^ char1b;+ compare1_type = vector_compare_match1i;++ if (!is_powerof2(bit1))+ {+ bit1 = 0;+ compare1_type = vector_compare_match2;+ }+ }++if (char2a != char2b)+ {+ bit2 = char2a ^ char2b;+ compare2_type = vector_compare_match1i;++ if (!is_powerof2(bit2))+ {+ bit2 = 0;+ compare2_type = vector_compare_match2;+ }+ }++/* Initialize. */+if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));++ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, STR_END, 0);+ SELECT(SLJIT_LESS, STR_END, TMP1, 0, STR_END);+ }++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, ~15);++#if PCRE2_CODE_UNIT_WIDTH != 32++OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, -diff);++/* VREPI */+instruction[0] = (sljit_u16)(0xe700 | (cmp1a_ind << 4));+instruction[1] = (sljit_u16)(char1a | bit1);+instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45);+sljit_emit_op_custom(compiler, instruction, 6);++if (char1a != char1b)+ {+ /* VREPI */+ instruction[0] = (sljit_u16)(0xe700 | (cmp1b_ind << 4));+ instruction[1] = (sljit_u16)(bit1 != 0 ? bit1 : char1b);+ /* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */+ sljit_emit_op_custom(compiler, instruction, 6);+ }++/* VREPI */+instruction[0] = (sljit_u16)(0xe700 | (cmp2a_ind << 4));+instruction[1] = (sljit_u16)(char2a | bit2);+/* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */+sljit_emit_op_custom(compiler, instruction, 6);++if (char2a != char2b)+ {+ /* VREPI */+ instruction[0] = (sljit_u16)(0xe700 | (cmp2b_ind << 4));+ instruction[1] = (sljit_u16)(bit2 != 0 ? bit2 : char2b);+ /* instruction[2] = (sljit_u16)((VECTOR_ELEMENT_SIZE << 12) | (0x8 << 8) | 0x45); */+ sljit_emit_op_custom(compiler, instruction, 6);+ }++#else /* PCRE2_CODE_UNIT_WIDTH == 32 */++for (int i = 0; i < 2; i++)+ {+ replicate_imm_vector(compiler, i, cmp1a_ind, char1a | bit1, TMP1);++ if (char1a != char1b)+ replicate_imm_vector(compiler, i, cmp1b_ind, bit1 != 0 ? bit1 : char1b, TMP1);++ replicate_imm_vector(compiler, i, cmp2a_ind, char2a | bit2, TMP1);++ if (char2a != char2b)+ replicate_imm_vector(compiler, i, cmp2b_ind, bit2 != 0 ? bit2 : char2b, TMP1);+ }++OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, -diff);++#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */++/* VREPI */+instruction[0] = (sljit_u16)(0xe700 | (zero_ind << 4));+instruction[1] = 0;+instruction[2] = (sljit_u16)((0x8 << 8) | 0x45);+sljit_emit_op_custom(compiler, instruction, 6);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+restart = LABEL();+#endif++jump[0] = CMP(SLJIT_LESS, TMP1, 0, TMP2, 0);+load_from_mem_vector(compiler, TRUE, data2_ind, tmp1_reg_ind, 0);+jump[1] = JUMP(SLJIT_JUMP);+JUMPHERE(jump[0]);+load_from_mem_vector(compiler, FALSE, data2_ind, tmp1_reg_ind, 0);+JUMPHERE(jump[1]);++load_from_mem_vector(compiler, TRUE, data1_ind, str_ptr_reg_ind, 0);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 16);++for (i = 0; i < 3; i++)+ {+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);+ }++/* VN */+instruction[0] = (sljit_u16)(0xe700 | (data1_ind << 4) | data1_ind);+instruction[1] = (sljit_u16)(data2_ind << 12);+instruction[2] = (sljit_u16)((0xe << 8) | 0x68);+sljit_emit_op_custom(compiler, instruction, 6);++/* VFENE */+instruction[0] = (sljit_u16)(0xe700 | (data1_ind << 4) | data1_ind);+instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));+instruction[2] = (sljit_u16)((0xe << 8) | 0x81);+sljit_emit_op_custom(compiler, instruction, 6);++/* VLGVB */+instruction[0] = (sljit_u16)(0xe700 | (tmp1_reg_ind << 4) | data1_ind);+instruction[1] = 7;+instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);+sljit_emit_op_custom(compiler, instruction, 6);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+quit = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);++OP2(SLJIT_SUB, STR_PTR, 0, TMP2, 0, SLJIT_IMM, 16);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, diff);++/* Main loop. */+start = LABEL();++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++load_from_mem_vector(compiler, FALSE, data1_ind, str_ptr_reg_ind, 0);+load_from_mem_vector(compiler, FALSE, data2_ind, str_ptr_reg_ind, tmp1_reg_ind);++for (i = 0; i < 3; i++)+ {+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);+ }++/* VN */+instruction[0] = (sljit_u16)(0xe700 | (data1_ind << 4) | data1_ind);+instruction[1] = (sljit_u16)(data2_ind << 12);+instruction[2] = (sljit_u16)((0xe << 8) | 0x68);+sljit_emit_op_custom(compiler, instruction, 6);++/* VFENE */+instruction[0] = (sljit_u16)(0xe700 | (data1_ind << 4) | data1_ind);+instruction[1] = (sljit_u16)((zero_ind << 12) | (1 << 4));+instruction[2] = (sljit_u16)((0xe << 8) | 0x81);+sljit_emit_op_custom(compiler, instruction, 6);++sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);+JUMPTO(SLJIT_OVERFLOW, start);++/* VLGVB */+instruction[0] = (sljit_u16)(0xe700 | (tmp2_reg_ind << 4) | data1_ind);+instruction[1] = 7;+instruction[2] = (sljit_u16)((0x4 << 8) | 0x21);+sljit_emit_op_custom(compiler, instruction, 6);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++JUMPHERE(quit);++add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf)+ {+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));++ quit = jump_if_utf_char_start(compiler, TMP1);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++ /* TMP1 contains diff. */+ OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, ~15);+ OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, -diff);+ JUMPTO(SLJIT_JUMP, restart);++ JUMPHERE(quit);+ }+#endif++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+}++#endif /* SLJIT_CONFIG_S390X */++#if (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64)++#ifdef __linux__+/* Using getauxval(AT_HWCAP) under Linux for detecting whether LSX is available */+#include <sys/auxv.h>+#define LOONGARCH_HWCAP_LSX (1 << 4)+#define HAS_LSX_SUPPORT ((getauxval(AT_HWCAP) & LOONGARCH_HWCAP_LSX) != 0)+#else+#define HAS_LSX_SUPPORT 0+#endif++typedef sljit_ins sljit_u32;++#define SI12_IMM_MASK 0x003ffc00+#define UI5_IMM_MASK 0x00007c00+#define UI2_IMM_MASK 0x00000c00++#define VD(vd) ((sljit_ins)vd << 0)+#define VJ(vj) ((sljit_ins)vj << 5)+#define VK(vk) ((sljit_ins)vk << 10)+#define RD_V(rd) ((sljit_ins)rd << 0)+#define RJ_V(rj) ((sljit_ins)rj << 5)++#define IMM_SI12(imm) (((sljit_ins)(imm) << 10) & SI12_IMM_MASK)+#define IMM_UI5(imm) (((sljit_ins)(imm) << 10) & UI5_IMM_MASK)+#define IMM_UI2(imm) (((sljit_ins)(imm) << 10) & UI2_IMM_MASK)++// LSX OPCODES:+#define VLD 0x2c000000+#define VOR_V 0x71268000+#define VAND_V 0x71260000+#define VBSLL_V 0x728e0000+#define VMSKLTZ_B 0x729c4000+#define VPICKVE2GR_WU 0x72f3e000++#if PCRE2_CODE_UNIT_WIDTH == 8+#define VREPLGR2VR 0x729f0000+#define VSEQ 0x70000000+#elif PCRE2_CODE_UNIT_WIDTH == 16+#define VREPLGR2VR 0x729f0400+#define VSEQ 0x70008000+#else+#define VREPLGR2VR 0x729f0800+#define VSEQ 0x70010000+#endif++static void fast_forward_char_pair_lsx_compare(struct sljit_compiler *compiler, vector_compare_type compare_type,+ sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)+{+if (compare_type != vector_compare_match2)+ {+ if (compare_type == vector_compare_match1i)+ {+ /* VOR.V vd, vj, vk */+ push_inst(compiler, VOR_V | VD(dst_ind) | VJ(cmp2_ind) | VK(dst_ind));+ }++ /* VSEQ.B/H/W vd, vj, vk */+ push_inst(compiler, VSEQ | VD(dst_ind) | VJ(dst_ind) | VK(cmp1_ind));+ return;+ }++/* VBSLL.V vd, vj, ui5 */+push_inst(compiler, VBSLL_V | VD(tmp_ind) | VJ(dst_ind) | IMM_UI5(0));++/* VSEQ.B/H/W vd, vj, vk */+push_inst(compiler, VSEQ | VD(dst_ind) | VJ(dst_ind) | VK(cmp1_ind));++/* VSEQ.B/H/W vd, vj, vk */+push_inst(compiler, VSEQ | VD(tmp_ind) | VJ(tmp_ind) | VK(cmp2_ind));++/* VOR vd, vj, vk */+push_inst(compiler, VOR_V | VD(dst_ind) | VJ(tmp_ind) | VK(dst_ind));+return;+}++#define JIT_HAS_FAST_FORWARD_CHAR_SIMD HAS_LSX_SUPPORT++static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)+{+DEFINE_COMPILER;+struct sljit_label *start;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *restart;+#endif+struct sljit_jump *quit;+struct sljit_jump *partial_quit[2];+vector_compare_type compare_type = vector_compare_match1;+sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, STR_PTR);+sljit_s32 data_ind = 0;+sljit_s32 tmp_ind = 1;+sljit_s32 cmp1_ind = 2;+sljit_s32 cmp2_ind = 3;+sljit_u32 bit = 0;++SLJIT_UNUSED_ARG(offset);++if (char1 != char2)+ {+ bit = char1 ^ char2;+ compare_type = vector_compare_match1i;++ if (!is_powerof2(bit))+ {+ bit = 0;+ compare_type = vector_compare_match2;+ }+ }++partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit[0]);++/* First part (unaligned start) */++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1 | bit);++/* VREPLGR2VR.B/H/W vd, rj */+push_inst(compiler, VREPLGR2VR | VD(cmp1_ind) | RJ_V(tmp1_reg_ind));++if (char1 != char2)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, bit != 0 ? bit : char2);++ /* VREPLGR2VR.B/H/W vd, rj */+ push_inst(compiler, VREPLGR2VR | VD(cmp2_ind) | RJ_V(tmp1_reg_ind));+ }++OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+restart = LABEL();+#endif++OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* VLD vd, rj, si12 */+push_inst(compiler, VLD | VD(data_ind) | RJ_V(str_ptr_reg_ind) | IMM_SI12(0));+fast_forward_char_pair_lsx_compare(compiler, compare_type, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* VMSKLTZ.B vd, vj */+push_inst(compiler, VMSKLTZ_B | VD(tmp_ind) | VJ(data_ind));++/* VPICKVE2GR.WU rd, vj, ui2 */+push_inst(compiler, VPICKVE2GR_WU | RD_V(tmp1_reg_ind) | VJ(tmp_ind) | IMM_UI2(0));++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);++quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* Second part (aligned) */+start = LABEL();++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);++partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit[1]);++/* VLD vd, rj, si12 */+push_inst(compiler, VLD | VD(data_ind) | RJ_V(str_ptr_reg_ind) | IMM_SI12(0));+fast_forward_char_pair_lsx_compare(compiler, compare_type, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* VMSKLTZ.B vd, vj */+push_inst(compiler, VMSKLTZ_B | VD(tmp_ind) | VJ(data_ind));++/* VPICKVE2GR.WU rd, vj, ui2 */+push_inst(compiler, VPICKVE2GR_WU | RD_V(tmp1_reg_ind) | VJ(tmp_ind) | IMM_UI2(0));++CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(quit);++/* CTZ.W rd, rj */+push_inst(compiler, CTZ_W | RD_V(tmp1_reg_ind) | RJ_V(tmp1_reg_ind));++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);++if (common->mode != PCRE2_JIT_COMPLETE)+ {+ JUMPHERE(partial_quit[0]);+ JUMPHERE(partial_quit[1]);+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);+ SELECT(SLJIT_GREATER, STR_PTR, STR_END, 0, STR_PTR);+ }+else+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && offset > 0)+ {+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));++ quit = jump_if_utf_char_start(compiler, TMP1);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, restart);++ JUMPHERE(quit);+ }+#endif+}++#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD HAS_LSX_SUPPORT++static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)+{+DEFINE_COMPILER;+struct sljit_label *start;+struct sljit_jump *quit;+jump_list *not_found = NULL;+vector_compare_type compare_type = vector_compare_match1;+sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, STR_PTR);+sljit_s32 data_ind = 0;+sljit_s32 tmp_ind = 1;+sljit_s32 cmp1_ind = 2;+sljit_s32 cmp2_ind = 3;+sljit_u32 bit = 0;++if (char1 != char2)+ {+ bit = char1 ^ char2;+ compare_type = vector_compare_match1i;++ if (!is_powerof2(bit))+ {+ bit = 0;+ compare_type = vector_compare_match2;+ }+ }++add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));+OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);+OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);++/* First part (unaligned start) */++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1 | bit);++/* VREPLGR2VR vd, rj */+push_inst(compiler, VREPLGR2VR | VD(cmp1_ind) | RJ_V(tmp1_reg_ind));++if (char1 != char2)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, bit != 0 ? bit : char2);+ /* VREPLGR2VR vd, rj */+ push_inst(compiler, VREPLGR2VR | VD(cmp2_ind) | RJ_V(tmp1_reg_ind));+ }++OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* VLD vd, rj, si12 */+push_inst(compiler, VLD | VD(data_ind) | RJ_V(str_ptr_reg_ind) | IMM_SI12(0));+fast_forward_char_pair_lsx_compare(compiler, compare_type, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* VMSKLTZ.B vd, vj */+push_inst(compiler, VMSKLTZ_B | VD(tmp_ind) | VJ(data_ind));++/* VPICKVE2GR.WU rd, vj, ui2 */+push_inst(compiler, VPICKVE2GR_WU | RD_V(tmp1_reg_ind) | VJ(tmp_ind) | IMM_UI2(0));++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);++quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* Second part (aligned) */+start = LABEL();++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);++add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++/* VLD vd, rj, si12 */+push_inst(compiler, VLD | VD(data_ind) | RJ_V(str_ptr_reg_ind) | IMM_SI12(0));+fast_forward_char_pair_lsx_compare(compiler, compare_type, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* VMSKLTZ.B vd, vj */+push_inst(compiler, VMSKLTZ_B | VD(tmp_ind) | VJ(data_ind));++/* VPICKVE2GR.WU rd, vj, ui2 */+push_inst(compiler, VPICKVE2GR_WU | RD_V(tmp1_reg_ind) | VJ(tmp_ind) | IMM_UI2(0));++CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(quit);++/* CTZ.W rd, rj */+push_inst(compiler, CTZ_W | RD_V(tmp1_reg_ind) | RJ_V(tmp1_reg_ind));++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, STR_PTR, 0);+add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));++OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+return not_found;+}++#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD HAS_LSX_SUPPORT++static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)+{+DEFINE_COMPILER;+vector_compare_type compare1_type = vector_compare_match1;+vector_compare_type compare2_type = vector_compare_match1;+sljit_u32 bit1 = 0;+sljit_u32 bit2 = 0;+sljit_u32 diff = IN_UCHARS(offs1 - offs2);+sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);+sljit_s32 tmp2_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP2);+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, STR_PTR);+sljit_s32 data1_ind = 0;+sljit_s32 data2_ind = 1;+sljit_s32 tmp1_ind = 2;+sljit_s32 tmp2_ind = 3;+sljit_s32 cmp1a_ind = 4;+sljit_s32 cmp1b_ind = 5;+sljit_s32 cmp2a_ind = 6;+sljit_s32 cmp2b_ind = 7;+struct sljit_label *start;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *restart;+#endif+struct sljit_jump *jump[2];++SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);+SLJIT_ASSERT(diff <= (unsigned)IN_UCHARS(max_fast_forward_char_pair_offset()));++/* Initialize. */+if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);++ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, STR_END, 0);+ SELECT(SLJIT_LESS, STR_END, TMP1, 0, STR_END);+ }++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++if (char1a == char1b)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1a);+else+ {+ bit1 = char1a ^ char1b;+ if (is_powerof2(bit1))+ {+ compare1_type = vector_compare_match1i;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1a | bit1);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, bit1);+ }+ else+ {+ compare1_type = vector_compare_match2;+ bit1 = 0;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1a);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, char1b);+ }+ }++/* VREPLGR2VR vd, rj */+push_inst(compiler, VREPLGR2VR | VD(cmp1a_ind) | RJ_V(tmp1_reg_ind));++if (char1a != char1b)+ {+ /* VREPLGR2VR vd, rj */+ push_inst(compiler, VREPLGR2VR | VD(cmp1b_ind) | RJ_V(tmp2_reg_ind));+ }++if (char2a == char2b)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char2a);+else+ {+ bit2 = char2a ^ char2b;+ if (is_powerof2(bit2))+ {+ compare2_type = vector_compare_match1i;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char2a | bit2);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, bit2);+ }+ else+ {+ compare2_type = vector_compare_match2;+ bit2 = 0;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char2a);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, char2b);+ }+ }++/* VREPLGR2VR vd, rj */+push_inst(compiler, VREPLGR2VR | VD(cmp2a_ind) | RJ_V(tmp1_reg_ind));++if (char2a != char2b)+ {+ /* VREPLGR2VR vd, rj */+ push_inst(compiler, VREPLGR2VR | VD(cmp2b_ind) | RJ_V(tmp2_reg_ind));+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+restart = LABEL();+#endif++OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, diff);+OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* VLD vd, rj, si12 */+push_inst(compiler, VLD | VD(data1_ind) | RJ_V(str_ptr_reg_ind) | IMM_SI12(0));++jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0);++/* VLD vd, rj, si12 */+push_inst(compiler, VLD | VD(data2_ind) | RJ_V(str_ptr_reg_ind) | IMM_SI12(-(sljit_s8)diff));+jump[1] = JUMP(SLJIT_JUMP);++JUMPHERE(jump[0]);++/* VBSLL.V vd, vj, ui5 */+push_inst(compiler, VBSLL_V | VD(data2_ind) | VJ(data1_ind) | IMM_UI5(diff));++JUMPHERE(jump[1]);++fast_forward_char_pair_lsx_compare(compiler, compare2_type, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);+fast_forward_char_pair_lsx_compare(compiler, compare1_type, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);++/* VAND vd, vj, vk */+push_inst(compiler, VOR_V | VD(data1_ind) | VJ(data1_ind) | VK(data2_ind));++/* VMSKLTZ.B vd, vj */+push_inst(compiler, VMSKLTZ_B | VD(tmp1_ind) | VJ(data1_ind));++/* VPICKVE2GR.WU rd, vj, ui2 */+push_inst(compiler, VPICKVE2GR_WU | RD_V(tmp1_reg_ind) | VJ(tmp1_ind) | IMM_UI2(0));++/* Ignore matches before the first STR_PTR. */+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);++jump[0] = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* Main loop. */+start = LABEL();++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++/* VLD vd, rj, si12 */+push_inst(compiler, VLD | VD(data1_ind) | RJ_V(str_ptr_reg_ind) | IMM_SI12(0));+push_inst(compiler, VLD | VD(data2_ind) | RJ_V(str_ptr_reg_ind) | IMM_SI12(-(sljit_s8)diff));++fast_forward_char_pair_lsx_compare(compiler, compare1_type, data1_ind, cmp1a_ind, cmp1b_ind, tmp2_ind);+fast_forward_char_pair_lsx_compare(compiler, compare2_type, data2_ind, cmp2a_ind, cmp2b_ind, tmp1_ind);++/* VAND.V vd, vj, vk */+push_inst(compiler, VAND_V | VD(data1_ind) | VJ(data1_ind) | VK(data2_ind));++/* VMSKLTZ.B vd, vj */+push_inst(compiler, VMSKLTZ_B | VD(tmp1_ind) | VJ(data1_ind));++/* VPICKVE2GR.WU rd, vj, ui2 */+push_inst(compiler, VPICKVE2GR_WU | RD_V(tmp1_reg_ind) | VJ(tmp1_ind) | IMM_UI2(0));++CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(jump[0]);++/* CTZ.W rd, rj */+push_inst(compiler, CTZ_W | RD_V(tmp1_reg_ind) | RJ_V(tmp1_reg_ind));++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);++add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));++ jump[0] = jump_if_utf_char_start(compiler, TMP1);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart);++ add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP));++ JUMPHERE(jump[0]);+ }+#endif++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+}++#endif /* SLJIT_CONFIG_LOONGARCH_64 */ #endif /* !SUPPORT_VALGRIND */
src/c/pcre2/src/pcre2_jit_test.c view
@@ -148,7 +148,7 @@ #define F_PROPERTY 0x200000 struct regression_test_case {- int compile_options;+ uint32_t compile_options; int newline; int match_options; int start_offset;@@ -198,6 +198,8 @@ { M, A, 0, 0, "[3-57-9]", "5" }, { PCRE2_AUTO_CALLOUT, A, 0, 0, "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "12345678901234567890123456789012345678901234567890123456789012345678901234567890" },+ { 0, A, 0, 0, "..a.......b", "bbbbbbbbbbbbbbbbbbbbbabbbbbbbb" },+ { 0, A, 0, 0, "..a.....b", "bbbbbbbbbbbbbbbbbbbbbabbbbbbbb" }, /* Assertions. */ { MU, A, 0, 0, "\\b[^A]", "A_B#" },@@ -273,6 +275,8 @@ { CM, A, 0, 0, "ab|cd", "CD" }, { CM, A, 0, 0, "a1277|a1377|bX487", "bx487" }, { CM, A, 0, 0, "a1277|a1377|bx487", "bX487" },+ { 0, A, 0, 0, "(a|)b*+a", "a" },+ { 0, A, 0, 0 | F_NOMATCH, "(.|.|.|.|.)(|.|.|.|.)(.||.|.|.)(.|.||.|.)(.|.|.||.)(.|.|.|.|)(A|.|.|.|.)(.|A|.|.|.)(.|.|A|.|.)(.|.|.|A|.)(.|.|.|.|A)(B|.|.|.|.)(.|B|.|.|.)(.|.|B|.|.)(.|.|.|B|.)(.|.|.|.|B)xa", "1234567890123456ax" }, /* Greedy and non-greedy ? operators. */ { MU, A, 0, 0, "(?:a)?a", "laab" },@@ -354,6 +358,8 @@ { MU, A, 0, 0, "_[ab]+_*a", "_aa" }, { MU, A, 0, 0, "#(A+)#\\d+", "#A#A#0" }, { MU, A, 0, 0, "(?P<size>\\d+)m|M", "4M" },+ { M, PCRE2_NEWLINE_CRLF, 0, 0, "\\n?.+#", "\n,\n,#" },+ { 0, A, 0, 0, "<(\\w+)[\\s\\w]+id>", "<br><div id>" }, /* Bracket repeats with limit. */ { MU, A, 0, 0, "(?:(ab){2}){5}M", "abababababababababababM" },@@ -389,7 +395,8 @@ { MU, A, 0, 0, "[^\\x{801}-\\x{fffe}]+", "\xe0\xa0\x81#\xc3\xa9\xf0\x90\x90\x80\xe0\xa0\x80\xef\xbf\xbf\xef\xbf\xbe" }, { MU, A, 0, 0, "[\\x{10001}-\\x{10fffe}]+", "#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf0\x90\x80\x81\xf4\x8f\xbf\xbe\xf4\x8f\xbf\xbf" }, { MU, A, 0, 0, "[^\\x{10001}-\\x{10fffe}]+", "\xf0\x90\x80\x81#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf4\x8f\xbf\xbf\xf4\x8f\xbf\xbe" },- { CMU, A, 0, 0 | F_NOMATCH, "^[\\x{0100}-\\x{017f}]", " " },+ { CMU, A, 0, 0 | F_NOMATCH | F_PROPERTY, "^[\\x{100}-\\x{17f}]", " " },+ { M, A, 0, 0 | F_NOMATCH, "[^\\S\\W]{6}", "abcdefghijk" }, /* Unicode properties. */ { MUP, A, 0, 0, "[1-5\xc3\xa9\\w]", "\xc3\xa1_" },@@ -412,10 +419,13 @@ { MUP, A, 0, 0 | F_PROPERTY, "[\xc3\xa2-\xc3\xa6\xc3\x81-\xc3\x84\xe2\x80\xa8-\xe2\x80\xa9\xe6\x92\xad\\p{Zs}]{2,}", "\xe2\x80\xa7\xe2\x80\xa9\xe6\x92\xad \xe6\x92\xae" }, { MUP, A, 0, 0 | F_PROPERTY, "[\\P{L&}]{2}[^\xc2\x85-\xc2\x89\\p{Ll}\\p{Lu}]{2}", "\xc3\xa9\xe6\x92\xad.a\xe6\x92\xad|\xc2\x8a#" }, { PCRE2_UCP, 0, 0, 0 | F_PROPERTY, "[a-b\\s]{2,5}[^a]", "AB baaa" },- { MUP, 0, 0, 0 | F_NOMATCH, "[^\\p{Hangul}\\p{Z}]", " " },+ { MUP, 0, 0, 0 | F_NOMATCH | F_PROPERTY, "[^\\p{Hangul}\\p{Z}]", " " }, { MUP, 0, 0, 0, "[\\p{Lu}\\P{Latin}]+", "c\xEA\xA4\xAE,A,b" }, { MUP, 0, 0, 0, "[\\x{a92e}\\p{Lu}\\P{Latin}]+", "c\xEA\xA4\xAE,A,b" }, { CMUP, 0, 0, 0, "[^S]\\B", "\xe2\x80\x8a" },+ { MUP, 0, 0, 0 | F_NOMATCH, "[^[:print:]\\x{f6f6}]", "\xef\x9b\xb6" },+ { MUP, 0, 0, 0, "[[:xdigit:]\\x{6500}]#", "\xe6\x94\x80#" },+ { MUP, 0, 0, 0 | F_PROPERTY, "[\\pC\\PC]#", "A#" }, /* Possible empty brackets. */ { MU, A, 0, 0, "(?:|ab||bc|a)+d", "abcxabcabd" },@@ -511,6 +521,7 @@ { MU, A, 0, 0 | F_PROPERTY, "\\X{2,4}..", "#\xcc\x8d#\xcc\x8d##" }, { MU, A, 0, 0, "(c(ab)?+ab)+", "cabcababcab" }, { MU, A, 0, 0, "(?>(a+)b)+aabab", "aaaabaaabaabab" },+ { MU, A, 0, 0 | F_NOMATCH, "(?>a*|)a", "aaa" }, /* Possessive quantifiers. */ { MU, A, 0, 0, "(?:a|b)++m", "mababbaaxababbaam" },@@ -543,6 +554,7 @@ { MU, A, 0, 0, "((b*))++m", "bxbbxbbbxbbm" }, { MU, A, 0, 0, "((b*))*+m", "bxbbxbbbxm" }, { MU, A, 0, 0, "((b*))*+m", "bxbbxbbbxbbm" },+ { MU, A, 0, 0, "(A)*+$", "ABC" }, { MU, A, 0, 0 | F_NOMATCH, "(?>(b{2,4}))(?:(?:(aa|c))++m|(?:(aa|c))+n)", "bbaacaaccaaaacxbbbmbn" }, { MU, A, 0, 0, "((?:b)++a)+(cd)*+m", "bbababbacdcdnbbababbacdcdm" }, { MU, A, 0, 0, "((?:(b))++a)+((c)d)*+m", "bbababbacdcdnbbababbacdcdm" },@@ -589,6 +601,8 @@ { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{1,3}M", "aaaaaaaabbbbaabbbbm" }, { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{0,3}?M", "aaaaaabbbbbbaabbbbbbbbbbm" }, { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{2,3}?", "aaaabbbbaaaabbbbbbbbbb" },+ { MU | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "(a)|\\1+c", "xxc" },+ { MU | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "\\1+?()", "" }, /* Assertions. */ { MU, A, 0, 0, "(?=xx|yy|zz)\\w{4}", "abczzdefg" },@@ -625,6 +639,7 @@ { MU, A, 0, 0, "c(?(?!\\b|(?C)\\B(?C`x`))ab|a)", "cab" }, { MU, A, 0, 0, "a(?=)b", "ab" }, { MU, A, 0, 0 | F_NOMATCH, "a(?!)b", "ab" },+ { MU, A, 0, 0, "(?(?<!|(|a)))", "a" }, /* Not empty, ACCEPT, FAIL */ { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a*", "bcx" },@@ -647,6 +662,7 @@ { MU, A, 0, 0, "(?=(a(b(*ACCEPT)b)))a", "ab" }, { MU, A, PCRE2_NOTEMPTY, 0, "(?=a*(*ACCEPT))c", "c" }, { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "(?=A)", "AB" },+ { MU | PCRE2_ENDANCHORED, A, 0, 0, "aa(*ACCEPT)aa", "aaa" }, /* Conditional blocks. */ { MU, A, 0, 0, "(?(?=(a))a|b)+k", "ababbalbbadabak" },@@ -871,6 +887,7 @@ { MU, A, 0, 0, "(?!(?(?=a)ab|b(*THEN)d))bn|bnn", "bnn" }, { MU, A, 0, 0, "(?=(*THEN: ))* ", " " }, { MU, A, 0, 0, "a(*THEN)(?R) |", "a" },+ { MU, A, 0, 0 | F_NOMATCH, "(?<!(*THEN)a|(*THEN)b|(*THEN)ab?|(*THEN)ba?|)", "c" }, /* Recurse and control verbs. */ { MU, A, 0, 0, "(a(*ACCEPT)b){0}a(?1)b", "aacaabb" },@@ -892,7 +909,7 @@ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)++#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" }, { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)?#", "!ab!abc!ab!ab#" }, { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)??#", "!ab!abc!ab!ab#" },-#endif+#endif /* SUPPORT_UNICODE */ /* Deep recursion. */ { MU, A, 0, 0, "((((?:(?:(?:\\w)+)?)*|(?>\\w)+?)+|(?>\\w)?\?)*)?\\s", "aaaaa+ " },@@ -1157,7 +1174,7 @@ int counter = 0; int jit_compile_mode; int utf = 0;- int disabled_options = 0;+ uint32_t disabled_options = 0; int i; #ifdef SUPPORT_PCRE2_8 pcre2_code_8 *re8;@@ -1362,9 +1379,9 @@ ovector8_1 = pcre2_get_ovector_pointer_8(mdata8_1); ovector8_2 = pcre2_get_ovector_pointer_8(mdata8_2); for (i = 0; i < OVECTOR_SIZE * 2; ++i)- ovector8_1[i] = -2;+ ovector8_1[i] = (PCRE2_SIZE)(-2); for (i = 0; i < OVECTOR_SIZE * 2; ++i)- ovector8_2[i] = -2;+ ovector8_2[i] = (PCRE2_SIZE)(-2); pcre2_set_match_limit_8(mcontext8, 10000000); } if (re8) {@@ -1402,9 +1419,9 @@ ovector16_1 = pcre2_get_ovector_pointer_16(mdata16_1); ovector16_2 = pcre2_get_ovector_pointer_16(mdata16_2); for (i = 0; i < OVECTOR_SIZE * 2; ++i)- ovector16_1[i] = -2;+ ovector16_1[i] = (PCRE2_SIZE)(-2); for (i = 0; i < OVECTOR_SIZE * 2; ++i)- ovector16_2[i] = -2;+ ovector16_2[i] = (PCRE2_SIZE)(-2); pcre2_set_match_limit_16(mcontext16, 10000000); } if (re16) {@@ -1447,9 +1464,9 @@ ovector32_1 = pcre2_get_ovector_pointer_32(mdata32_1); ovector32_2 = pcre2_get_ovector_pointer_32(mdata32_2); for (i = 0; i < OVECTOR_SIZE * 2; ++i)- ovector32_1[i] = -2;+ ovector32_1[i] = (PCRE2_SIZE)(-2); for (i = 0; i < OVECTOR_SIZE * 2; ++i)- ovector32_2[i] = -2;+ ovector32_2[i] = (PCRE2_SIZE)(-2); pcre2_set_match_limit_32(mcontext32, 10000000); } if (re32) {@@ -1829,7 +1846,7 @@ #define CPI (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_INVALID_UTF) struct invalid_utf8_regression_test_case {- int compile_options;+ uint32_t compile_options; int jit_compile_options; int start_offset; int skip_left;@@ -1980,6 +1997,9 @@ { PCRE2_UTF, CI, 0, 0, 0, 7, 11, { "#\xc7\x85#", NULL }, "\x80\x80#\xc7\x80\x80\x80#\xc7\x85#" }, { PCRE2_UTF | PCRE2_UCP, CI, 0, 0, 0, -1, -1, { "[\\s]", NULL }, "\xed\xa0\x80" },+ { PCRE2_UTF, CI, 0, 0, 0, 0, 3, { "[\\D]", NULL }, "\xe0\xab\xaa@" },+ { PCRE2_UTF, CI, 0, 0, 0, 0, 3, { "\\D+", NULL }, "n\xc3\xb1" },+ { PCRE2_UTF, CI, 0, 0, 0, 0, 5, { "\\W+", NULL }, "@\xf0\x9d\x84\x9e" }, /* These two are not invalid UTF tests, but this infrastructure fits better for them. */ { 0, PCRE2_JIT_COMPLETE, 0, 0, 1, -1, -1, { "\\X{2}", NULL }, "\r\n\n" },@@ -2117,7 +2137,7 @@ #define CPI (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_INVALID_UTF) struct invalid_utf16_regression_test_case {- int compile_options;+ uint32_t compile_options; int jit_compile_options; int start_offset; int skip_left;@@ -2325,7 +2345,7 @@ #define CPI (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_INVALID_UTF) struct invalid_utf32_regression_test_case {- int compile_options;+ uint32_t compile_options; int jit_compile_options; int start_offset; int skip_left;
src/c/pcre2/src/pcre2_maketables.c view
@@ -52,8 +52,6 @@ # include "pcre2_internal.h" #endif -- /************************************************* * Create PCRE2 character tables * *************************************************/@@ -98,7 +96,11 @@ /* Next the case-flipping table */ -for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i);+for (i = 0; i < 256; i++)+ {+ int c = islower(i)? toupper(i) : tolower(i);+ *p++ = (c < 256)? c : i;+ } /* Then the character class tables. Don't try to be clever and save effort on exclusive ones - in some locales things may be different.
src/c/pcre2/src/pcre2_match.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2015-2022 University of Cambridge+ New API code Copyright (c) 2015-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -43,6 +43,8 @@ #include "config.h" #endif +#include "pcre2_internal.h"+ /* These defines enable debugging code */ /* #define DEBUG_FRAMES_DISPLAY */@@ -53,6 +55,10 @@ #include <stdarg.h> #endif +#ifdef DEBUG_SHOW_OPS+static const char *OP_names[] = { OP_NAME_LIST };+#endif+ /* These defines identify the name of the block containing "static" information, and fields within it. */ @@ -60,8 +66,6 @@ #define PSSTART start_subject /* Field containing processed string start */ #define PSEND end_subject /* Field containing processed string end */ -#include "pcre2_internal.h"- #define RECURSE_UNSET 0xffffffffu /* Bigger than max group number */ /* Masks for identifying the public options that are permitted at match time. */@@ -69,7 +73,8 @@ #define PUBLIC_MATCH_OPTIONS \ (PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \ PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \- PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT|PCRE2_COPY_MATCHED_SUBJECT)+ PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT|PCRE2_COPY_MATCHED_SUBJECT| \+ PCRE2_DISABLE_RECURSELOOP_CHECK) #define PUBLIC_JIT_MATCH_OPTIONS \ (PCRE2_NO_UTF_CHECK|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY|\@@ -150,7 +155,7 @@ enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10, RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20, RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,- RM31, RM32, RM33, RM34, RM35, RM36 };+ RM31, RM32, RM33, RM34, RM35, RM36, RM37 }; #ifdef SUPPORT_WIDE_CHARS enum { RM100=100, RM101 };@@ -204,6 +209,7 @@ P a previous frame of interest frame_size the frame size mb points to the match block+ match_data points to the match data block s identification text Returns: nothing@@ -211,7 +217,7 @@ static void display_frames(FILE *f, heapframe *F, heapframe *P, PCRE2_SIZE frame_size,- match_block *mb, const char *s, ...)+ match_block *mb, pcre2_match_data *match_data, const char *s, ...) { uint32_t i; heapframe *Q;@@ -223,10 +229,10 @@ va_end(ap); if (P != NULL) fprintf(f, " P=%lu",- ((char *)P - (char *)(mb->match_frames))/frame_size);+ ((char *)P - (char *)(match_data->heapframes))/frame_size); fprintf(f, "\n"); -for (i = 0, Q = mb->match_frames;+for (i = 0, Q = match_data->heapframes; Q <= F; i++, Q = (heapframe *)((char *)Q + frame_size)) {@@ -490,10 +496,16 @@ match() recursively, but this ran substantially slower. The current version is a refactoring that uses a vector of frames to remember backtracking points. This runs no slower, and possibly even a bit faster than the original recursive-implementation. An initial vector of size START_FRAMES_SIZE (enough for maybe-50 frames) is allocated on the system stack. If this is not big enough, the-heap is used for a larger vector.+implementation. +At first, an initial vector of size START_FRAMES_SIZE (enough for maybe 50+frames) was allocated on the system stack. If this was not big enough, the heap+was used for a larger vector. However, it turns out that there are environments+where taking as little as 20KiB from the system stack is an embarrassment.+After another refactoring, the heap is used exclusively, but a pointer the+frames vector and its size are cached in the match_data block, so that there is+no new memory allocation if the same match_data block is used for multiple+matches (unless the frames vector has to be extended). ******************************************************************************* ******************************************************************************/ @@ -566,10 +578,9 @@ Arguments: start_eptr starting character in subject start_ecode starting position in compiled code- ovector pointer to the final output vector- oveccount number of pairs in ovector top_bracket number of capturing parentheses in the pattern frame_size size of each backtracking frame+ match_data pointer to the match_data block mb pointer to "static" variables block Returns: MATCH_MATCH if matched ) these values are >= 0@@ -580,20 +591,23 @@ */ static int-match(PCRE2_SPTR start_eptr, PCRE2_SPTR start_ecode, PCRE2_SIZE *ovector,- uint16_t oveccount, uint16_t top_bracket, PCRE2_SIZE frame_size,- match_block *mb)+match(PCRE2_SPTR start_eptr, PCRE2_SPTR start_ecode, uint16_t top_bracket,+ PCRE2_SIZE frame_size, pcre2_match_data *match_data, match_block *mb) { /* Frame-handling variables */ heapframe *F; /* Current frame pointer */ heapframe *N = NULL; /* Temporary frame pointers */ heapframe *P = NULL;++heapframe *frames_top; /* End of frames vector */ heapframe *assert_accept_frame = NULL; /* For passing back a frame with captures */-PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */+PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */ /* Local variables that do not need to be preserved over calls to RRMATCH(). */ +PCRE2_SPTR branch_end = NULL;+PCRE2_SPTR branch_start; PCRE2_SPTR bracode; /* Temp pointer to start of group */ PCRE2_SIZE offset; /* Used for group offsets */ PCRE2_SIZE length; /* Used for various length calculations */@@ -627,10 +641,11 @@ frame_copy_size = frame_size - offsetof(heapframe, eptr); -/* Set up the first current frame at the start of the vector, and initialize-fields that are not reset for new frames. */+/* Set up the first frame and the end of the frames vector. */ -F = mb->match_frames;+F = match_data->heapframes;+frames_top = (heapframe *)((char *)F + match_data->heapframes_size);+ Frdepth = 0; /* "Recursion" depth */ Fcapture_last = 0; /* Number of most recent capture */ Fcurrent_recurse = RECURSE_UNSET; /* Not pattern recursing. */@@ -646,38 +661,58 @@ MATCH_RECURSE: -/* Set up a new backtracking frame. If the vector is full, get a new one-on the heap, doubling the size, but constrained by the heap limit. */+/* Set up a new backtracking frame. If the vector is full, get a new one,+doubling the size, but constrained by the heap limit (which is in KiB). */ N = (heapframe *)((char *)F + frame_size);-if (N >= mb->match_frames_top)+if ((heapframe *)((char *)N + frame_size) >= frames_top) {- PCRE2_SIZE newsize = mb->frame_vector_size * 2; heapframe *new;+ PCRE2_SIZE newsize;+ PCRE2_SIZE usedsize = (char *)N - (char *)(match_data->heapframes); - if ((newsize / 1024) > mb->heap_limit)+ if (match_data->heapframes_size >= PCRE2_SIZE_MAX / 2) {- PCRE2_SIZE maxsize = ((mb->heap_limit * 1024)/frame_size) * frame_size;- if (mb->frame_vector_size >= maxsize) return PCRE2_ERROR_HEAPLIMIT;- newsize = maxsize;+ if (match_data->heapframes_size == PCRE2_SIZE_MAX - 1)+ return PCRE2_ERROR_NOMEMORY;+ newsize = PCRE2_SIZE_MAX - 1; }+ else+ newsize = match_data->heapframes_size * 2; - new = mb->memctl.malloc(newsize, mb->memctl.memory_data);+ if (newsize / 1024 >= mb->heap_limit)+ {+ PCRE2_SIZE old_size = match_data->heapframes_size / 1024;+ if (mb->heap_limit <= old_size)+ return PCRE2_ERROR_HEAPLIMIT;+ else+ {+ PCRE2_SIZE max_delta = 1024 * (mb->heap_limit - old_size);+ int over_bytes = match_data->heapframes_size % 1024;+ if (over_bytes) max_delta -= (1024 - over_bytes);+ newsize = match_data->heapframes_size + max_delta;+ }+ }++ /* With a heap limit set, the permitted additional size may not be enough for+ another frame, so do a final check. */++ if (newsize - usedsize < frame_size) return PCRE2_ERROR_HEAPLIMIT;+ new = match_data->memctl.malloc(newsize, match_data->memctl.memory_data); if (new == NULL) return PCRE2_ERROR_NOMEMORY;- memcpy(new, mb->match_frames, mb->frame_vector_size);+ memcpy(new, match_data->heapframes, usedsize); - F = (heapframe *)((char *)new + ((char *)F - (char *)mb->match_frames));- N = (heapframe *)((char *)F + frame_size);+ N = (heapframe *)((char *)new + usedsize);+ F = (heapframe *)((char *)N - frame_size); - if (mb->match_frames != mb->stack_frames)- mb->memctl.free(mb->match_frames, mb->memctl.memory_data);- mb->match_frames = new;- mb->match_frames_top = (heapframe *)((char *)mb->match_frames + newsize);- mb->frame_vector_size = newsize;+ match_data->memctl.free(match_data->heapframes, match_data->memctl.memory_data);+ match_data->heapframes = new;+ match_data->heapframes_size = newsize;+ frames_top = (heapframe *)((char *)new + newsize); } #ifdef DEBUG_SHOW_RMATCH-fprintf(stderr, "++ RMATCH %2d frame=%d", Freturn_id, Frdepth + 1);+fprintf(stderr, "++ RMATCH %d frame=%d", Freturn_id, Frdepth + 1); if (group_frame_type != 0) { fprintf(stderr, " type=%x ", group_frame_type);@@ -731,7 +766,7 @@ if (group_frame_type != 0) {- Flast_group_offset = (char *)F - (char *)mb->match_frames;+ Flast_group_offset = (char *)F - (char *)match_data->heapframes; if (GF_IDMASK(group_frame_type) == GF_RECURSE) Fcurrent_recurse = GF_DATAMASK(group_frame_type); group_frame_type = 0;@@ -747,10 +782,16 @@ if (mb->match_call_count++ >= mb->match_limit) return PCRE2_ERROR_MATCHLIMIT; if (Frdepth >= mb->match_limit_depth) return PCRE2_ERROR_DEPTHLIMIT; +#ifdef DEBUG_SHOW_OPS+fprintf(stderr, "\n++ New frame: type=0x%x subject offset %ld\n",+ GF_IDMASK(Fgroup_frame_type), Feptr - mb->start_subject);+#endif+ for (;;) { #ifdef DEBUG_SHOW_OPS-fprintf(stderr, "++ op=%d\n", *Fecode);+fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,+ OP_names[*Fecode]); #endif Fop = (uint8_t)(*Fecode); /* Cast needed for 16-bit and 32-bit modes */@@ -773,7 +814,7 @@ for(;;) { if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL;- N = (heapframe *)((char *)mb->match_frames + offset);+ N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (N->group_frame_type == (GF_CAPTURE | number)) break; offset = P->last_group_offset;@@ -798,20 +839,21 @@ assert_accept_frame = F; RRETURN(MATCH_ACCEPT); - /* If recursing, we have to find the most recent recursion. */+ /* For ACCEPT within a recursion, we have to find the most recent+ recursion. If not in a recursion, fall through to code that is common with+ OP_END. */ case OP_ACCEPT:- case OP_END:-- /* Handle end of a recursion. */- if (Fcurrent_recurse != RECURSE_UNSET) {+#ifdef DEBUG_SHOW_OPS+ fprintf(stderr, "++ Accept within recursion\n");+#endif offset = Flast_group_offset; for(;;) { if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL;- N = (heapframe *)((char *)mb->match_frames + offset);+ N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (GF_IDMASK(N->group_frame_type) == GF_RECURSE) break; offset = P->last_group_offset;@@ -829,27 +871,49 @@ Fecode += 1 + LINK_SIZE; continue; }+ /* Fall through */ - /* Not a recursion. Fail for an empty string match if either PCRE2_NOTEMPTY- is set, or if PCRE2_NOTEMPTY_ATSTART is set and we have matched at the- start of the subject. In both cases, backtracking will then try other- alternatives, if any. */+ /* OP_END itself can never be reached within a recursion because that is+ picked up when the OP_KET that always precedes OP_END is reached. */ + case OP_END:++ /* Fail for an empty string match if either PCRE2_NOTEMPTY is set, or if+ PCRE2_NOTEMPTY_ATSTART is set and we have matched at the start of the+ subject. In both cases, backtracking will then try other alternatives, if+ any. */+ if (Feptr == Fstart_match && ((mb->moptions & PCRE2_NOTEMPTY) != 0 || ((mb->moptions & PCRE2_NOTEMPTY_ATSTART) != 0 && Fstart_match == mb->start_subject + mb->start_offset)))+ {+#ifdef DEBUG_SHOW_OPS+ fprintf(stderr, "++ Backtrack because empty string\n");+#endif RRETURN(MATCH_NOMATCH);+ } - /* Also fail if PCRE2_ENDANCHORED is set and the end of the match is not+ /* Fail if PCRE2_ENDANCHORED is set and the end of the match is not the end of the subject. After (*ACCEPT) we fail the entire match (at this- position) but backtrack on reaching the end of the pattern. */+ position) but backtrack if we've reached the end of the pattern. This+ applies whether or not we are in a recursion. */ if (Feptr < mb->end_subject && ((mb->moptions | mb->poptions) & PCRE2_ENDANCHORED) != 0) {- if (Fop == OP_END) RRETURN(MATCH_NOMATCH);- return MATCH_NOMATCH;+ if (Fop == OP_END)+ {+#ifdef DEBUG_SHOW_OPS+ fprintf(stderr, "++ Backtrack because not at end (endanchored set)\n");+#endif+ RRETURN(MATCH_NOMATCH);+ }++#ifdef DEBUG_SHOW_OPS+ fprintf(stderr, "++ Failed ACCEPT not at end (endanchnored set)\n");+#endif+ return MATCH_NOMATCH; /* (*ACCEPT) */ } /* We have a successful match of the whole pattern. Record the result and@@ -864,14 +928,15 @@ mb->mark = Fmark; /* and the last success mark */ if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr; - ovector[0] = Fstart_match - mb->start_subject;- ovector[1] = Feptr - mb->start_subject;+ match_data->ovector[0] = Fstart_match - mb->start_subject;+ match_data->ovector[1] = Feptr - mb->start_subject; /* Set i to the smaller of the sizes of the external and frame ovectors. */ - i = 2 * ((top_bracket + 1 > oveccount)? oveccount : top_bracket + 1);- memcpy(ovector + 2, Fovector, (i - 2) * sizeof(PCRE2_SIZE));- while (--i >= Foffset_top + 2) ovector[i] = PCRE2_UNSET;+ i = 2 * ((top_bracket + 1 > match_data->oveccount)?+ match_data->oveccount : top_bracket + 1);+ memcpy(match_data->ovector + 2, Fovector, (i - 2) * sizeof(PCRE2_SIZE));+ while (--i >= Foffset_top + 2) match_data->ovector[i] = PCRE2_UNSET; return MATCH_MATCH; /* Note: NOT RRETURN */ @@ -2421,6 +2486,7 @@ GETCHARINCTEST(fc, Feptr); { const uint32_t *cp;+ uint32_t chartype; const ucd_record *prop = GET_UCD(fc); BOOL notmatch = Fop == OP_NOTPROP; @@ -2431,9 +2497,10 @@ break; case PT_LAMP:- if ((prop->chartype == ucp_Lu ||- prop->chartype == ucp_Ll ||- prop->chartype == ucp_Lt) == notmatch)+ chartype = prop->chartype;+ if ((chartype == ucp_Lu ||+ chartype == ucp_Ll ||+ chartype == ucp_Lt) == notmatch) RRETURN(MATCH_NOMATCH); break; @@ -2463,8 +2530,9 @@ /* These are specials */ case PT_ALNUM:- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N) == notmatch)+ chartype = prop->chartype;+ if ((PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N) == notmatch) RRETURN(MATCH_NOMATCH); break; @@ -2489,13 +2557,22 @@ break; case PT_WORD:- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N ||- fc == CHAR_UNDERSCORE) == notmatch)+ chartype = prop->chartype;+ if ((PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N ||+ chartype == ucp_Mn ||+ chartype == ucp_Pc) == notmatch) RRETURN(MATCH_NOMATCH); break; case PT_CLIST:+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (fc > MAX_UTF_CODE_POINT)+ {+ if (notmatch) break;;+ RRETURN(MATCH_NOMATCH);+ }+#endif cp = PRIV(ucd_caseless_sets) + Fecode[2]; for (;;) {@@ -2791,16 +2868,17 @@ case PT_WORD: for (i = 1; i <= Lmin; i++) {- int category;+ int chartype, category; if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(fc, Feptr);- category = UCD_CATEGORY(fc);+ chartype = UCD_CHARTYPE(fc);+ category = PRIV(ucp_gentype)[chartype]; if ((category == ucp_L || category == ucp_N ||- fc == CHAR_UNDERSCORE) == notmatch)+ chartype == ucp_Mn || chartype == ucp_Pc) == notmatch) RRETURN(MATCH_NOMATCH); } break;@@ -2815,6 +2893,13 @@ RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(fc, Feptr);+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (fc > MAX_UTF_CODE_POINT)+ {+ if (notmatch) continue;+ RRETURN(MATCH_NOMATCH);+ }+#endif cp = PRIV(ucd_caseless_sets) + Lpropvalue; for (;;) {@@ -3595,7 +3680,7 @@ case PT_WORD: for (;;) {- int category;+ int chartype, category; RMATCH(Fecode, RM215); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);@@ -3605,10 +3690,12 @@ RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(fc, Feptr);- category = UCD_CATEGORY(fc);+ chartype = UCD_CHARTYPE(fc);+ category = PRIV(ucp_gentype)[chartype]; if ((category == ucp_L || category == ucp_N ||- fc == CHAR_UNDERSCORE) == (Lctype == OP_NOTPROP))+ chartype == ucp_Mn ||+ chartype == ucp_Pc) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */@@ -3626,6 +3713,13 @@ RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(fc, Feptr);+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (fc > MAX_UTF_CODE_POINT)+ {+ if (Lctype == OP_NOTPROP) continue;+ RRETURN(MATCH_NOMATCH);+ }+#endif cp = PRIV(ucd_caseless_sets) + Lpropvalue; for (;;) {@@ -4176,7 +4270,7 @@ case PT_WORD: for (i = Lmin; i < Lmax; i++) {- int category;+ int chartype, category; int len = 1; if (Feptr >= mb->end_subject) {@@ -4184,9 +4278,12 @@ break; } GETCHARLENTEST(fc, Feptr, len);- category = UCD_CATEGORY(fc);- if ((category == ucp_L || category == ucp_N ||- fc == CHAR_UNDERSCORE) == notmatch)+ chartype = UCD_CHARTYPE(fc);+ category = PRIV(ucp_gentype)[chartype];+ if ((category == ucp_L ||+ category == ucp_N ||+ chartype == ucp_Mn ||+ chartype == ucp_Pc) == notmatch) break; Feptr+= len; }@@ -4203,14 +4300,24 @@ break; } GETCHARLENTEST(fc, Feptr, len);- cp = PRIV(ucd_caseless_sets) + Lpropvalue;- for (;;)+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (fc > MAX_UTF_CODE_POINT) {- if (fc < *cp)- { if (notmatch) break; else goto GOT_MAX; }- if (fc == *cp++)- { if (notmatch) goto GOT_MAX; else break; }+ if (!notmatch) goto GOT_MAX; }+ else+#endif+ {+ cp = PRIV(ucd_caseless_sets) + Lpropvalue;+ for (;;)+ {+ if (fc < *cp)+ { if (notmatch) break; else goto GOT_MAX; }+ if (fc == *cp++)+ { if (notmatch) goto GOT_MAX; else break; }+ }+ }+ Feptr += len; } GOT_MAX:@@ -5308,9 +5415,11 @@ /* ===================================================================== */- /* Recursion either matches the current regex, or some subexpression. The- offset data is the offset to the starting bracket from the start of the- whole pattern. (This is so that it works from duplicated subpatterns.) */+ /* Pattern recursion either matches the current regex, or some+ subexpression. The offset data is the offset to the starting bracket from+ the start of the whole pattern. This is so that it works from duplicated+ subpatterns. For a whole-pattern recursion, we have to infer the number+ zero. */ #define Lframe_type F->temp_32[0] #define Lstart_branch F->temp_sptr[0]@@ -5319,28 +5428,35 @@ bracode = mb->start_code + GET(Fecode, 1); number = (bracode == mb->start_code)? 0 : GET2(bracode, 1 + LINK_SIZE); - /* If we are already in a recursion, check for repeating the same one- without advancing the subject pointer. This should catch convoluted mutual- recursions. (Some simple cases are caught at compile time.) */+ /* If we are already in a pattern recursion, check for repeating the same+ one without changing the subject pointer or the last referenced character+ in the subject. This should catch convoluted mutual recursions; some+ simple cases are caught at compile time. However, there are rare cases when+ this check needs to be turned off. In this case, actual recursion loops+ will be caught by the match or heap limits. */ if (Fcurrent_recurse != RECURSE_UNSET) { offset = Flast_group_offset; while (offset != PCRE2_UNSET) {- N = (heapframe *)((char *)mb->match_frames + offset);+ N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (N->group_frame_type == (GF_RECURSE | number)) {- if (Feptr == P->eptr) return PCRE2_ERROR_RECURSELOOP;+ if (Feptr == P->eptr && mb->last_used_ptr == P->recurse_last_used &&+ (mb->moptions & PCRE2_DISABLE_RECURSELOOP_CHECK) == 0)+ return PCRE2_ERROR_RECURSELOOP; break; } offset = P->last_group_offset; } } - /* Now run the recursion, branch by branch. */+ /* Remember the current last referenced character and then run the+ recursion branch by branch. */ + F->recurse_last_used = mb->last_used_ptr; Lstart_branch = bracode; Lframe_type = GF_RECURSE | number; @@ -5669,13 +5785,13 @@ /* ===================================================================== */- /* Move the subject pointer back. This occurs only at the start of each- branch of a lookbehind assertion. If we are too close to the start to move- back, fail. When working with UTF-8 we move back a number of characters,- not bytes. */+ /* Move the subject pointer back by one fixed amount. This occurs at the+ start of each branch that has a fixed length in a lookbehind assertion. If+ we are too close to the start to move back, fail. When working with UTF-8+ we move back a number of characters, not bytes. */ case OP_REVERSE:- number = GET(Fecode, 1);+ number = GET2(Fecode, 1); #ifdef SUPPORT_UNICODE if (utf) {@@ -5689,7 +5805,7 @@ else #endif - /* No UTF-8 support, or not in UTF-8 mode: count is code unit count */+ /* No UTF support, or not in UTF mode: count is code unit count */ { if ((ptrdiff_t)number > Feptr - mb->start_subject) RRETURN(MATCH_NOMATCH);@@ -5699,15 +5815,84 @@ /* Save the earliest consulted character, then skip to next opcode */ if (Feptr < mb->start_used_ptr) mb->start_used_ptr = Feptr;- Fecode += 1 + LINK_SIZE;+ Fecode += 1 + IMM2_SIZE; break; /* ===================================================================== */+ /* Move the subject pointer back by a variable amount. This occurs at the+ start of each branch of a lookbehind assertion when the branch has a+ variable, but limited, length. A loop is needed to try matching the branch+ after moving back different numbers of characters. If we are too close to+ the start to move back even the minimum amount, fail. When working with+ UTF-8 we move back a number of characters, not bytes. */++#define Lmin F->temp_32[0]+#define Lmax F->temp_32[1]+#define Leptr F->temp_sptr[0]++ case OP_VREVERSE:+ Lmin = GET2(Fecode, 1);+ Lmax = GET2(Fecode, 1 + IMM2_SIZE);+ Leptr = Feptr;++ /* Move back by the maximum branch length and then work forwards. This+ ensures that items such as \d{3,5} get the maximum length, which is+ relevant for captures, and makes for Perl compatibility. */++#ifdef SUPPORT_UNICODE+ if (utf)+ {+ for (i = 0; i < Lmax; i++)+ {+ if (Feptr == mb->start_subject)+ {+ if (i < Lmin) RRETURN(MATCH_NOMATCH);+ Lmax = i;+ break;+ }+ Feptr--;+ BACKCHAR(Feptr);+ }+ }+ else+#endif++ /* No UTF support or not in UTF mode */++ {+ ptrdiff_t diff = Feptr - mb->start_subject;+ uint32_t available = (diff > 65535)? 65535 : ((diff > 0)? (int)diff : 0);+ if (Lmin > available) RRETURN(MATCH_NOMATCH);+ if (Lmax > available) Lmax = available;+ Feptr -= Lmax;+ }++ /* Now try matching, moving forward one character on failure, until we+ reach the mimimum back length. */++ for (;;)+ {+ RMATCH(Fecode + 1 + 2 * IMM2_SIZE, RM37);+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);+ if (Lmax-- <= Lmin) RRETURN(MATCH_NOMATCH);+ Feptr++;+#ifdef SUPPORT_UNICODE+ if (utf) { FORWARDCHARTEST(Feptr, mb->end_subject); }+#endif+ }+ /* Control never reaches here */++#undef Lmin+#undef Lmax+#undef Leptr++ /* ===================================================================== */ /* An alternation is the end of a branch; scan along to find the end of the bracketed group. */ case OP_ALT:+ branch_end = Fecode; do Fecode += GET(Fecode,1); while (*Fecode == OP_ALT); break; @@ -5715,7 +5900,8 @@ /* ===================================================================== */ /* The end of a parenthesized group. For all but OP_BRA and OP_COND, the starting frame was added to the chained frames in order to remember the- starting subject position for the group. */+ starting subject position for the group. (Not true for OP_BRA when it's a+ whole pattern recursion, but that is handled separately below.)*/ case OP_KET: case OP_KETRMIN:@@ -5724,12 +5910,18 @@ bracode = Fecode - GET(Fecode, 1); - /* Point N to the frame at the start of the most recent group.- Remember the subject pointer at the start of the group. */+ if (branch_end == NULL) branch_end = Fecode;+ branch_start = bracode;+ while (branch_start + GET(branch_start, 1) != branch_end)+ branch_start += GET(branch_start, 1);+ branch_end = NULL; + /* Point N to the frame at the start of the most recent group, and P to its+ predecessor. Remember the subject pointer at the start of the group. */+ if (*bracode != OP_BRA && *bracode != OP_COND) {- N = (heapframe *)((char *)mb->match_frames + Flast_group_offset);+ N = (heapframe *)((char *)match_data->heapframes + Flast_group_offset); P = (heapframe *)((char *)N - frame_size); Flast_group_offset = P->last_group_offset; @@ -5761,27 +5953,64 @@ switch (*bracode) {- case OP_BRA: /* No need to do anything for these */- case OP_COND:+ /* Whole pattern recursion is handled as a recursion into group 0, but+ the entire pattern is wrapped in OP_BRA/OP_KET rather than a capturing+ group - a design mistake: it should perhaps have been capture group 0.+ Anyway, that means the end of such recursion must be handled here. It is+ detected by checking for an immediately following OP_END when we are+ recursing in group 0. If this is not the end of a whole-pattern+ recursion, there is nothing to be done. */++ case OP_BRA:+ if (Fcurrent_recurse != 0 || Fecode[1+LINK_SIZE] != OP_END) break;++ /* It is the end of whole-pattern recursion. */++ offset = Flast_group_offset;+ if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL;+ N = (heapframe *)((char *)match_data->heapframes + offset);+ P = (heapframe *)((char *)N - frame_size);+ Flast_group_offset = P->last_group_offset;++ /* Reinstate the previous set of captures and then carry on after the+ recursion call. */++ memcpy((char *)F + offsetof(heapframe, ovector), P->ovector,+ Foffset_top * sizeof(PCRE2_SIZE));+ Foffset_top = P->offset_top;+ Fcapture_last = P->capture_last;+ Fcurrent_recurse = P->current_recurse;+ Fecode = P->ecode + 1 + LINK_SIZE;+ continue; /* With next opcode */++ case OP_COND: /* No need to do anything for these */ case OP_SCOND: break; /* Non-atomic positive assertions are like OP_BRA, except that the subject pointer must be put back to where it was at the start of the- assertion. */+ assertion. For a variable lookbehind, check its end point. */ - case OP_ASSERT_NA: case OP_ASSERTBACK_NA:+ if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)+ RRETURN(MATCH_NOMATCH);+ /* Fall through */++ case OP_ASSERT_NA: if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr; Feptr = P->eptr; break; /* Atomic positive assertions are like OP_ONCE, except that in addition the subject pointer must be put back to where it was at the start of the- assertion. */+ assertion. For a variable lookbehind, check its end point. */ - case OP_ASSERT: case OP_ASSERTBACK:+ if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)+ RRETURN(MATCH_NOMATCH);+ /* Fall through */++ case OP_ASSERT: if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr; Feptr = P->eptr; /* Fall through */@@ -5802,10 +6031,15 @@ break; /* A matching negative assertion returns MATCH, which is turned into- NOMATCH at the assertion level. */+ NOMATCH at the assertion level. For a variable lookbehind, check its end+ point. */ - case OP_ASSERT_NOT: case OP_ASSERTBACK_NOT:+ if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)+ RRETURN(MATCH_NOMATCH);+ /* Fall through */++ case OP_ASSERT_NOT: RRETURN(MATCH_MATCH); /* At the end of a script run, apply the script-checking rules. This code@@ -5816,9 +6050,8 @@ if (!PRIV(script_run)(P->eptr, Feptr, utf)) RRETURN(MATCH_NOMATCH); break; - /* Whole-pattern recursion is coded as a recurse into group 0, so it- won't be picked up here. Instead, we catch it when the OP_END is reached.- Other recursion is handled here. */+ /* Whole-pattern recursion is coded as a recurse into group 0, and is+ handled with OP_BRA above. Other recursion is handled here. */ case OP_CBRA: case OP_CBRAPOS:@@ -5833,7 +6066,7 @@ { P = (heapframe *)((char *)N - frame_size); memcpy((char *)F + offsetof(heapframe, ovector), P->ovector,- P->offset_top * sizeof(PCRE2_SIZE));+ Foffset_top * sizeof(PCRE2_SIZE)); Foffset_top = P->offset_top; Fcapture_last = P->capture_last; Fcurrent_recurse = P->current_recurse;@@ -5916,10 +6149,10 @@ if ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0) goto ASSERT_NL_OR_EOS; /* Fall through */- /* Unconditional end of subject assertion (\z) */+ /* Unconditional end of subject assertion (\z). */ case OP_EOD:- if (Feptr < mb->end_subject) RRETURN(MATCH_NOMATCH);+ if (Feptr < mb->true_end_subject) RRETURN(MATCH_NOMATCH); if (mb->partial != 0) { mb->hitend = TRUE;@@ -6031,6 +6264,8 @@ case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY:+ case OP_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY: if (Feptr == mb->check_subject) prev_is_word = FALSE; else { PCRE2_SPTR lastptr = Feptr - 1;@@ -6045,13 +6280,12 @@ fc = *lastptr; if (lastptr < mb->start_used_ptr) mb->start_used_ptr = lastptr; #ifdef SUPPORT_UNICODE- if ((mb->poptions & PCRE2_UCP) != 0)+ if (Fop == OP_UCP_WORD_BOUNDARY || Fop == OP_NOT_UCP_WORD_BOUNDARY) {- if (fc == '_') prev_is_word = TRUE; else- {- int cat = UCD_CATEGORY(fc);- prev_is_word = (cat == ucp_L || cat == ucp_N);- }+ int chartype = UCD_CHARTYPE(fc);+ int category = PRIV(ucp_gentype)[chartype];+ prev_is_word = (category == ucp_L || category == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc); } else #endif /* SUPPORT_UNICODE */@@ -6079,13 +6313,12 @@ fc = *Feptr; if (nextptr > mb->last_used_ptr) mb->last_used_ptr = nextptr; #ifdef SUPPORT_UNICODE- if ((mb->poptions & PCRE2_UCP) != 0)+ if (Fop == OP_UCP_WORD_BOUNDARY || Fop == OP_NOT_UCP_WORD_BOUNDARY) {- if (fc == '_') cur_is_word = TRUE; else- {- int cat = UCD_CATEGORY(fc);- cur_is_word = (cat == ucp_L || cat == ucp_N);- }+ int chartype = UCD_CHARTYPE(fc);+ int category = PRIV(ucp_gentype)[chartype];+ cur_is_word = (category == ucp_L || category == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc); } else #endif /* SUPPORT_UNICODE */@@ -6094,7 +6327,7 @@ /* Now see if the situation is what we want */ - if ((*Fecode++ == OP_WORD_BOUNDARY)?+ if ((*Fecode++ == OP_WORD_BOUNDARY || Fop == OP_UCP_WORD_BOUNDARY)? cur_is_word == prev_is_word : cur_is_word != prev_is_word) RRETURN(MATCH_NOMATCH); break;@@ -6240,7 +6473,7 @@ mb->cb->callout_flags |= PCRE2_CALLOUT_BACKTRACK; /* Note for callouts */ #ifdef DEBUG_SHOW_RMATCH-fprintf(stderr, "++ RETURN %d to %d\n", rrc, Freturn_id);+fprintf(stderr, "++ RETURN %d to RM%d\n", rrc, Freturn_id); #endif switch (Freturn_id)@@ -6249,7 +6482,7 @@ LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(16) LBL(17) LBL(18) LBL(19) LBL(20) LBL(21) LBL(22) LBL(23) LBL(24) LBL(25) LBL(26) LBL(27) LBL(28) LBL(29) LBL(30) LBL(31) LBL(32)- LBL(33) LBL(34) LBL(35) LBL(36)+ LBL(33) LBL(34) LBL(35) LBL(36) LBL(37) #ifdef SUPPORT_WIDE_CHARS LBL(100) LBL(101)@@ -6346,6 +6579,7 @@ #endif /* SUPPORT_UNICODE */ PCRE2_SIZE frame_size;+PCRE2_SIZE heapframes_size; /* We need to have mb as a pointer to a match block, because the IS_NEWLINE macro is used below, and it expects NLBLOCK to be defined as a pointer. */@@ -6354,15 +6588,6 @@ match_block actual_match_block; match_block *mb = &actual_match_block; -/* Allocate an initial vector of backtracking frames on the stack. If this-proves to be too small, it is replaced by a larger one on the heap. To get a-vector of the size required that is aligned for pointers, allocate it as a-vector of pointers. */--PCRE2_SPTR stack_frames_vector[START_FRAMES_SIZE/sizeof(PCRE2_SPTR)]- PCRE2_KEEP_UNINITIALIZED;-mb->stack_frames = (heapframe *)stack_frames_vector;- /* Recognize NULL, length 0 as an empty string. */ if (subject == NULL && length == 0) subject = (PCRE2_SPTR)"";@@ -6545,6 +6770,7 @@ match_data, mcontext); if (rc != PCRE2_ERROR_JIT_BADOPTION) {+ match_data->subject_length = length; if (rc >= 0 && (options & PCRE2_COPY_MATCHED_SUBJECT) != 0) { length = CU2BYTES(length + was_zero_terminated);@@ -6713,7 +6939,7 @@ else mb->memctl = mcontext->memctl; anchored = ((re->overall_options | options) & PCRE2_ANCHORED) != 0;-firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;+firstline = !anchored && (re->overall_options & PCRE2_FIRSTLINE) != 0; startline = (re->flags & PCRE2_STARTLINE) != 0; bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)? true_end_subject : subject + mcontext->offset_limit;@@ -6736,6 +6962,7 @@ mb->start_subject = subject; mb->start_offset = start_offset; mb->end_subject = end_subject;+mb->true_end_subject = true_end_subject; mb->hasthen = (re->flags & PCRE2_HASTHEN) != 0; mb->allowemptypartial = (re->max_lookbehind > 0) || (re->flags & PCRE2_MATCH_EMPTY) != 0;@@ -6793,15 +7020,11 @@ vector at the end, whose size depends on the number of capturing parentheses in the pattern. It is not used at all if there are no capturing parentheses. - frame_size is the total size of each frame- mb->frame_vector_size is the total usable size of the vector (rounded down- to a whole number of frames)--The last of these is changed within the match() function if the frame vector-has to be expanded. We therefore put it into the match block so that it is-correct when calling match() more than once for non-anchored patterns.+ frame_size is the total size of each frame+ match_data->heapframes is the pointer to the frames vector+ match_data->heapframes_size is the allocated size of the vector -We must also pad frame_size for alignment to ensure subsequent frames are as+We must pad the frame_size for alignment to ensure subsequent frames are as aligned as heapframe. Whilst ovector is word-aligned due to being a PCRE2_SIZE array, that does not guarantee it is suitably aligned for pointers, as some architectures have pointers that are larger than a size_t. */@@ -6813,8 +7036,8 @@ /* Limits set in the pattern override the match context only if they are smaller. */ -mb->heap_limit = (mcontext->heap_limit < re->limit_heap)?- mcontext->heap_limit : re->limit_heap;+mb->heap_limit = ((mcontext->heap_limit < re->limit_heap)?+ mcontext->heap_limit : re->limit_heap); mb->match_limit = (mcontext->match_limit < re->limit_match)? mcontext->match_limit : re->limit_match;@@ -6823,35 +7046,40 @@ mcontext->depth_limit : re->limit_depth; /* If a pattern has very many capturing parentheses, the frame size may be very-large. Ensure that there are at least 10 available frames by getting an initial-vector on the heap if necessary, except when the heap limit prevents this. Get-fewer if possible. (The heap limit is in kibibytes.) */+large. Set the initial frame vector size to ensure that there are at least 10+available frames, but enforce a minimum of START_FRAMES_SIZE. If this is+greater than the heap limit, get as large a vector as possible. */ -if (frame_size <= START_FRAMES_SIZE/10)+heapframes_size = frame_size * 10;+if (heapframes_size < START_FRAMES_SIZE) heapframes_size = START_FRAMES_SIZE;+if (heapframes_size / 1024 > mb->heap_limit) {- mb->match_frames = mb->stack_frames; /* Initial frame vector on the stack */- mb->frame_vector_size = ((START_FRAMES_SIZE/frame_size) * frame_size);+ PCRE2_SIZE max_size = 1024 * mb->heap_limit;+ if (max_size < frame_size) return PCRE2_ERROR_HEAPLIMIT;+ heapframes_size = max_size; }-else++/* If an existing frame vector in the match_data block is large enough, we can+use it. Otherwise, free any pre-existing vector and get a new one. */++if (match_data->heapframes_size < heapframes_size) {- mb->frame_vector_size = frame_size * 10;- if ((mb->frame_vector_size / 1024) > mb->heap_limit)+ match_data->memctl.free(match_data->heapframes,+ match_data->memctl.memory_data);+ match_data->heapframes = match_data->memctl.malloc(heapframes_size,+ match_data->memctl.memory_data);+ if (match_data->heapframes == NULL) {- if (frame_size > mb->heap_limit * 1024) return PCRE2_ERROR_HEAPLIMIT;- mb->frame_vector_size = ((mb->heap_limit * 1024)/frame_size) * frame_size;+ match_data->heapframes_size = 0;+ return PCRE2_ERROR_NOMEMORY; }- mb->match_frames = mb->memctl.malloc(mb->frame_vector_size,- mb->memctl.memory_data);- if (mb->match_frames == NULL) return PCRE2_ERROR_NOMEMORY;+ match_data->heapframes_size = heapframes_size; } -mb->match_frames_top =- (heapframe *)((char *)mb->match_frames + mb->frame_vector_size);- /* Write to the ovector within the first frame to mark every capture unset and to avoid uninitialized memory read errors when it is copied to a new frame. */ -memset((char *)(mb->match_frames) + offsetof(heapframe, ovector), 0xff,+memset((char *)(match_data->heapframes) + offsetof(heapframe, ovector), 0xff, frame_size - offsetof(heapframe, ovector)); /* Pointers to the individual character tables */@@ -7279,9 +7507,17 @@ mb->end_offset_top = 0; mb->skip_arg_count = 0; - rc = match(start_match, mb->start_code, match_data->ovector,- match_data->oveccount, re->top_bracket, frame_size, mb);+#ifdef DEBUG_SHOW_OPS+ fprintf(stderr, "++ Calling match()\n");+#endif + rc = match(start_match, mb->start_code, re->top_bracket, frame_size,+ match_data, mb);++#ifdef DEBUG_SHOW_OPS+ fprintf(stderr, "++ match() returned %d\n\n", rc);+#endif+ if (mb->hitend && start_partial == NULL) { start_partial = mb->start_used_ptr;@@ -7429,6 +7665,7 @@ if (start_match >= true_end_subject) { rc = MATCH_NOMATCH; /* In case it was partial */+ match_partial = NULL; break; } @@ -7463,11 +7700,6 @@ } #endif /* SUPPORT_UNICODE */ -/* Release an enlarged frame vector that is on the heap. */--if (mb->match_frames != mb->stack_frames)- mb->memctl.free(mb->match_frames, mb->memctl.memory_data);- /* Fill in fields that are always returned in the match data. */ match_data->code = re;@@ -7483,6 +7715,7 @@ { match_data->rc = ((int)mb->end_offset_top >= 2 * match_data->oveccount)? 0 : (int)mb->end_offset_top/2 + 1;+ match_data->subject_length = length; match_data->startchar = start_match - subject; match_data->leftchar = mb->start_used_ptr - subject; match_data->rightchar = ((mb->last_used_ptr > mb->end_match_ptr)?@@ -7497,6 +7730,7 @@ match_data->flags |= PCRE2_MD_COPIED_SUBJECT; } else match_data->subject = subject;+ return match_data->rc; } @@ -7518,6 +7752,7 @@ else if (match_partial != NULL) { match_data->subject = subject;+ match_data->subject_length = length; match_data->ovector[0] = match_partial - subject; match_data->ovector[1] = end_subject - subject; match_data->startchar = match_partial - subject;@@ -7532,5 +7767,11 @@ return match_data->rc; }++/* These #undefs are here to enable unity builds with CMake. */++#undef NLBLOCK /* Block containing newline information */+#undef PSSTART /* Field containing processed string start */+#undef PSEND /* Field containing processed string end */ /* End of pcre2_match.c */
src/c/pcre2/src/pcre2_match_data.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2019 University of Cambridge+ New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -51,19 +51,23 @@ * Create a match data block given ovector size * *************************************************/ -/* A minimum of 1 is imposed on the number of ovector pairs. */+/* A minimum of 1 is imposed on the number of ovector pairs. A maximum is also+imposed because the oveccount field in a match data block is uintt6_t. */ PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION pcre2_match_data_create(uint32_t oveccount, pcre2_general_context *gcontext) { pcre2_match_data *yield; if (oveccount < 1) oveccount = 1;+if (oveccount > UINT16_MAX) oveccount = UINT16_MAX; yield = PRIV(memctl_malloc)( offsetof(pcre2_match_data, ovector) + 2*oveccount*sizeof(PCRE2_SIZE), (pcre2_memctl *)gcontext); if (yield == NULL) return NULL; yield->oveccount = oveccount; yield->flags = 0;+yield->heapframes = NULL;+yield->heapframes_size = 0; return yield; } @@ -95,6 +99,9 @@ { if (match_data != NULL) {+ if (match_data->heapframes != NULL)+ match_data->memctl.free(match_data->heapframes,+ match_data->memctl.memory_data); if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0) match_data->memctl.free((void *)match_data->subject, match_data->memctl.memory_data);@@ -161,6 +168,18 @@ { return offsetof(pcre2_match_data, ovector) + 2 * (match_data->oveccount) * sizeof(PCRE2_SIZE);+}++++/*************************************************+* Get heapframes size *+*************************************************/++PCRE2_EXP_DEFN PCRE2_SIZE PCRE2_CALL_CONVENTION+pcre2_get_match_data_heapframes_size(pcre2_match_data *match_data)+{+return match_data->heapframes_size; } /* End of pcre2_match_data.c */
src/c/pcre2/src/pcre2_printint.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2022 University of Cambridge+ New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -309,9 +309,8 @@ } else {- const char *not = (*code == OP_PROP)? "" : "not "; const uint32_t *p = PRIV(ucd_caseless_sets) + code[2];- fprintf (f, "%s%sclist", before, not);+ fprintf (f, "%s%sclist", before, (*code == OP_PROP)? "" : "not "); while (*p < NOTACHAR) fprintf(f, " %04x", *p++); fprintf(f, "%s", after); }@@ -429,12 +428,24 @@ case OP_SCRIPT_RUN: case OP_COND: case OP_SCOND:- case OP_REVERSE: if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); else fprintf(f, " "); fprintf(f, "%s", OP_names[*code]); break; + case OP_REVERSE:+ if (print_lengths) fprintf(f, "%3d ", GET2(code, 1));+ else fprintf(f, " ");+ fprintf(f, "%s", OP_names[*code]);+ break;++ case OP_VREVERSE:+ if (print_lengths) fprintf(f, "%3d %d ", GET2(code, 1),+ GET2(code, 1 + IMM2_SIZE));+ else fprintf(f, " ");+ fprintf(f, "%s", OP_names[*code]);+ break;+ case OP_CLOSE: fprintf(f, " %s %d", OP_names[*code], GET2(code, 1)); break;@@ -673,14 +684,14 @@ case OP_NCLASS: case OP_XCLASS: {- unsigned int min, max;- BOOL printmap;- BOOL invertmap = FALSE;- uint8_t *map;- uint8_t inverted_map[32];+ BOOL printmap, invertmap; fprintf(f, " ["); + /* Negative XCLASS has an inverted map whereas the original opcodes have+ already done the inversion. */++ invertmap = FALSE; if (*code == OP_XCLASS) { extra = GET(code, 1);@@ -693,7 +704,7 @@ } ccode++; }- else+ else /* CLASS or NCLASS */ { printmap = TRUE; ccode = code + 1;@@ -703,7 +714,9 @@ if (printmap) {- map = (uint8_t *)ccode;+ uint8_t inverted_map[32];+ uint8_t *map = (uint8_t *)ccode;+ if (invertmap) { /* Using 255 ^ instead of ~ avoids clang sanitize warning. */@@ -733,104 +746,109 @@ } ccode += 32 / sizeof(PCRE2_UCHAR); }+ } - /* For an XCLASS there is always some additional data */+ /* For an XCLASS there is always some additional data */ - if (*code == OP_XCLASS)+ if (*code == OP_XCLASS)+ {+ PCRE2_UCHAR ch;+ while ((ch = *ccode++) != XCL_END) {- PCRE2_UCHAR ch;- while ((ch = *ccode++) != XCL_END)+ const char *notch = "";++ switch(ch) {- BOOL not = FALSE;- const char *notch = "";+ case XCL_NOTPROP:+ notch = "^";+ /* Fall through */ - switch(ch)+ case XCL_PROP: {- case XCL_NOTPROP:- not = TRUE;- notch = "^";- /* Fall through */+ unsigned int ptype = *ccode++;+ unsigned int pvalue = *ccode++;+ const char *s; - case XCL_PROP:+ switch(ptype) {- unsigned int ptype = *ccode++;- unsigned int pvalue = *ccode++;- const char *s;+ case PT_PXGRAPH:+ fprintf(f, "[:%sgraph:]", notch);+ break; - switch(ptype)- {- case PT_PXGRAPH:- fprintf(f, "[:%sgraph:]", notch);- break;+ case PT_PXPRINT:+ fprintf(f, "[:%sprint:]", notch);+ break; - case PT_PXPRINT:- fprintf(f, "[:%sprint:]", notch);- break;+ case PT_PXPUNCT:+ fprintf(f, "[:%spunct:]", notch);+ break; - case PT_PXPUNCT:- fprintf(f, "[:%spunct:]", notch);- break;+ case PT_PXXDIGIT:+ fprintf(f, "[:%sxdigit:]", notch);+ break; - default:- s = get_ucpname(ptype, pvalue);- fprintf(f, "\\%c{%c%s}", (not? 'P':'p'), toupper(s[0]), s+1);- break;- }+ default:+ s = get_ucpname(ptype, pvalue);+ fprintf(f, "\\%c{%c%s}", ((notch[0] == '^')? 'P':'p'),+ toupper(s[0]), s+1);+ break; }- break;+ }+ break; - default:+ default:+ ccode += 1 + print_char(f, ccode, utf);+ if (ch == XCL_RANGE)+ {+ fprintf(f, "-"); ccode += 1 + print_char(f, ccode, utf);- if (ch == XCL_RANGE)- {- fprintf(f, "-");- ccode += 1 + print_char(f, ccode, utf);- }- break; }+ break; } }+ } - /* Indicate a non-UTF class which was created by negation */+ /* Indicate a non-UTF class which was created by negation */ - fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");+ fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : ""); - /* Handle repeats after a class or a back reference */+ /* Handle repeats after a class or a back reference */ - CLASS_REF_REPEAT:- switch(*ccode)- {- case OP_CRSTAR:- case OP_CRMINSTAR:- case OP_CRPLUS:- case OP_CRMINPLUS:- case OP_CRQUERY:- case OP_CRMINQUERY:- case OP_CRPOSSTAR:- case OP_CRPOSPLUS:- case OP_CRPOSQUERY:- fprintf(f, "%s", OP_names[*ccode]);- extra += OP_lengths[*ccode];- break;+ CLASS_REF_REPEAT:+ switch(*ccode)+ {+ unsigned int min, max; - case OP_CRRANGE:- case OP_CRMINRANGE:- case OP_CRPOSRANGE:- min = GET2(ccode,1);- max = GET2(ccode,1 + IMM2_SIZE);- if (max == 0) fprintf(f, "{%u,}", min);- else fprintf(f, "{%u,%u}", min, max);- if (*ccode == OP_CRMINRANGE) fprintf(f, "?");- else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+");- extra += OP_lengths[*ccode];- break;+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRPLUS:+ case OP_CRMINPLUS:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSSTAR:+ case OP_CRPOSPLUS:+ case OP_CRPOSQUERY:+ fprintf(f, "%s", OP_names[*ccode]);+ extra += OP_lengths[*ccode];+ break; - /* Do nothing if it's not a repeat; this code stops picky compilers- warning about the lack of a default code path. */+ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ min = GET2(ccode,1);+ max = GET2(ccode,1 + IMM2_SIZE);+ if (max == 0) fprintf(f, "{%u,}", min);+ else fprintf(f, "{%u,%u}", min, max);+ if (*ccode == OP_CRMINRANGE) fprintf(f, "?");+ else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+");+ extra += OP_lengths[*ccode];+ break; - default:- break;- }+ /* Do nothing if it's not a repeat; this code stops picky compilers+ warning about the lack of a default code path. */++ default:+ break; } break;
src/c/pcre2/src/pcre2_study.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2021 University of Cambridge+ New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -256,6 +256,7 @@ /* Skip over things that don't match chars */ case OP_REVERSE:+ case OP_VREVERSE: case OP_CREF: case OP_DNCREF: case OP_RREF:@@ -273,6 +274,8 @@ case OP_DOLLM: case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY:+ case OP_NOT_UCP_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY: cc += PRIV(OP_lengths)[*cc]; break; @@ -976,6 +979,7 @@ while (try_next) /* Loop for items in this branch */ { int rc;+ PCRE2_SPTR ncode; uint8_t *classmap = NULL; #ifdef SUPPORT_WIDE_CHARS PCRE2_UCHAR xclassflags;@@ -1054,6 +1058,7 @@ case OP_REF: case OP_REFI: case OP_REVERSE:+ case OP_VREVERSE: case OP_RREF: case OP_SCOND: case OP_SET_SOM:@@ -1101,14 +1106,101 @@ case OP_WORD_BOUNDARY: case OP_NOT_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:+ case OP_NOT_UCP_WORD_BOUNDARY: tcode++; break; - /* If we hit a bracket or a positive lookahead assertion, recurse to set- bits from within the subpattern. If it can't find anything, we have to- give up. If it finds some mandatory character(s), we are done for this- branch. Otherwise, carry on scanning after the subpattern. */+ /* For a positive lookahead assertion, inspect what immediately follows,+ ignoring intermediate assertions and callouts. If the next item is one+ that sets a mandatory character, skip this assertion. Otherwise, treat it+ the same as other bracket groups. */ + case OP_ASSERT:+ case OP_ASSERT_NA:+ ncode = tcode + GET(tcode, 1);+ while (*ncode == OP_ALT) ncode += GET(ncode, 1);+ ncode += 1 + LINK_SIZE;++ /* Skip irrelevant items */++ for (BOOL done = FALSE; !done;)+ {+ switch (*ncode)+ {+ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ ncode += GET(ncode, 1);+ while (*ncode == OP_ALT) ncode += GET(ncode, 1);+ ncode += 1 + LINK_SIZE;+ break;++ case OP_WORD_BOUNDARY:+ case OP_NOT_WORD_BOUNDARY:+ case OP_UCP_WORD_BOUNDARY:+ case OP_NOT_UCP_WORD_BOUNDARY:+ ncode++;+ break;++ case OP_CALLOUT:+ ncode += PRIV(OP_lengths)[OP_CALLOUT];+ break;++ case OP_CALLOUT_STR:+ ncode += GET(ncode, 1 + 2*LINK_SIZE);+ break;++ default:+ done = TRUE;+ break;+ }+ }++ /* Now check the next significant item. */++ switch(*ncode)+ {+ default:+ break;++ case OP_PROP:+ if (ncode[1] != PT_CLIST) break;+ /* Fall through */+ case OP_ANYNL:+ case OP_CHAR:+ case OP_CHARI:+ case OP_EXACT:+ case OP_EXACTI:+ case OP_HSPACE:+ case OP_MINPLUS:+ case OP_MINPLUSI:+ case OP_PLUS:+ case OP_PLUSI:+ case OP_POSPLUS:+ case OP_POSPLUSI:+ case OP_VSPACE:+ /* Note that these types will only be present in non-UCP mode. */+ case OP_DIGIT:+ case OP_NOT_DIGIT:+ case OP_WORDCHAR:+ case OP_NOT_WORDCHAR:+ case OP_WHITESPACE:+ case OP_NOT_WHITESPACE:+ tcode = ncode;+ continue; /* With the following significant opcode */+ }+ /* Fall through */++ /* For a group bracket or a positive assertion without an immediately+ following mandatory setting, recurse to set bits from within the+ subpattern. If it can't find anything, we have to give up. If it finds+ some mandatory character(s), we are done for this branch. Otherwise,+ carry on scanning after the subpattern. */+ case OP_BRA: case OP_SBRA: case OP_CBRA:@@ -1119,8 +1211,6 @@ case OP_SCBRAPOS: case OP_ONCE: case OP_SCRIPT_RUN:- case OP_ASSERT:- case OP_ASSERT_NA: rc = set_start_bits(re, tcode, utf, ucp, depthptr); if (rc == SSB_DONE) {
src/c/pcre2/src/pcre2_substitute.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2021 University of Cambridge+ New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -259,16 +259,16 @@ if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0) return PCRE2_ERROR_BADOPTION;- -/* Validate length and find the end of the replacement. A NULL replacement of ++/* Validate length and find the end of the replacement. A NULL replacement of zero length is interpreted as an empty string. */ -if (replacement == NULL) +if (replacement == NULL) { if (rlength != 0) return PCRE2_ERROR_NULL;- replacement = (PCRE2_SPTR)""; - } - + replacement = (PCRE2_SPTR)"";+ }+ if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement); repend = replacement + rlength; @@ -282,8 +282,9 @@ match data block. We create an internal match_data block in two cases: (a) an external one is not supplied (and we are not starting from an existing match); (b) an existing match is to be used for the first substitution. In the latter-case, we copy the existing match into the internal block. This ensures that no-changes are made to the existing match data block. */+case, we copy the existing match into the internal block, except for any cached+heap frame size and pointer. This ensures that no changes are made to the+external match data block. */ if (match_data == NULL) {@@ -309,6 +310,8 @@ if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY; memcpy(internal_match_data, match_data, offsetof(pcre2_match_data, ovector) + 2*pairs*sizeof(PCRE2_SIZE));+ internal_match_data->heapframes = NULL;+ internal_match_data->heapframes_size = 0; match_data = internal_match_data; } @@ -328,9 +331,9 @@ if (subject == NULL) {- if (length != 0) return PCRE2_ERROR_NULL; + if (length != 0) return PCRE2_ERROR_NULL; subject = (PCRE2_SPTR)"";- } + } /* Find length of zero-terminated subject */
src/c/pcre2/src/pcre2_substring.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2018 University of Cambridge+ New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -309,6 +309,7 @@ PCRE2_ERROR_NOSUBSTRING: no such substring PCRE2_ERROR_UNAVAILABLE: ovector is too small PCRE2_ERROR_UNSET: substring is not set+ PCRE2_ERROR_INVALIDOFFSET: internal error, should not occur */ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION@@ -341,6 +342,8 @@ left = match_data->ovector[stringnumber*2]; right = match_data->ovector[stringnumber*2+1];+if (left > match_data->subject_length || right > match_data->subject_length)+ return PCRE2_ERROR_INVALIDOFFSET; if (sizeptr != NULL) *sizeptr = (left > right)? 0 : right - left; return 0; }@@ -442,7 +445,7 @@ */ PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION-pcre2_substring_list_free(PCRE2_SPTR *list)+pcre2_substring_list_free(PCRE2_UCHAR **list) { if (list != NULL) {
src/c/pcre2/src/pcre2_tables.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2021 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -171,9 +171,9 @@ 6. Do not break after Prepend characters. 7. Do not break within emoji modifier sequences or emoji zwj sequences. That- is, do not break between characters with the Extended_Pictographic property.- Extend and ZWJ characters are allowed between the characters; this cannot be- represented in this table, the code has to deal with it.+ is, do not break between characters with the Extended_Pictographic property+ if a ZWJ intervenes. Extend characters are allowed between the characters;+ this cannot be represented in this table, the code has to deal with it. 8. Do not break within emoji flag sequences. That is, do not break between regional indicator (RI) symbols if there are an odd number of RI characters@@ -203,8 +203,8 @@ ESZ|(1u<<ucp_gbT), /* 10 LVT */ (1u<<ucp_gbRegional_Indicator), /* 11 Regional Indicator */ ESZ, /* 12 Other */- ESZ, /* 13 ZWJ */- ESZ|(1u<<ucp_gbExtended_Pictographic) /* 14 Extended Pictographic */+ ESZ|(1u<<ucp_gbExtended_Pictographic), /* 13 ZWJ */+ ESZ /* 14 Extended Pictographic */ }; #undef ESZ
src/c/pcre2/src/pcre2_ucd.c view
@@ -68,5322 +68,5386 @@ compilers barf at that. Instead, just supply some small dummy tables. */ #ifndef SUPPORT_UNICODE-const ucd_record PRIV(ucd_records)[] = {{0,0,0,0,0,0,0 }};-const uint16_t PRIV(ucd_stage1)[] = {0};-const uint16_t PRIV(ucd_stage2)[] = {0};-const uint32_t PRIV(ucd_caseless_sets)[] = {0};-#else--/* Total size: 111116 bytes, block size: 128. */--const char *PRIV(unicode_version) = "14.0.0";--/* When recompiling tables with a new Unicode version, please check the types-in this structure definition with those in pcre2_internal.h (the actual field-names will be different).--typedef struct {-uint8_t property_0;-uint8_t property_1;-uint8_t property_2;-uint8_t property_3;-int32_t property_4;-uint16_t property_5;-uint16_t property_6;-} ucd_record;-*/--/* 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. */--#if PCRE2_CODE_UNIT_WIDTH == 32-const ucd_record PRIV(dummy_ucd_record)[] = {{- ucp_Unknown, /* script */- ucp_Cn, /* type unassigned */- ucp_gbOther, /* grapheme break property */- 0, /* case set */- 0, /* other case */- 0 | (ucp_bidiL << UCD_BIDICLASS_SHIFT), /* script extension and bidi class */- 0, /* bool properties offset */- }};-#endif--/* This table contains lists of characters that are caseless sets of-more than one character. Each list is terminated by NOTACHAR. */--const uint32_t PRIV(ucd_caseless_sets)[] = {- NOTACHAR,- 0x0053, 0x0073, 0x017f, NOTACHAR,- 0x01c4, 0x01c5, 0x01c6, NOTACHAR,- 0x01c7, 0x01c8, 0x01c9, NOTACHAR,- 0x01ca, 0x01cb, 0x01cc, NOTACHAR,- 0x01f1, 0x01f2, 0x01f3, NOTACHAR,- 0x0345, 0x0399, 0x03b9, 0x1fbe, NOTACHAR,- 0x00b5, 0x039c, 0x03bc, NOTACHAR,- 0x03a3, 0x03c2, 0x03c3, NOTACHAR,- 0x0392, 0x03b2, 0x03d0, NOTACHAR,- 0x0398, 0x03b8, 0x03d1, 0x03f4, NOTACHAR,- 0x03a6, 0x03c6, 0x03d5, NOTACHAR,- 0x03a0, 0x03c0, 0x03d6, NOTACHAR,- 0x039a, 0x03ba, 0x03f0, NOTACHAR,- 0x03a1, 0x03c1, 0x03f1, NOTACHAR,- 0x0395, 0x03b5, 0x03f5, NOTACHAR,- 0x0412, 0x0432, 0x1c80, NOTACHAR,- 0x0414, 0x0434, 0x1c81, NOTACHAR,- 0x041e, 0x043e, 0x1c82, NOTACHAR,- 0x0421, 0x0441, 0x1c83, NOTACHAR,- 0x0422, 0x0442, 0x1c84, 0x1c85, NOTACHAR,- 0x042a, 0x044a, 0x1c86, NOTACHAR,- 0x0462, 0x0463, 0x1c87, NOTACHAR,- 0x1e60, 0x1e61, 0x1e9b, NOTACHAR,- 0x03a9, 0x03c9, 0x2126, NOTACHAR,- 0x004b, 0x006b, 0x212a, NOTACHAR,- 0x00c5, 0x00e5, 0x212b, NOTACHAR,- 0x1c88, 0xa64a, 0xa64b, NOTACHAR,-};--/* When #included in pcre2test, we don't need the table of digit sets, nor the-the large main UCD tables. */--#ifndef PCRE2_PCRE2TEST--/* This table lists the code points for the '9' characters in each set of-decimal digits. It is used to ensure that all the digits in a script run come-from the same set. */--const uint32_t PRIV(ucd_digit_sets)[] = {- 66, /* Number of subsequent values */- 0x00039, 0x00669, 0x006f9, 0x007c9, 0x0096f, 0x009ef, 0x00a6f, 0x00aef,- 0x00b6f, 0x00bef, 0x00c6f, 0x00cef, 0x00d6f, 0x00def, 0x00e59, 0x00ed9,- 0x00f29, 0x01049, 0x01099, 0x017e9, 0x01819, 0x0194f, 0x019d9, 0x01a89,- 0x01a99, 0x01b59, 0x01bb9, 0x01c49, 0x01c59, 0x0a629, 0x0a8d9, 0x0a909,- 0x0a9d9, 0x0a9f9, 0x0aa59, 0x0abf9, 0x0ff19, 0x104a9, 0x10d39, 0x1106f,- 0x110f9, 0x1113f, 0x111d9, 0x112f9, 0x11459, 0x114d9, 0x11659, 0x116c9,- 0x11739, 0x118e9, 0x11959, 0x11c59, 0x11d59, 0x11da9, 0x16a69, 0x16ac9,- 0x16b59, 0x1d7d7, 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e149, 0x1e2f9,- 0x1e959, 0x1fbf9,-};--/* This vector is a list of script bitsets for the Script Extension property.-The number of 32-bit words in each bitset is #defined in pcre2_ucp.h as-ucd_script_sets_item_size. */--const uint32_t PRIV(ucd_script_sets)[] = {- 0x00000000u, 0x00000000u, 0x00000000u,- 0x00000080u, 0x00000000u, 0x00000000u,- 0x00000040u, 0x00000000u, 0x00000000u,- 0x00000000u, 0x00004000u, 0x00000000u,- 0x00000002u, 0x00000000u, 0x00000000u,- 0x00800000u, 0x00000000u, 0x00000000u,- 0x00000001u, 0x00000000u, 0x00000000u,- 0x00000000u, 0x00000000u, 0x00000001u,- 0x00000010u, 0x00000000u, 0x00000000u,- 0x00000008u, 0x00000004u, 0x00000000u,- 0x00000008u, 0x40000000u, 0x00000000u,- 0x00000008u, 0x00000040u, 0x00000000u,- 0x00000018u, 0x00000000u, 0x00000000u,- 0x00000028u, 0x00000000u, 0x00000000u,- 0x000000c0u, 0x00000000u, 0x00000000u,- 0x00c00000u, 0x00000000u, 0x00000000u,- 0x00000000u, 0x00000102u, 0x00000000u,- 0x80000000u, 0x00000001u, 0x00000000u,- 0x00000004u, 0x00000008u, 0x00000000u,- 0x00000005u, 0x00000000u, 0x00000000u,- 0x00000004u, 0x00200000u, 0x00000000u,- 0x00000014u, 0x00000000u, 0x00000000u,- 0x00000040u, 0x00008000u, 0x00000000u,- 0x00000040u, 0x00000000u, 0x00000001u,- 0x00000040u, 0x00001000u, 0x00000000u,- 0x00000840u, 0x00000000u, 0x00000000u,- 0x00020001u, 0x00000000u, 0x00000000u,- 0x00000800u, 0x00008000u, 0x00000000u,- 0x00000200u, 0x00010000u, 0x00000000u,- 0x00000100u, 0x02000000u, 0x00000000u,- 0x00800001u, 0x00000000u, 0x00000000u,- 0x00300000u, 0x00000000u, 0x00000000u,- 0x00002000u, 0x00000000u, 0x00000001u,- 0x00080001u, 0x00000000u, 0x00000000u,- 0x00000000u, 0x00080000u, 0x00000008u,- 0x00080000u, 0x00000020u, 0x00000000u,- 0x00000038u, 0x00000000u, 0x00000000u,- 0x00000028u, 0x00000000u, 0x00000002u,- 0x00000080u, 0x00000810u, 0x00000000u,- 0x40010000u, 0x00000800u, 0x00000000u,- 0x80000000u, 0x00000001u, 0x00000004u,- 0x80000000u, 0x00020001u, 0x00000000u,- 0x00002040u, 0x00008000u, 0x00000000u,- 0x00000041u, 0x00008000u, 0x00000000u,- 0x00b00000u, 0x00000000u, 0x00000000u,- 0x00010001u, 0x00000080u, 0x00000000u,- 0x000020c0u, 0x00008000u, 0x00000000u,- 0x1e000000u, 0x00000000u, 0x00000000u,- 0x00000040u, 0x10040200u, 0x00000000u,- 0x00f40000u, 0x00000000u, 0x00000000u,- 0x00000038u, 0x40000040u, 0x00000002u,- 0x01f40000u, 0x00000000u, 0x00000000u,- 0x00007c40u, 0x00000000u, 0x00000000u,- 0x00000038u, 0x44000040u, 0x00000002u,- 0x000034c0u, 0x01008000u, 0x00000001u,- 0x00000018u, 0xc4480400u, 0x00000008u,- 0x00000340u, 0x11952200u, 0x00000000u,- 0x00007fc1u, 0x01008000u, 0x00000000u,- 0x00007fc1u, 0x01009000u, 0x00000000u,- 0x00002340u, 0x11952200u, 0x00000001u,- 0x00006340u, 0x11952200u, 0x00000001u,- 0x0000ffc0u, 0x3984a010u, 0x00000001u,- 0x2000ffc0u, 0x3984a010u, 0x00000001u,-};--/* This vector is a list of bitsets for Boolean properties. The number of-32_bit words in each bitset is #defined as ucd_boolprop_sets_item_size in-pcre2_ucp.h. */--const uint32_t PRIV(ucd_boolprop_sets)[] = {- 0x00000000u, 0x00000000u,- 0x00000001u, 0x00000000u,- 0x00000001u, 0x00020040u,- 0x00800001u, 0x00020040u,- 0x00800001u, 0x00002820u,- 0x00800001u, 0x00000120u,- 0x00830001u, 0x00000020u,- 0x00800001u, 0x00000020u,- 0x00800021u, 0x00000120u,- 0x00800011u, 0x00000020u,- 0x00800001u, 0x00000028u,- 0x00800001u, 0x00002020u,- 0x00801001u, 0x00000020u,- 0x00800021u, 0x00002820u,- 0x24830003u, 0x00040000u,- 0x00800021u, 0x00002020u,- 0x00800011u, 0x00000028u,- 0x648003c7u, 0x000c8000u,- 0x608003c5u, 0x000c8000u,- 0x00808021u, 0x00000028u,- 0x20800001u, 0x00040000u,- 0x00808021u, 0x00000020u,- 0x64800d47u, 0x000c0004u,- 0x60800d45u, 0x000c0004u,- 0x60800d45u, 0x000c1004u,- 0x00000000u, 0x00020040u,- 0x00800000u, 0x00020000u,- 0x00800000u, 0x00000020u,- 0x00808020u, 0x00000000u,- 0x00a10000u, 0x00000020u,- 0x60800044u, 0x000c0004u,- 0x00800010u, 0x00000120u,- 0x00800000u, 0x00000028u,- 0x00002020u, 0x00000000u,- 0x00800000u, 0x00000000u,- 0x60800dc4u, 0x000c0004u,- 0x20c08020u, 0x00040000u,- 0x608003c4u, 0x000c8000u,- 0x60800d44u, 0x000c0004u,- 0x60800d44u, 0x000c1004u,- 0x60804dc4u, 0x000c0004u,- 0x60800004u, 0x000c0000u,- 0x608007c4u, 0x000c8000u,- 0x60800bc4u, 0x000c0000u,- 0x60808064u, 0x000c0004u,- 0x60808064u, 0x000c1004u,- 0x60808024u, 0x000c0000u,- 0x60c08024u, 0x000c0000u,- 0x21008020u, 0x00040000u,- 0x21008de4u, 0x00040004u,- 0x21002020u, 0x00040000u,- 0x21000020u, 0x00040000u,- 0x60808064u, 0x00000004u,- 0x00800000u, 0x00002000u,- 0x20800020u, 0x00042000u,- 0x60800dc4u, 0x000c000cu,- 0x60800044u, 0x000c8008u,- 0x60800044u, 0x000c8000u,- 0x608003c4u, 0x000c8008u,- 0x00800000u, 0x00000008u,- 0x01000020u, 0x00000000u,- 0x00800020u, 0x00000000u,- 0x00800000u, 0x00002800u,- 0x00801000u, 0x00000000u,- 0x21008024u, 0x00040000u,- 0x21000024u, 0x00040000u,- 0x00000020u, 0x00000080u,- 0x00002028u, 0x00000000u,- 0x60c00024u, 0x000c0000u,- 0x20800000u, 0x00040000u,- 0x60804004u, 0x000c0000u,- 0x60800024u, 0x000c0000u,- 0x20800004u, 0x00040000u,- 0x23008020u, 0x00040000u,- 0x21000004u, 0x00040000u,- 0x21408020u, 0x00040000u,- 0x60800004u, 0x00040000u,- 0x23000024u, 0x00040000u,- 0x60800004u, 0x000c0002u,- 0x00800010u, 0x00000000u,- 0x20808000u, 0x00040000u,- 0x21004024u, 0x00040000u,- 0x20808004u, 0x00040000u,- 0x60800944u, 0x000c0004u,- 0x60802004u, 0x000c0000u,- 0x60800344u, 0x000c8000u,- 0x22808000u, 0x00040000u,- 0x22800000u, 0x00040000u,- 0x00c00000u, 0x00000000u,- 0x21002020u, 0x00050000u,- 0x61000024u, 0x000c0000u,- 0x23000020u, 0x00040000u,- 0x01008020u, 0x00000000u,- 0x21408024u, 0x00040000u,- 0x00808000u, 0x00000000u,- 0x60800064u, 0x000c0004u,- 0x60800044u, 0x000c1004u,- 0x60800064u, 0x000c1004u,- 0x01002020u, 0x00000001u,- 0x00022020u, 0x00000001u,- 0x00002028u, 0x00000040u,- 0x00801000u, 0x00000020u,- 0x00800020u, 0x00000120u,- 0x00800000u, 0x00000120u,- 0x00800020u, 0x00000020u,- 0x00a10000u, 0x00002820u,- 0x00800000u, 0x00002820u,- 0x20800000u, 0x00040008u,- 0x00800010u, 0x00000020u,- 0x00002020u, 0x00000008u,- 0x00002000u, 0x00000000u,- 0x00006020u, 0x00000000u,- 0x00801000u, 0x00000008u,- 0x00800010u, 0x00000008u,- 0x21000020u, 0x00040008u,- 0x01020020u, 0x00000000u,- 0x60800044u, 0x000c000cu,- 0x60800000u, 0x000c0008u,- 0x00a10000u, 0x00000000u,- 0x60800000u, 0x000c0000u,- 0x60800004u, 0x000c0008u,- 0x60a10044u, 0x000c0004u,- 0x60800044u, 0x000c100cu,- 0x00a10000u, 0x00000028u,- 0x00800010u, 0x00000028u,- 0x00801000u, 0x00000028u,- 0x00b10000u, 0x00000020u,- 0x00804010u, 0x00000020u,- 0x00a00000u, 0x00000020u,- 0x00000000u, 0x00000020u,- 0x008003c4u, 0x00008000u,- 0x00a103c4u, 0x00008000u,- 0x00800d44u, 0x00000004u,- 0x00b10000u, 0x00000028u,- 0x00a00000u, 0x00000028u,- 0x00a90000u, 0x00000020u,- 0x00b90000u, 0x00000020u,- 0x00808024u, 0x00000020u,- 0x00800000u, 0x00002020u,- 0x00800000u, 0x00000200u,- 0x08800000u, 0x00000000u,- 0x10800000u, 0x00000000u,- 0xe0800004u, 0x000c0000u,- 0x21008000u, 0x00040000u,- 0x00a11000u, 0x00000020u,- 0x60808020u, 0x00000000u,- 0xe0800004u, 0x000c4000u,- 0x60808004u, 0x000c0000u,- 0x60800004u, 0x00000000u,- 0x00000000u, 0x00000010u,- 0x21022020u, 0x00050000u,- 0x00800000u, 0x00000100u,- 0x00800020u, 0x00002800u,- 0x00800020u, 0x00002000u,- 0x00800020u, 0x00000100u,- 0x24800000u, 0x00040000u,- 0x648003c4u, 0x000c8000u,- 0x00808020u, 0x00000008u,- 0x64800d44u, 0x000c0004u,- 0x00800010u, 0x00000100u,- 0x61008024u, 0x00040000u,- 0x00000020u, 0x00000000u,- 0x60c00004u, 0x000c0000u,- 0x21400020u, 0x00040000u,- 0xa1000020u, 0x00040000u,- 0x21000000u, 0x00040000u,- 0x00a00000u, 0x00000000u,- 0x00b10000u, 0x00000000u,- 0x00200000u, 0x00000000u,- 0x00800044u, 0x00008000u,- 0x00a10044u, 0x00008000u,- 0x00930000u, 0x00000400u,- 0x00b90000u, 0x00000000u,- 0x00a90000u, 0x00000000u,- 0x00970020u, 0x00000000u,- 0x00b30000u, 0x00000000u,- 0x01022020u, 0x00000000u,-};--/* These are the main two-stage UCD tables. The fields in each record are:-script (8 bits), character type (8 bits), grapheme break property (8 bits),-offset to multichar other cases or zero (8 bits), offset to other case or zero-(32 bits, signed), bidi class (5 bits) and script extension (11 bits) packed-into a 16-bit field, and offset in binary properties table (16 bits). */--const ucd_record PRIV(ucd_records)[] = { /* 16908 bytes, record size 12 */- { 69, 0, 2, 0, 0, 6144, 2, }, /* 0 */- { 69, 0, 2, 0, 0, 43008, 4, }, /* 1 */- { 69, 0, 1, 0, 0, 4096, 4, }, /* 2 */- { 69, 0, 2, 0, 0, 45056, 4, }, /* 3 */- { 69, 0, 0, 0, 0, 4096, 4, }, /* 4 */- { 69, 0, 2, 0, 0, 4096, 2, }, /* 5 */- { 69, 0, 2, 0, 0, 43008, 2, }, /* 6 */- { 69, 29, 12, 0, 0, 45056, 6, }, /* 7 */- { 69, 21, 12, 0, 0, 28672, 8, }, /* 8 */- { 69, 21, 12, 0, 0, 28672, 10, }, /* 9 */- { 69, 21, 12, 0, 0, 14336, 12, }, /* 10 */- { 69, 23, 12, 0, 0, 14336, 14, }, /* 11 */- { 69, 21, 12, 0, 0, 14336, 14, }, /* 12 */- { 69, 21, 12, 0, 0, 28672, 14, }, /* 13 */- { 69, 21, 12, 0, 0, 28672, 16, }, /* 14 */- { 69, 22, 12, 0, 0, 28672, 18, }, /* 15 */- { 69, 18, 12, 0, 0, 28672, 18, }, /* 16 */- { 69, 21, 12, 0, 0, 28672, 12, }, /* 17 */- { 69, 25, 12, 0, 0, 12288, 20, }, /* 18 */- { 69, 21, 12, 0, 0, 8192, 22, }, /* 19 */- { 69, 17, 12, 0, 0, 12288, 24, }, /* 20 */- { 69, 21, 12, 0, 0, 8192, 26, }, /* 21 */- { 69, 21, 12, 0, 0, 8192, 14, }, /* 22 */- { 69, 13, 12, 0, 0, 10240, 28, }, /* 23 */- { 69, 21, 12, 0, 0, 8192, 30, }, /* 24 */- { 69, 21, 12, 0, 0, 28672, 22, }, /* 25 */- { 69, 25, 12, 0, 0, 28672, 32, }, /* 26 */- { 69, 25, 12, 0, 0, 28672, 20, }, /* 27 */- { 0, 9, 12, 0, 32, 18432, 34, }, /* 28 */- { 0, 9, 12, 0, 32, 18432, 36, }, /* 29 */- { 0, 9, 12, 100, 32, 18432, 36, }, /* 30 */- { 0, 9, 12, 1, 32, 18432, 36, }, /* 31 */- { 69, 24, 12, 0, 0, 28672, 38, }, /* 32 */- { 69, 16, 12, 0, 0, 28672, 40, }, /* 33 */- { 69, 24, 12, 0, 0, 28672, 42, }, /* 34 */- { 0, 5, 12, 0, -32, 18432, 44, }, /* 35 */- { 0, 5, 12, 0, -32, 18432, 46, }, /* 36 */- { 0, 5, 12, 0, -32, 18432, 48, }, /* 37 */- { 0, 5, 12, 100, -32, 18432, 46, }, /* 38 */- { 0, 5, 12, 1, -32, 18432, 46, }, /* 39 */- { 69, 0, 2, 0, 0, 6144, 0, }, /* 40 */- { 69, 0, 2, 0, 0, 4096, 50, }, /* 41 */- { 69, 29, 12, 0, 0, 8192, 52, }, /* 42 */- { 69, 21, 12, 0, 0, 28672, 54, }, /* 43 */- { 69, 23, 12, 0, 0, 14336, 54, }, /* 44 */- { 69, 26, 12, 0, 0, 28672, 54, }, /* 45 */- { 69, 24, 12, 0, 0, 28672, 56, }, /* 46 */- { 69, 26, 14, 0, 0, 28672, 58, }, /* 47 */- { 0, 7, 12, 0, 0, 18432, 60, }, /* 48 */- { 69, 20, 12, 0, 0, 28672, 62, }, /* 49 */- { 69, 25, 12, 0, 0, 28672, 64, }, /* 50 */- { 69, 1, 2, 0, 0, 6144, 66, }, /* 51 */- { 69, 26, 12, 0, 0, 14336, 54, }, /* 52 */- { 69, 25, 12, 0, 0, 14336, 64, }, /* 53 */- { 69, 15, 12, 0, 0, 10240, 68, }, /* 54 */- { 69, 5, 12, 26, 775, 18432, 70, }, /* 55 */- { 69, 21, 12, 0, 0, 28672, 72, }, /* 56 */- { 69, 19, 12, 0, 0, 28672, 62, }, /* 57 */- { 69, 15, 12, 0, 0, 28672, 68, }, /* 58 */- { 0, 9, 12, 0, 32, 18432, 74, }, /* 59 */- { 0, 9, 12, 104, 32, 18432, 74, }, /* 60 */- { 0, 5, 12, 0, 7615, 18432, 70, }, /* 61 */- { 0, 5, 12, 0, -32, 18432, 76, }, /* 62 */- { 0, 5, 12, 104, -32, 18432, 76, }, /* 63 */- { 0, 5, 12, 0, 121, 18432, 76, }, /* 64 */- { 0, 9, 12, 0, 1, 18432, 74, }, /* 65 */- { 0, 5, 12, 0, -1, 18432, 76, }, /* 66 */- { 0, 5, 12, 0, -1, 18432, 78, }, /* 67 */- { 0, 9, 12, 0, 0, 18432, 74, }, /* 68 */- { 0, 5, 12, 0, 0, 18432, 76, }, /* 69 */- { 0, 5, 12, 0, 0, 18432, 60, }, /* 70 */- { 0, 5, 12, 0, 0, 18432, 80, }, /* 71 */- { 0, 9, 12, 0, -121, 18432, 74, }, /* 72 */- { 0, 5, 12, 1, -268, 18432, 70, }, /* 73 */- { 0, 5, 12, 0, 195, 18432, 76, }, /* 74 */- { 0, 9, 12, 0, 210, 18432, 74, }, /* 75 */- { 0, 9, 12, 0, 206, 18432, 74, }, /* 76 */- { 0, 9, 12, 0, 205, 18432, 74, }, /* 77 */- { 0, 9, 12, 0, 79, 18432, 74, }, /* 78 */- { 0, 9, 12, 0, 202, 18432, 74, }, /* 79 */- { 0, 9, 12, 0, 203, 18432, 74, }, /* 80 */- { 0, 9, 12, 0, 207, 18432, 74, }, /* 81 */- { 0, 5, 12, 0, 97, 18432, 76, }, /* 82 */- { 0, 9, 12, 0, 211, 18432, 74, }, /* 83 */- { 0, 9, 12, 0, 209, 18432, 74, }, /* 84 */- { 0, 5, 12, 0, 163, 18432, 76, }, /* 85 */- { 0, 9, 12, 0, 213, 18432, 74, }, /* 86 */- { 0, 5, 12, 0, 130, 18432, 76, }, /* 87 */- { 0, 9, 12, 0, 214, 18432, 74, }, /* 88 */- { 0, 9, 12, 0, 218, 18432, 74, }, /* 89 */- { 0, 9, 12, 0, 217, 18432, 74, }, /* 90 */- { 0, 9, 12, 0, 219, 18432, 74, }, /* 91 */- { 0, 7, 12, 0, 0, 18432, 82, }, /* 92 */- { 0, 5, 12, 0, 56, 18432, 76, }, /* 93 */- { 0, 9, 12, 5, 2, 18432, 84, }, /* 94 */- { 0, 8, 12, 5, 1, 18432, 86, }, /* 95 */- { 0, 5, 12, 5, -2, 18432, 76, }, /* 96 */- { 0, 9, 12, 9, 2, 18432, 84, }, /* 97 */- { 0, 8, 12, 9, 1, 18432, 86, }, /* 98 */- { 0, 5, 12, 9, -2, 18432, 76, }, /* 99 */- { 0, 9, 12, 13, 2, 18432, 84, }, /* 100 */- { 0, 8, 12, 13, 1, 18432, 86, }, /* 101 */- { 0, 5, 12, 13, -2, 18432, 76, }, /* 102 */- { 0, 5, 12, 0, -79, 18432, 76, }, /* 103 */- { 0, 9, 12, 17, 2, 18432, 84, }, /* 104 */- { 0, 8, 12, 17, 1, 18432, 86, }, /* 105 */- { 0, 5, 12, 17, -2, 18432, 76, }, /* 106 */- { 0, 9, 12, 0, -97, 18432, 74, }, /* 107 */- { 0, 9, 12, 0, -56, 18432, 74, }, /* 108 */- { 0, 9, 12, 0, -130, 18432, 74, }, /* 109 */- { 0, 9, 12, 0, 10795, 18432, 74, }, /* 110 */- { 0, 9, 12, 0, -163, 18432, 74, }, /* 111 */- { 0, 9, 12, 0, 10792, 18432, 74, }, /* 112 */- { 0, 5, 12, 0, 10815, 18432, 76, }, /* 113 */- { 0, 9, 12, 0, -195, 18432, 74, }, /* 114 */- { 0, 9, 12, 0, 69, 18432, 74, }, /* 115 */- { 0, 9, 12, 0, 71, 18432, 74, }, /* 116 */- { 0, 5, 12, 0, 10783, 18432, 76, }, /* 117 */- { 0, 5, 12, 0, 10780, 18432, 76, }, /* 118 */- { 0, 5, 12, 0, 10782, 18432, 76, }, /* 119 */- { 0, 5, 12, 0, -210, 18432, 76, }, /* 120 */- { 0, 5, 12, 0, -206, 18432, 76, }, /* 121 */- { 0, 5, 12, 0, -205, 18432, 76, }, /* 122 */- { 0, 5, 12, 0, -202, 18432, 76, }, /* 123 */- { 0, 5, 12, 0, -203, 18432, 76, }, /* 124 */- { 0, 5, 12, 0, 42319, 18432, 76, }, /* 125 */- { 0, 5, 12, 0, 42315, 18432, 76, }, /* 126 */- { 0, 5, 12, 0, -207, 18432, 76, }, /* 127 */- { 0, 5, 12, 0, 42280, 18432, 76, }, /* 128 */- { 0, 5, 12, 0, 42308, 18432, 76, }, /* 129 */- { 0, 5, 12, 0, -209, 18432, 78, }, /* 130 */- { 0, 5, 12, 0, -211, 18432, 76, }, /* 131 */- { 0, 5, 12, 0, 10743, 18432, 76, }, /* 132 */- { 0, 5, 12, 0, 42305, 18432, 76, }, /* 133 */- { 0, 5, 12, 0, 10749, 18432, 76, }, /* 134 */- { 0, 5, 12, 0, -213, 18432, 76, }, /* 135 */- { 0, 5, 12, 0, -214, 18432, 76, }, /* 136 */- { 0, 5, 12, 0, 10727, 18432, 76, }, /* 137 */- { 0, 5, 12, 0, -218, 18432, 76, }, /* 138 */- { 0, 5, 12, 0, 42307, 18432, 76, }, /* 139 */- { 0, 5, 12, 0, 42282, 18432, 76, }, /* 140 */- { 0, 5, 12, 0, -69, 18432, 76, }, /* 141 */- { 0, 5, 12, 0, -217, 18432, 76, }, /* 142 */- { 0, 5, 12, 0, -71, 18432, 76, }, /* 143 */- { 0, 5, 12, 0, -219, 18432, 76, }, /* 144 */- { 0, 5, 12, 0, 42261, 18432, 78, }, /* 145 */- { 0, 5, 12, 0, 42258, 18432, 76, }, /* 146 */- { 0, 6, 12, 0, 0, 18432, 88, }, /* 147 */- { 0, 6, 12, 0, 0, 18432, 90, }, /* 148 */- { 69, 6, 12, 0, 0, 28672, 92, }, /* 149 */- { 69, 6, 12, 0, 0, 18432, 92, }, /* 150 */- { 69, 6, 12, 0, 0, 18432, 88, }, /* 151 */- { 69, 6, 12, 0, 0, 18432, 94, }, /* 152 */- { 22, 24, 12, 0, 0, 28672, 56, }, /* 153 */- { 84, 12, 3, 0, 0, 26624, 96, }, /* 154 */- { 84, 12, 3, 0, 0, 26636, 96, }, /* 155 */- { 84, 12, 3, 21, 116, 26636, 98, }, /* 156 */- { 84, 12, 3, 0, 0, 26624, 100, }, /* 157 */- { 84, 12, 3, 0, 0, 26624, 102, }, /* 158 */- { 84, 12, 3, 0, 0, 26642, 102, }, /* 159 */- { 1, 9, 12, 0, 1, 18432, 74, }, /* 160 */- { 1, 5, 12, 0, -1, 18432, 76, }, /* 161 */- { 1, 24, 12, 0, 0, 28672, 56, }, /* 162 */- { 68, 2, 12, 0, 0, 18432, 0, }, /* 163 */- { 1, 6, 12, 0, 0, 18432, 104, }, /* 164 */- { 1, 5, 12, 0, 130, 18432, 76, }, /* 165 */- { 69, 21, 12, 0, 0, 28672, 106, }, /* 166 */- { 1, 9, 12, 0, 116, 18432, 74, }, /* 167 */- { 1, 9, 12, 0, 38, 18432, 74, }, /* 168 */- { 69, 21, 12, 0, 0, 28672, 108, }, /* 169 */- { 1, 9, 12, 0, 37, 18432, 74, }, /* 170 */- { 1, 9, 12, 0, 64, 18432, 74, }, /* 171 */- { 1, 9, 12, 0, 63, 18432, 74, }, /* 172 */- { 1, 5, 12, 0, 0, 18432, 76, }, /* 173 */- { 1, 9, 12, 0, 32, 18432, 74, }, /* 174 */- { 1, 9, 12, 34, 32, 18432, 74, }, /* 175 */- { 1, 9, 12, 59, 32, 18432, 74, }, /* 176 */- { 1, 9, 12, 38, 32, 18432, 74, }, /* 177 */- { 1, 9, 12, 21, 32, 18432, 74, }, /* 178 */- { 1, 9, 12, 51, 32, 18432, 74, }, /* 179 */- { 1, 9, 12, 26, 32, 18432, 74, }, /* 180 */- { 1, 9, 12, 47, 32, 18432, 74, }, /* 181 */- { 1, 9, 12, 55, 32, 18432, 74, }, /* 182 */- { 1, 9, 12, 30, 32, 18432, 74, }, /* 183 */- { 1, 9, 12, 43, 32, 18432, 74, }, /* 184 */- { 1, 9, 12, 96, 32, 18432, 74, }, /* 185 */- { 1, 5, 12, 0, -38, 18432, 76, }, /* 186 */- { 1, 5, 12, 0, -37, 18432, 76, }, /* 187 */- { 1, 5, 12, 0, -32, 18432, 76, }, /* 188 */- { 1, 5, 12, 34, -32, 18432, 76, }, /* 189 */- { 1, 5, 12, 59, -32, 18432, 76, }, /* 190 */- { 1, 5, 12, 38, -32, 18432, 76, }, /* 191 */- { 1, 5, 12, 21, -116, 18432, 76, }, /* 192 */- { 1, 5, 12, 51, -32, 18432, 76, }, /* 193 */- { 1, 5, 12, 26, -775, 18432, 76, }, /* 194 */- { 1, 5, 12, 47, -32, 18432, 76, }, /* 195 */- { 1, 5, 12, 55, -32, 18432, 76, }, /* 196 */- { 1, 5, 12, 30, 1, 18432, 70, }, /* 197 */- { 1, 5, 12, 30, -32, 18432, 76, }, /* 198 */- { 1, 5, 12, 43, -32, 18432, 76, }, /* 199 */- { 1, 5, 12, 96, -32, 18432, 76, }, /* 200 */- { 1, 5, 12, 0, -64, 18432, 76, }, /* 201 */- { 1, 5, 12, 0, -63, 18432, 76, }, /* 202 */- { 1, 9, 12, 0, 8, 18432, 74, }, /* 203 */- { 1, 5, 12, 34, -30, 18432, 110, }, /* 204 */- { 1, 5, 12, 38, -25, 18432, 110, }, /* 205 */- { 1, 9, 12, 0, 0, 18432, 112, }, /* 206 */- { 1, 9, 12, 0, 0, 18432, 114, }, /* 207 */- { 1, 5, 12, 43, -15, 18432, 110, }, /* 208 */- { 1, 5, 12, 47, -22, 18432, 70, }, /* 209 */- { 1, 5, 12, 0, -8, 18432, 76, }, /* 210 */- { 34, 9, 12, 0, 1, 18432, 74, }, /* 211 */- { 34, 5, 12, 0, -1, 18432, 76, }, /* 212 */- { 1, 5, 12, 51, -54, 18432, 110, }, /* 213 */- { 1, 5, 12, 55, -48, 18432, 110, }, /* 214 */- { 1, 5, 12, 0, 7, 18432, 76, }, /* 215 */- { 1, 5, 12, 0, -116, 18432, 78, }, /* 216 */- { 1, 9, 12, 38, -60, 18432, 116, }, /* 217 */- { 1, 5, 12, 59, -64, 18432, 110, }, /* 218 */- { 1, 25, 12, 0, 0, 28672, 118, }, /* 219 */- { 1, 9, 12, 0, -7, 18432, 74, }, /* 220 */- { 1, 5, 12, 0, 0, 18432, 60, }, /* 221 */- { 1, 9, 12, 0, -130, 18432, 74, }, /* 222 */- { 2, 9, 12, 0, 80, 18432, 74, }, /* 223 */- { 2, 9, 12, 0, 32, 18432, 74, }, /* 224 */- { 2, 9, 12, 63, 32, 18432, 74, }, /* 225 */- { 2, 9, 12, 67, 32, 18432, 74, }, /* 226 */- { 2, 9, 12, 71, 32, 18432, 74, }, /* 227 */- { 2, 9, 12, 75, 32, 18432, 74, }, /* 228 */- { 2, 9, 12, 79, 32, 18432, 74, }, /* 229 */- { 2, 9, 12, 84, 32, 18432, 74, }, /* 230 */- { 2, 5, 12, 0, -32, 18432, 76, }, /* 231 */- { 2, 5, 12, 63, -32, 18432, 76, }, /* 232 */- { 2, 5, 12, 67, -32, 18432, 76, }, /* 233 */- { 2, 5, 12, 71, -32, 18432, 76, }, /* 234 */- { 2, 5, 12, 75, -32, 18432, 76, }, /* 235 */- { 2, 5, 12, 79, -32, 18432, 76, }, /* 236 */- { 2, 5, 12, 84, -32, 18432, 76, }, /* 237 */- { 2, 5, 12, 0, -80, 18432, 76, }, /* 238 */- { 2, 5, 12, 0, -80, 18432, 78, }, /* 239 */- { 2, 9, 12, 0, 1, 18432, 74, }, /* 240 */- { 2, 5, 12, 0, -1, 18432, 76, }, /* 241 */- { 2, 9, 12, 88, 1, 18432, 74, }, /* 242 */- { 2, 5, 12, 88, -1, 18432, 76, }, /* 243 */- { 2, 26, 12, 0, 0, 18432, 68, }, /* 244 */- { 2, 12, 3, 0, 0, 26684, 96, }, /* 245 */- { 2, 12, 3, 0, 0, 26678, 96, }, /* 246 */- { 84, 12, 3, 0, 0, 26681, 96, }, /* 247 */- { 2, 11, 3, 0, 0, 26624, 120, }, /* 248 */- { 2, 9, 12, 0, 15, 18432, 74, }, /* 249 */- { 2, 5, 12, 0, -15, 18432, 76, }, /* 250 */- { 70, 9, 12, 0, 48, 18432, 74, }, /* 251 */- { 70, 6, 12, 0, 0, 18432, 92, }, /* 252 */- { 70, 21, 12, 0, 0, 18432, 68, }, /* 253 */- { 70, 21, 12, 0, 0, 18432, 122, }, /* 254 */- { 70, 5, 12, 0, 0, 18432, 60, }, /* 255 */- { 70, 5, 12, 0, -48, 18432, 76, }, /* 256 */- { 70, 5, 12, 0, 0, 18432, 70, }, /* 257 */- { 70, 21, 12, 0, 0, 18432, 124, }, /* 258 */- { 70, 17, 12, 0, 0, 28672, 126, }, /* 259 */- { 70, 26, 12, 0, 0, 28672, 68, }, /* 260 */- { 70, 23, 12, 0, 0, 14336, 68, }, /* 261 */- { 68, 2, 12, 0, 0, 34816, 0, }, /* 262 */- { 71, 12, 3, 0, 0, 26624, 96, }, /* 263 */- { 71, 12, 3, 0, 0, 26624, 102, }, /* 264 */- { 71, 12, 3, 0, 0, 26624, 128, }, /* 265 */- { 71, 17, 12, 0, 0, 34816, 126, }, /* 266 */- { 71, 21, 12, 0, 0, 34816, 68, }, /* 267 */- { 71, 21, 12, 0, 0, 34816, 106, }, /* 268 */- { 71, 12, 3, 0, 0, 26624, 130, }, /* 269 */- { 71, 7, 12, 0, 0, 34816, 82, }, /* 270 */- { 71, 21, 12, 0, 0, 34816, 122, }, /* 271 */- { 3, 1, 4, 0, 0, 2048, 132, }, /* 272 */- { 69, 1, 4, 0, 0, 2048, 132, }, /* 273 */- { 3, 25, 12, 0, 0, 28672, 118, }, /* 274 */- { 3, 25, 12, 0, 0, 0, 118, }, /* 275 */- { 3, 21, 12, 0, 0, 14336, 68, }, /* 276 */- { 3, 23, 12, 0, 0, 0, 68, }, /* 277 */- { 69, 21, 12, 0, 0, 8342, 106, }, /* 278 */- { 3, 21, 12, 0, 0, 0, 68, }, /* 279 */- { 3, 26, 12, 0, 0, 28672, 68, }, /* 280 */- { 3, 12, 3, 0, 0, 26624, 130, }, /* 281 */- { 69, 21, 12, 0, 0, 150, 106, }, /* 282 */- { 3, 1, 2, 0, 0, 108, 134, }, /* 283 */- { 3, 21, 12, 0, 0, 0, 124, }, /* 284 */- { 69, 21, 12, 0, 0, 159, 124, }, /* 285 */- { 3, 7, 12, 0, 0, 0, 82, }, /* 286 */- { 69, 6, 12, 0, 0, 165, 136, }, /* 287 */- { 84, 12, 3, 0, 0, 26660, 128, }, /* 288 */- { 84, 12, 3, 0, 0, 26660, 130, }, /* 289 */- { 3, 12, 3, 0, 0, 26624, 128, }, /* 290 */- { 3, 12, 3, 0, 0, 26624, 96, }, /* 291 */- { 3, 13, 12, 0, 0, 2159, 138, }, /* 292 */- { 3, 21, 12, 0, 0, 2048, 68, }, /* 293 */- { 3, 7, 12, 0, 0, 0, 140, }, /* 294 */- { 3, 21, 12, 0, 0, 30, 124, }, /* 295 */- { 3, 6, 12, 0, 0, 0, 92, }, /* 296 */- { 3, 13, 12, 0, 0, 10240, 138, }, /* 297 */- { 3, 26, 12, 0, 0, 0, 68, }, /* 298 */- { 4, 21, 12, 0, 0, 0, 124, }, /* 299 */- { 4, 21, 12, 0, 0, 0, 106, }, /* 300 */- { 4, 21, 12, 0, 0, 0, 68, }, /* 301 */- { 68, 2, 12, 0, 0, 0, 0, }, /* 302 */- { 4, 1, 4, 0, 0, 0, 132, }, /* 303 */- { 4, 7, 12, 0, 0, 0, 82, }, /* 304 */- { 4, 12, 3, 0, 0, 26624, 130, }, /* 305 */- { 4, 12, 3, 0, 0, 26624, 128, }, /* 306 */- { 4, 12, 3, 0, 0, 26624, 96, }, /* 307 */- { 5, 7, 12, 0, 0, 0, 82, }, /* 308 */- { 5, 12, 3, 0, 0, 26624, 128, }, /* 309 */- { 38, 13, 12, 0, 0, 34816, 138, }, /* 310 */- { 38, 7, 12, 0, 0, 34816, 82, }, /* 311 */- { 38, 12, 3, 0, 0, 26624, 96, }, /* 312 */- { 38, 6, 12, 0, 0, 34816, 92, }, /* 313 */- { 38, 26, 12, 0, 0, 28672, 68, }, /* 314 */- { 38, 21, 12, 0, 0, 28672, 68, }, /* 315 */- { 38, 21, 12, 0, 0, 28672, 106, }, /* 316 */- { 38, 21, 12, 0, 0, 28672, 124, }, /* 317 */- { 38, 6, 12, 0, 0, 34816, 136, }, /* 318 */- { 38, 12, 3, 0, 0, 26624, 102, }, /* 319 */- { 38, 23, 12, 0, 0, 34816, 68, }, /* 320 */- { 110, 7, 12, 0, 0, 34816, 82, }, /* 321 */- { 110, 12, 3, 0, 0, 26624, 130, }, /* 322 */- { 110, 12, 3, 0, 0, 26624, 96, }, /* 323 */- { 110, 6, 12, 0, 0, 34816, 142, }, /* 324 */- { 110, 12, 3, 0, 0, 26624, 102, }, /* 325 */- { 110, 21, 12, 0, 0, 34816, 106, }, /* 326 */- { 110, 21, 12, 0, 0, 34816, 124, }, /* 327 */- { 42, 7, 12, 0, 0, 34816, 82, }, /* 328 */- { 42, 12, 3, 0, 0, 26624, 102, }, /* 329 */- { 42, 21, 12, 0, 0, 34816, 106, }, /* 330 */- { 3, 24, 12, 0, 0, 0, 122, }, /* 331 */- { 3, 12, 3, 0, 0, 26624, 102, }, /* 332 */- { 6, 12, 3, 0, 0, 26624, 130, }, /* 333 */- { 6, 10, 5, 0, 0, 18432, 144, }, /* 334 */- { 6, 7, 12, 0, 0, 18432, 82, }, /* 335 */- { 6, 12, 3, 0, 0, 26624, 96, }, /* 336 */- { 6, 12, 3, 0, 0, 26624, 146, }, /* 337 */- { 84, 12, 3, 0, 0, 26798, 96, }, /* 338 */- { 84, 12, 3, 0, 0, 26795, 96, }, /* 339 */- { 69, 21, 12, 0, 0, 18615, 124, }, /* 340 */- { 69, 21, 12, 0, 0, 18618, 124, }, /* 341 */- { 6, 13, 12, 0, 0, 18576, 138, }, /* 342 */- { 6, 21, 12, 0, 0, 18432, 68, }, /* 343 */- { 6, 6, 12, 0, 0, 18432, 92, }, /* 344 */- { 7, 7, 12, 0, 0, 18432, 82, }, /* 345 */- { 7, 12, 3, 0, 0, 26624, 130, }, /* 346 */- { 7, 10, 5, 0, 0, 18432, 144, }, /* 347 */- { 7, 12, 3, 0, 0, 26624, 96, }, /* 348 */- { 7, 10, 3, 0, 0, 18432, 148, }, /* 349 */- { 7, 12, 3, 0, 0, 26624, 146, }, /* 350 */- { 7, 13, 12, 0, 0, 18546, 138, }, /* 351 */- { 7, 23, 12, 0, 0, 14336, 68, }, /* 352 */- { 7, 15, 12, 0, 0, 18432, 68, }, /* 353 */- { 7, 26, 12, 0, 0, 18432, 68, }, /* 354 */- { 7, 21, 12, 0, 0, 18432, 68, }, /* 355 */- { 7, 12, 3, 0, 0, 26624, 102, }, /* 356 */- { 8, 12, 3, 0, 0, 26624, 130, }, /* 357 */- { 8, 10, 5, 0, 0, 18432, 144, }, /* 358 */- { 8, 7, 12, 0, 0, 18432, 82, }, /* 359 */- { 8, 12, 3, 0, 0, 26624, 96, }, /* 360 */- { 8, 12, 3, 0, 0, 26624, 146, }, /* 361 */- { 8, 13, 12, 0, 0, 18519, 138, }, /* 362 */- { 8, 21, 12, 0, 0, 18432, 68, }, /* 363 */- { 9, 12, 3, 0, 0, 26624, 130, }, /* 364 */- { 9, 10, 5, 0, 0, 18432, 144, }, /* 365 */- { 9, 7, 12, 0, 0, 18432, 82, }, /* 366 */- { 9, 12, 3, 0, 0, 26624, 96, }, /* 367 */- { 9, 12, 3, 0, 0, 26624, 146, }, /* 368 */- { 9, 13, 12, 0, 0, 18516, 138, }, /* 369 */- { 9, 21, 12, 0, 0, 18432, 68, }, /* 370 */- { 9, 23, 12, 0, 0, 14336, 68, }, /* 371 */- { 10, 12, 3, 0, 0, 26624, 130, }, /* 372 */- { 10, 10, 5, 0, 0, 18432, 144, }, /* 373 */- { 10, 7, 12, 0, 0, 18432, 82, }, /* 374 */- { 10, 12, 3, 0, 0, 26624, 96, }, /* 375 */- { 10, 10, 3, 0, 0, 18432, 148, }, /* 376 */- { 10, 12, 3, 0, 0, 26624, 146, }, /* 377 */- { 10, 12, 3, 0, 0, 26624, 150, }, /* 378 */- { 10, 13, 12, 0, 0, 18432, 138, }, /* 379 */- { 10, 26, 12, 0, 0, 18432, 68, }, /* 380 */- { 10, 15, 12, 0, 0, 18432, 68, }, /* 381 */- { 11, 12, 3, 0, 0, 26624, 130, }, /* 382 */- { 11, 7, 12, 0, 0, 18432, 82, }, /* 383 */- { 11, 10, 3, 0, 0, 18432, 148, }, /* 384 */- { 11, 10, 5, 0, 0, 18432, 144, }, /* 385 */- { 11, 12, 3, 0, 0, 26624, 146, }, /* 386 */- { 11, 13, 12, 0, 0, 18513, 138, }, /* 387 */- { 11, 15, 12, 0, 0, 18513, 68, }, /* 388 */- { 11, 26, 12, 0, 0, 28753, 68, }, /* 389 */- { 11, 26, 12, 0, 0, 28672, 68, }, /* 390 */- { 11, 23, 12, 0, 0, 14336, 68, }, /* 391 */- { 12, 12, 3, 0, 0, 26624, 130, }, /* 392 */- { 12, 10, 5, 0, 0, 18432, 144, }, /* 393 */- { 12, 12, 3, 0, 0, 26624, 102, }, /* 394 */- { 12, 7, 12, 0, 0, 18432, 82, }, /* 395 */- { 12, 12, 3, 0, 0, 26624, 96, }, /* 396 */- { 12, 12, 3, 0, 0, 26624, 146, }, /* 397 */- { 12, 13, 12, 0, 0, 18432, 138, }, /* 398 */- { 12, 21, 12, 0, 0, 18432, 68, }, /* 399 */- { 12, 15, 12, 0, 0, 28672, 68, }, /* 400 */- { 12, 26, 12, 0, 0, 18432, 68, }, /* 401 */- { 13, 7, 12, 0, 0, 18432, 82, }, /* 402 */- { 13, 12, 3, 0, 0, 26624, 130, }, /* 403 */- { 13, 10, 5, 0, 0, 18432, 144, }, /* 404 */- { 13, 21, 12, 0, 0, 18432, 68, }, /* 405 */- { 13, 12, 3, 0, 0, 26624, 96, }, /* 406 */- { 13, 12, 3, 0, 0, 18432, 130, }, /* 407 */- { 13, 10, 3, 0, 0, 18432, 148, }, /* 408 */- { 13, 12, 3, 0, 0, 26624, 146, }, /* 409 */- { 13, 13, 12, 0, 0, 18528, 138, }, /* 410 */- { 14, 12, 3, 0, 0, 26624, 130, }, /* 411 */- { 14, 10, 5, 0, 0, 18432, 144, }, /* 412 */- { 14, 7, 12, 0, 0, 18432, 82, }, /* 413 */- { 14, 12, 3, 0, 0, 26624, 146, }, /* 414 */- { 14, 10, 3, 0, 0, 18432, 148, }, /* 415 */- { 14, 7, 4, 0, 0, 18432, 82, }, /* 416 */- { 14, 26, 12, 0, 0, 18432, 68, }, /* 417 */- { 14, 15, 12, 0, 0, 18432, 68, }, /* 418 */- { 14, 13, 12, 0, 0, 18432, 138, }, /* 419 */- { 15, 12, 3, 0, 0, 26624, 130, }, /* 420 */- { 15, 10, 5, 0, 0, 18432, 144, }, /* 421 */- { 15, 7, 12, 0, 0, 18432, 82, }, /* 422 */- { 15, 12, 3, 0, 0, 26624, 146, }, /* 423 */- { 15, 10, 3, 0, 0, 18432, 148, }, /* 424 */- { 15, 13, 12, 0, 0, 18432, 138, }, /* 425 */- { 15, 21, 12, 0, 0, 18432, 68, }, /* 426 */- { 72, 7, 12, 0, 0, 18432, 82, }, /* 427 */- { 72, 12, 3, 0, 0, 26624, 130, }, /* 428 */- { 72, 7, 5, 0, 0, 18432, 152, }, /* 429 */- { 72, 12, 3, 0, 0, 26624, 154, }, /* 430 */- { 69, 23, 12, 0, 0, 14336, 68, }, /* 431 */- { 72, 7, 12, 0, 0, 18432, 156, }, /* 432 */- { 72, 6, 12, 0, 0, 18432, 136, }, /* 433 */- { 72, 12, 3, 0, 0, 26624, 96, }, /* 434 */- { 72, 21, 12, 0, 0, 18432, 68, }, /* 435 */- { 72, 13, 12, 0, 0, 18432, 138, }, /* 436 */- { 72, 21, 12, 0, 0, 18432, 106, }, /* 437 */- { 73, 7, 12, 0, 0, 18432, 82, }, /* 438 */- { 73, 12, 3, 0, 0, 26624, 130, }, /* 439 */- { 73, 7, 5, 0, 0, 18432, 152, }, /* 440 */- { 73, 12, 3, 0, 0, 26624, 146, }, /* 441 */- { 73, 7, 12, 0, 0, 18432, 156, }, /* 442 */- { 73, 6, 12, 0, 0, 18432, 136, }, /* 443 */- { 73, 12, 3, 0, 0, 26624, 96, }, /* 444 */- { 73, 13, 12, 0, 0, 18432, 138, }, /* 445 */- { 74, 7, 12, 0, 0, 18432, 82, }, /* 446 */- { 74, 26, 12, 0, 0, 18432, 68, }, /* 447 */- { 74, 21, 12, 0, 0, 18432, 68, }, /* 448 */- { 74, 21, 12, 0, 0, 18432, 106, }, /* 449 */- { 74, 12, 3, 0, 0, 26624, 96, }, /* 450 */- { 74, 13, 12, 0, 0, 18432, 138, }, /* 451 */- { 74, 15, 12, 0, 0, 18432, 68, }, /* 452 */- { 74, 22, 12, 0, 0, 28672, 158, }, /* 453 */- { 74, 18, 12, 0, 0, 28672, 158, }, /* 454 */- { 74, 10, 5, 0, 0, 18432, 160, }, /* 455 */- { 74, 12, 3, 0, 0, 26624, 130, }, /* 456 */- { 74, 12, 3, 0, 0, 26624, 162, }, /* 457 */- { 74, 10, 5, 0, 0, 18432, 144, }, /* 458 */- { 74, 12, 3, 0, 0, 26624, 146, }, /* 459 */- { 69, 26, 12, 0, 0, 18432, 68, }, /* 460 */- { 16, 7, 12, 0, 0, 18432, 82, }, /* 461 */- { 16, 10, 12, 0, 0, 18432, 144, }, /* 462 */- { 16, 12, 3, 0, 0, 26624, 130, }, /* 463 */- { 16, 10, 5, 0, 0, 18432, 144, }, /* 464 */- { 16, 12, 3, 0, 0, 26624, 96, }, /* 465 */- { 16, 12, 3, 0, 0, 26624, 146, }, /* 466 */- { 16, 13, 12, 0, 0, 18549, 138, }, /* 467 */- { 16, 21, 12, 0, 0, 18432, 124, }, /* 468 */- { 16, 21, 12, 0, 0, 18432, 68, }, /* 469 */- { 16, 10, 12, 0, 0, 18432, 164, }, /* 470 */- { 16, 12, 3, 0, 0, 26624, 128, }, /* 471 */- { 16, 13, 12, 0, 0, 18432, 138, }, /* 472 */- { 16, 26, 12, 0, 0, 18432, 68, }, /* 473 */- { 17, 9, 12, 0, 7264, 18432, 74, }, /* 474 */- { 17, 5, 12, 0, 3008, 18432, 166, }, /* 475 */- { 69, 21, 12, 0, 0, 18510, 68, }, /* 476 */- { 17, 6, 12, 0, 0, 18432, 142, }, /* 477 */- { 18, 7, 6, 0, 0, 18432, 82, }, /* 478 */- { 18, 7, 6, 0, 0, 18432, 168, }, /* 479 */- { 18, 7, 7, 0, 0, 18432, 168, }, /* 480 */- { 18, 7, 7, 0, 0, 18432, 82, }, /* 481 */- { 18, 7, 8, 0, 0, 18432, 82, }, /* 482 */- { 75, 7, 12, 0, 0, 18432, 82, }, /* 483 */- { 75, 12, 3, 0, 0, 26624, 96, }, /* 484 */- { 75, 21, 12, 0, 0, 18432, 68, }, /* 485 */- { 75, 21, 12, 0, 0, 18432, 106, }, /* 486 */- { 75, 21, 12, 0, 0, 18432, 124, }, /* 487 */- { 75, 15, 12, 0, 0, 18432, 138, }, /* 488 */- { 75, 15, 12, 0, 0, 18432, 68, }, /* 489 */- { 75, 26, 12, 0, 0, 28672, 68, }, /* 490 */- { 76, 9, 12, 0, 38864, 18432, 170, }, /* 491 */- { 76, 9, 12, 0, 8, 18432, 170, }, /* 492 */- { 76, 5, 12, 0, -8, 18432, 70, }, /* 493 */- { 77, 17, 12, 0, 0, 28672, 126, }, /* 494 */- { 77, 7, 12, 0, 0, 18432, 82, }, /* 495 */- { 77, 26, 12, 0, 0, 18432, 68, }, /* 496 */- { 77, 21, 12, 0, 0, 18432, 124, }, /* 497 */- { 78, 29, 12, 0, 0, 45056, 52, }, /* 498 */- { 78, 7, 12, 0, 0, 18432, 82, }, /* 499 */- { 78, 22, 12, 0, 0, 28672, 158, }, /* 500 */- { 78, 18, 12, 0, 0, 28672, 158, }, /* 501 */- { 79, 7, 12, 0, 0, 18432, 82, }, /* 502 */- { 69, 21, 12, 0, 0, 18432, 106, }, /* 503 */- { 79, 14, 12, 0, 0, 18432, 82, }, /* 504 */- { 25, 7, 12, 0, 0, 18432, 82, }, /* 505 */- { 25, 12, 3, 0, 0, 26624, 130, }, /* 506 */- { 25, 12, 3, 0, 0, 26624, 146, }, /* 507 */- { 25, 10, 5, 0, 0, 18432, 172, }, /* 508 */- { 26, 7, 12, 0, 0, 18432, 82, }, /* 509 */- { 26, 12, 3, 0, 0, 26624, 130, }, /* 510 */- { 26, 10, 5, 0, 0, 18432, 174, }, /* 511 */- { 69, 21, 12, 0, 0, 18573, 124, }, /* 512 */- { 27, 7, 12, 0, 0, 18432, 82, }, /* 513 */- { 27, 12, 3, 0, 0, 26624, 130, }, /* 514 */- { 28, 7, 12, 0, 0, 18432, 82, }, /* 515 */- { 28, 12, 3, 0, 0, 26624, 130, }, /* 516 */- { 80, 7, 12, 0, 0, 18432, 82, }, /* 517 */- { 80, 7, 12, 0, 0, 18432, 140, }, /* 518 */- { 80, 12, 3, 0, 0, 26624, 100, }, /* 519 */- { 80, 10, 5, 0, 0, 18432, 144, }, /* 520 */- { 80, 12, 3, 0, 0, 26624, 130, }, /* 521 */- { 80, 12, 3, 0, 0, 26624, 96, }, /* 522 */- { 80, 12, 3, 0, 0, 26624, 146, }, /* 523 */- { 80, 21, 12, 0, 0, 18432, 106, }, /* 524 */- { 80, 6, 12, 0, 0, 18432, 142, }, /* 525 */- { 80, 21, 12, 0, 0, 18432, 68, }, /* 526 */- { 80, 23, 12, 0, 0, 14336, 68, }, /* 527 */- { 80, 13, 12, 0, 0, 18432, 138, }, /* 528 */- { 80, 15, 12, 0, 0, 28672, 68, }, /* 529 */- { 19, 21, 12, 0, 0, 28672, 68, }, /* 530 */- { 69, 21, 12, 0, 0, 28777, 106, }, /* 531 */- { 69, 21, 12, 0, 0, 28777, 124, }, /* 532 */- { 19, 21, 12, 0, 0, 28672, 106, }, /* 533 */- { 19, 17, 12, 0, 0, 28672, 126, }, /* 534 */- { 19, 21, 12, 0, 0, 28672, 124, }, /* 535 */- { 19, 21, 12, 0, 0, 28672, 176, }, /* 536 */- { 19, 12, 3, 0, 0, 26624, 178, }, /* 537 */- { 19, 1, 2, 0, 0, 6144, 66, }, /* 538 */- { 19, 13, 12, 0, 0, 18432, 138, }, /* 539 */- { 19, 7, 12, 0, 0, 18432, 82, }, /* 540 */- { 19, 6, 12, 0, 0, 18432, 136, }, /* 541 */- { 19, 12, 3, 0, 0, 26624, 180, }, /* 542 */- { 19, 12, 3, 0, 0, 26624, 130, }, /* 543 */- { 29, 7, 12, 0, 0, 18432, 82, }, /* 544 */- { 29, 12, 3, 0, 0, 26624, 130, }, /* 545 */- { 29, 10, 5, 0, 0, 18432, 144, }, /* 546 */- { 29, 12, 3, 0, 0, 26624, 96, }, /* 547 */- { 29, 26, 12, 0, 0, 28672, 68, }, /* 548 */- { 29, 21, 12, 0, 0, 28672, 124, }, /* 549 */- { 29, 13, 12, 0, 0, 18432, 138, }, /* 550 */- { 30, 7, 12, 0, 0, 18432, 82, }, /* 551 */- { 89, 7, 12, 0, 0, 18432, 82, }, /* 552 */- { 89, 7, 12, 0, 0, 18432, 156, }, /* 553 */- { 89, 13, 12, 0, 0, 18432, 138, }, /* 554 */- { 89, 15, 12, 0, 0, 18432, 138, }, /* 555 */- { 89, 26, 12, 0, 0, 28672, 68, }, /* 556 */- { 80, 26, 12, 0, 0, 28672, 68, }, /* 557 */- { 33, 7, 12, 0, 0, 18432, 82, }, /* 558 */- { 33, 12, 3, 0, 0, 26624, 130, }, /* 559 */- { 33, 10, 5, 0, 0, 18432, 144, }, /* 560 */- { 33, 21, 12, 0, 0, 18432, 68, }, /* 561 */- { 106, 7, 12, 0, 0, 18432, 82, }, /* 562 */- { 106, 10, 5, 0, 0, 18432, 144, }, /* 563 */- { 106, 12, 3, 0, 0, 26624, 130, }, /* 564 */- { 106, 12, 3, 0, 0, 26624, 182, }, /* 565 */- { 106, 10, 12, 0, 0, 18432, 144, }, /* 566 */- { 106, 12, 3, 0, 0, 26624, 96, }, /* 567 */- { 106, 13, 12, 0, 0, 18432, 138, }, /* 568 */- { 106, 21, 12, 0, 0, 18432, 68, }, /* 569 */- { 106, 6, 12, 0, 0, 18432, 136, }, /* 570 */- { 106, 21, 12, 0, 0, 18432, 124, }, /* 571 */- { 84, 11, 3, 0, 0, 26624, 184, }, /* 572 */- { 84, 12, 3, 0, 0, 26624, 130, }, /* 573 */- { 93, 12, 3, 0, 0, 26624, 130, }, /* 574 */- { 93, 10, 5, 0, 0, 18432, 144, }, /* 575 */- { 93, 7, 12, 0, 0, 18432, 82, }, /* 576 */- { 93, 12, 3, 0, 0, 26624, 96, }, /* 577 */- { 93, 10, 3, 0, 0, 18432, 148, }, /* 578 */- { 93, 10, 5, 0, 0, 18432, 172, }, /* 579 */- { 93, 13, 12, 0, 0, 18432, 138, }, /* 580 */- { 93, 21, 12, 0, 0, 18432, 124, }, /* 581 */- { 93, 21, 12, 0, 0, 18432, 68, }, /* 582 */- { 93, 21, 12, 0, 0, 18432, 106, }, /* 583 */- { 93, 26, 12, 0, 0, 18432, 68, }, /* 584 */- { 96, 12, 3, 0, 0, 26624, 130, }, /* 585 */- { 96, 10, 5, 0, 0, 18432, 144, }, /* 586 */- { 96, 7, 12, 0, 0, 18432, 82, }, /* 587 */- { 96, 10, 5, 0, 0, 18432, 172, }, /* 588 */- { 96, 12, 3, 0, 0, 26624, 146, }, /* 589 */- { 96, 13, 12, 0, 0, 18432, 138, }, /* 590 */- { 119, 7, 12, 0, 0, 18432, 82, }, /* 591 */- { 119, 12, 3, 0, 0, 26624, 102, }, /* 592 */- { 119, 10, 5, 0, 0, 18432, 144, }, /* 593 */- { 119, 12, 3, 0, 0, 26624, 130, }, /* 594 */- { 119, 10, 5, 0, 0, 18432, 174, }, /* 595 */- { 119, 21, 12, 0, 0, 18432, 68, }, /* 596 */- { 97, 7, 12, 0, 0, 18432, 82, }, /* 597 */- { 97, 10, 5, 0, 0, 18432, 144, }, /* 598 */- { 97, 12, 3, 0, 0, 26624, 130, }, /* 599 */- { 97, 12, 3, 0, 0, 26624, 186, }, /* 600 */- { 97, 12, 3, 0, 0, 26624, 96, }, /* 601 */- { 97, 21, 12, 0, 0, 18432, 124, }, /* 602 */- { 97, 21, 12, 0, 0, 18432, 106, }, /* 603 */- { 97, 13, 12, 0, 0, 18432, 138, }, /* 604 */- { 98, 13, 12, 0, 0, 18432, 138, }, /* 605 */- { 98, 7, 12, 0, 0, 18432, 82, }, /* 606 */- { 98, 6, 12, 0, 0, 18432, 92, }, /* 607 */- { 98, 6, 12, 0, 0, 18432, 94, }, /* 608 */- { 98, 21, 12, 0, 0, 18432, 124, }, /* 609 */- { 2, 5, 12, 63, -6222, 18432, 70, }, /* 610 */- { 2, 5, 12, 67, -6221, 18432, 70, }, /* 611 */- { 2, 5, 12, 71, -6212, 18432, 70, }, /* 612 */- { 2, 5, 12, 75, -6210, 18432, 70, }, /* 613 */- { 2, 5, 12, 79, -6210, 18432, 70, }, /* 614 */- { 2, 5, 12, 79, -6211, 18432, 70, }, /* 615 */- { 2, 5, 12, 84, -6204, 18432, 70, }, /* 616 */- { 2, 5, 12, 88, -6180, 18432, 70, }, /* 617 */- { 2, 5, 12, 108, 35267, 18432, 70, }, /* 618 */- { 17, 9, 12, 0, -3008, 18432, 74, }, /* 619 */- { 96, 21, 12, 0, 0, 18432, 68, }, /* 620 */- { 84, 12, 3, 0, 0, 26762, 96, }, /* 621 */- { 84, 12, 3, 0, 0, 26630, 96, }, /* 622 */- { 69, 21, 12, 0, 0, 18498, 188, }, /* 623 */- { 84, 12, 3, 0, 0, 26666, 96, }, /* 624 */- { 84, 12, 3, 0, 0, 26696, 96, }, /* 625 */- { 84, 12, 3, 0, 0, 26780, 96, }, /* 626 */- { 69, 10, 5, 0, 0, 18474, 160, }, /* 627 */- { 69, 7, 12, 0, 0, 18501, 82, }, /* 628 */- { 69, 7, 12, 0, 0, 18474, 82, }, /* 629 */- { 69, 7, 12, 0, 0, 18438, 82, }, /* 630 */- { 69, 7, 12, 0, 0, 18594, 82, }, /* 631 */- { 69, 7, 12, 0, 0, 18498, 82, }, /* 632 */- { 84, 12, 3, 0, 0, 26750, 96, }, /* 633 */- { 69, 10, 5, 0, 0, 18435, 160, }, /* 634 */- { 84, 12, 3, 0, 0, 26690, 96, }, /* 635 */- { 69, 7, 12, 0, 0, 18453, 82, }, /* 636 */- { 2, 5, 12, 0, 0, 18432, 60, }, /* 637 */- { 1, 6, 12, 0, 0, 18432, 88, }, /* 638 */- { 2, 6, 12, 0, 0, 18432, 190, }, /* 639 */- { 0, 5, 12, 0, 35332, 18432, 76, }, /* 640 */- { 0, 5, 12, 0, 3814, 18432, 76, }, /* 641 */- { 0, 5, 12, 0, 35384, 18432, 76, }, /* 642 */- { 0, 5, 12, 0, 0, 18432, 192, }, /* 643 */- { 0, 6, 12, 0, 0, 18432, 190, }, /* 644 */- { 0, 6, 12, 0, 0, 18432, 194, }, /* 645 */- { 1, 6, 12, 0, 0, 18432, 190, }, /* 646 */- { 84, 12, 3, 0, 0, 26636, 102, }, /* 647 */- { 84, 12, 3, 0, 0, 26687, 96, }, /* 648 */- { 84, 12, 3, 0, 0, 26648, 96, }, /* 649 */- { 0, 9, 12, 92, 1, 18432, 74, }, /* 650 */- { 0, 5, 12, 92, -1, 18432, 76, }, /* 651 */- { 0, 5, 12, 0, 0, 18432, 70, }, /* 652 */- { 0, 5, 12, 92, -58, 18432, 70, }, /* 653 */- { 0, 9, 12, 0, -7615, 18432, 74, }, /* 654 */- { 1, 5, 12, 0, 8, 18432, 76, }, /* 655 */- { 1, 9, 12, 0, -8, 18432, 74, }, /* 656 */- { 1, 5, 12, 0, 74, 18432, 76, }, /* 657 */- { 1, 5, 12, 0, 86, 18432, 76, }, /* 658 */- { 1, 5, 12, 0, 100, 18432, 76, }, /* 659 */- { 1, 5, 12, 0, 128, 18432, 76, }, /* 660 */- { 1, 5, 12, 0, 112, 18432, 76, }, /* 661 */- { 1, 5, 12, 0, 126, 18432, 76, }, /* 662 */- { 1, 5, 12, 0, 8, 18432, 70, }, /* 663 */- { 1, 8, 12, 0, -8, 18432, 86, }, /* 664 */- { 1, 5, 12, 0, 0, 18432, 70, }, /* 665 */- { 1, 5, 12, 0, 9, 18432, 70, }, /* 666 */- { 1, 9, 12, 0, -74, 18432, 74, }, /* 667 */- { 1, 8, 12, 0, -9, 18432, 86, }, /* 668 */- { 1, 5, 12, 21, -7173, 18432, 76, }, /* 669 */- { 1, 9, 12, 0, -86, 18432, 74, }, /* 670 */- { 1, 9, 12, 0, -100, 18432, 74, }, /* 671 */- { 1, 9, 12, 0, -112, 18432, 74, }, /* 672 */- { 1, 9, 12, 0, -128, 18432, 74, }, /* 673 */- { 1, 9, 12, 0, -126, 18432, 74, }, /* 674 */- { 69, 29, 12, 0, 0, 45056, 52, }, /* 675 */- { 84, 1, 3, 0, 0, 6144, 196, }, /* 676 */- { 84, 1, 13, 0, 0, 6144, 198, }, /* 677 */- { 69, 1, 2, 0, 0, 18432, 200, }, /* 678 */- { 69, 1, 2, 0, 0, 34816, 200, }, /* 679 */- { 69, 17, 12, 0, 0, 28672, 202, }, /* 680 */- { 69, 21, 12, 0, 0, 28672, 64, }, /* 681 */- { 69, 20, 12, 0, 0, 28672, 204, }, /* 682 */- { 69, 19, 12, 0, 0, 28672, 204, }, /* 683 */- { 69, 22, 12, 0, 0, 28672, 206, }, /* 684 */- { 69, 20, 12, 0, 0, 28672, 206, }, /* 685 */- { 69, 19, 12, 0, 0, 28672, 206, }, /* 686 */- { 69, 21, 12, 0, 0, 28672, 208, }, /* 687 */- { 69, 27, 2, 0, 0, 45056, 50, }, /* 688 */- { 69, 28, 2, 0, 0, 4096, 50, }, /* 689 */- { 69, 1, 2, 0, 0, 20480, 134, }, /* 690 */- { 69, 1, 2, 0, 0, 36864, 134, }, /* 691 */- { 69, 1, 2, 0, 0, 30720, 134, }, /* 692 */- { 69, 1, 2, 0, 0, 24576, 134, }, /* 693 */- { 69, 1, 2, 0, 0, 40960, 134, }, /* 694 */- { 69, 29, 12, 0, 0, 8291, 52, }, /* 695 */- { 69, 21, 12, 0, 0, 14336, 54, }, /* 696 */- { 69, 21, 12, 0, 0, 14336, 64, }, /* 697 */- { 69, 21, 14, 0, 0, 28672, 210, }, /* 698 */- { 69, 21, 12, 0, 0, 28672, 212, }, /* 699 */- { 69, 16, 12, 0, 0, 28672, 138, }, /* 700 */- { 69, 16, 12, 0, 0, 28672, 214, }, /* 701 */- { 69, 25, 12, 0, 0, 8192, 64, }, /* 702 */- { 69, 22, 12, 0, 0, 28672, 216, }, /* 703 */- { 69, 18, 12, 0, 0, 28672, 216, }, /* 704 */- { 69, 21, 12, 0, 0, 28672, 202, }, /* 705 */- { 69, 1, 2, 0, 0, 6144, 218, }, /* 706 */- { 68, 2, 2, 0, 0, 6144, 220, }, /* 707 */- { 69, 1, 2, 0, 0, 22528, 134, }, /* 708 */- { 69, 1, 2, 0, 0, 38912, 134, }, /* 709 */- { 69, 1, 2, 0, 0, 16384, 134, }, /* 710 */- { 69, 1, 2, 0, 0, 32768, 134, }, /* 711 */- { 69, 1, 2, 0, 0, 6144, 222, }, /* 712 */- { 69, 25, 12, 0, 0, 12288, 118, }, /* 713 */- { 69, 25, 12, 0, 0, 12288, 224, }, /* 714 */- { 69, 25, 12, 0, 0, 28672, 118, }, /* 715 */- { 69, 22, 12, 0, 0, 28672, 226, }, /* 716 */- { 69, 18, 12, 0, 0, 28672, 226, }, /* 717 */- { 68, 2, 12, 0, 0, 14336, 0, }, /* 718 */- { 84, 12, 3, 0, 0, 26624, 228, }, /* 719 */- { 84, 11, 3, 0, 0, 26624, 120, }, /* 720 */- { 84, 11, 3, 0, 0, 26624, 230, }, /* 721 */- { 84, 12, 3, 0, 0, 26753, 102, }, /* 722 */- { 69, 26, 12, 0, 0, 28672, 68, }, /* 723 */- { 69, 9, 12, 0, 0, 18432, 112, }, /* 724 */- { 69, 5, 12, 0, 0, 18432, 232, }, /* 725 */- { 69, 25, 12, 0, 0, 28672, 234, }, /* 726 */- { 69, 26, 14, 0, 0, 28672, 236, }, /* 727 */- { 1, 9, 12, 96, -7517, 18432, 74, }, /* 728 */- { 69, 26, 12, 0, 0, 28672, 118, }, /* 729 */- { 0, 9, 12, 100, -8383, 18432, 74, }, /* 730 */- { 0, 9, 12, 104, -8262, 18432, 74, }, /* 731 */- { 69, 26, 12, 0, 0, 14336, 238, }, /* 732 */- { 0, 9, 12, 0, 28, 18432, 74, }, /* 733 */- { 69, 7, 12, 0, 0, 18432, 240, }, /* 734 */- { 69, 5, 14, 0, 0, 18432, 242, }, /* 735 */- { 69, 5, 12, 0, 0, 18432, 244, }, /* 736 */- { 0, 5, 12, 0, -28, 18432, 76, }, /* 737 */- { 0, 14, 12, 0, 16, 18432, 74, }, /* 738 */- { 0, 14, 12, 0, -16, 18432, 76, }, /* 739 */- { 0, 14, 12, 0, 0, 18432, 82, }, /* 740 */- { 69, 25, 14, 0, 0, 28672, 246, }, /* 741 */- { 69, 26, 14, 0, 0, 28672, 246, }, /* 742 */- { 69, 26, 12, 0, 0, 28672, 64, }, /* 743 */- { 69, 25, 12, 0, 0, 28672, 248, }, /* 744 */- { 69, 25, 12, 0, 0, 12288, 250, }, /* 745 */- { 69, 22, 12, 0, 0, 28672, 248, }, /* 746 */- { 69, 18, 12, 0, 0, 28672, 248, }, /* 747 */- { 69, 26, 14, 0, 0, 28672, 252, }, /* 748 */- { 69, 22, 12, 0, 0, 28672, 254, }, /* 749 */- { 69, 18, 12, 0, 0, 28672, 254, }, /* 750 */- { 69, 26, 12, 0, 0, 18432, 54, }, /* 751 */- { 69, 26, 14, 0, 0, 28672, 256, }, /* 752 */- { 68, 2, 12, 0, 0, 18432, 258, }, /* 753 */- { 69, 26, 12, 0, 26, 18432, 260, }, /* 754 */- { 69, 26, 14, 0, 26, 18432, 262, }, /* 755 */- { 69, 26, 12, 0, -26, 18432, 264, }, /* 756 */- { 69, 25, 14, 0, 0, 28672, 266, }, /* 757 */- { 69, 26, 14, 0, 0, 28672, 268, }, /* 758 */- { 69, 26, 14, 0, 0, 28672, 270, }, /* 759 */- { 69, 25, 14, 0, 0, 28672, 268, }, /* 760 */- { 69, 26, 14, 0, 0, 18432, 256, }, /* 761 */- { 69, 26, 14, 0, 0, 28672, 272, }, /* 762 */- { 88, 26, 12, 0, 0, 18432, 54, }, /* 763 */- { 69, 26, 12, 0, 0, 28672, 216, }, /* 764 */- { 35, 9, 12, 0, 48, 18432, 74, }, /* 765 */- { 35, 5, 12, 0, -48, 18432, 76, }, /* 766 */- { 0, 9, 12, 0, -10743, 18432, 74, }, /* 767 */- { 0, 9, 12, 0, -3814, 18432, 74, }, /* 768 */- { 0, 9, 12, 0, -10727, 18432, 74, }, /* 769 */- { 0, 5, 12, 0, -10795, 18432, 76, }, /* 770 */- { 0, 5, 12, 0, -10792, 18432, 76, }, /* 771 */- { 0, 9, 12, 0, -10780, 18432, 74, }, /* 772 */- { 0, 9, 12, 0, -10749, 18432, 74, }, /* 773 */- { 0, 9, 12, 0, -10783, 18432, 74, }, /* 774 */- { 0, 9, 12, 0, -10782, 18432, 74, }, /* 775 */- { 0, 9, 12, 0, -10815, 18432, 74, }, /* 776 */- { 34, 5, 12, 0, 0, 18432, 60, }, /* 777 */- { 34, 26, 12, 0, 0, 28672, 68, }, /* 778 */- { 34, 12, 3, 0, 0, 26624, 96, }, /* 779 */- { 34, 21, 12, 0, 0, 28672, 68, }, /* 780 */- { 34, 15, 12, 0, 0, 28672, 68, }, /* 781 */- { 17, 5, 12, 0, -7264, 18432, 76, }, /* 782 */- { 90, 7, 12, 0, 0, 18432, 82, }, /* 783 */- { 90, 6, 12, 0, 0, 18432, 142, }, /* 784 */- { 90, 21, 12, 0, 0, 18432, 68, }, /* 785 */- { 90, 12, 3, 0, 0, 26624, 182, }, /* 786 */- { 2, 12, 3, 0, 0, 26624, 130, }, /* 787 */- { 69, 20, 12, 0, 0, 28672, 216, }, /* 788 */- { 69, 19, 12, 0, 0, 28672, 216, }, /* 789 */- { 69, 6, 12, 0, 0, 28672, 274, }, /* 790 */- { 69, 21, 12, 0, 0, 28672, 276, }, /* 791 */- { 69, 21, 12, 0, 0, 28726, 54, }, /* 792 */- { 23, 26, 12, 0, 0, 28672, 278, }, /* 793 */- { 69, 26, 12, 0, 0, 28672, 280, }, /* 794 */- { 69, 26, 12, 0, 0, 28672, 282, }, /* 795 */- { 69, 21, 12, 0, 0, 28825, 276, }, /* 796 */- { 69, 21, 12, 0, 0, 28825, 212, }, /* 797 */- { 69, 21, 12, 0, 0, 28819, 54, }, /* 798 */- { 23, 6, 12, 0, 0, 18432, 136, }, /* 799 */- { 69, 7, 12, 0, 0, 18447, 284, }, /* 800 */- { 23, 14, 12, 0, 0, 18432, 284, }, /* 801 */- { 69, 22, 12, 0, 0, 28825, 216, }, /* 802 */- { 69, 18, 12, 0, 0, 28825, 216, }, /* 803 */- { 69, 22, 12, 0, 0, 28825, 62, }, /* 804 */- { 69, 18, 12, 0, 0, 28825, 62, }, /* 805 */- { 69, 26, 12, 0, 0, 28819, 54, }, /* 806 */- { 69, 17, 12, 0, 0, 28819, 202, }, /* 807 */- { 69, 22, 12, 0, 0, 28819, 206, }, /* 808 */- { 69, 18, 12, 0, 0, 28819, 206, }, /* 809 */- { 84, 12, 3, 0, 0, 26669, 96, }, /* 810 */- { 18, 10, 3, 0, 0, 18432, 286, }, /* 811 */- { 69, 17, 14, 0, 0, 28819, 288, }, /* 812 */- { 69, 6, 12, 0, 0, 18525, 136, }, /* 813 */- { 69, 26, 12, 0, 0, 28819, 68, }, /* 814 */- { 23, 6, 12, 0, 0, 18432, 142, }, /* 815 */- { 69, 7, 12, 0, 0, 18564, 82, }, /* 816 */- { 69, 21, 14, 0, 0, 28804, 236, }, /* 817 */- { 69, 26, 12, 0, 0, 28687, 68, }, /* 818 */- { 20, 7, 12, 0, 0, 18432, 82, }, /* 819 */- { 84, 12, 3, 0, 0, 26717, 96, }, /* 820 */- { 69, 24, 12, 0, 0, 28765, 290, }, /* 821 */- { 20, 6, 12, 0, 0, 18432, 136, }, /* 822 */- { 69, 17, 12, 0, 0, 28765, 126, }, /* 823 */- { 21, 7, 12, 0, 0, 18432, 82, }, /* 824 */- { 69, 21, 12, 0, 0, 28825, 68, }, /* 825 */- { 69, 6, 12, 0, 0, 18525, 94, }, /* 826 */- { 21, 6, 12, 0, 0, 18432, 136, }, /* 827 */- { 22, 7, 12, 0, 0, 18432, 82, }, /* 828 */- { 18, 7, 12, 0, 0, 18432, 82, }, /* 829 */- { 18, 7, 12, 0, 0, 18432, 168, }, /* 830 */- { 69, 26, 12, 0, 0, 18447, 68, }, /* 831 */- { 69, 15, 12, 0, 0, 18447, 68, }, /* 832 */- { 18, 26, 12, 0, 0, 18432, 68, }, /* 833 */- { 18, 26, 12, 0, 0, 28672, 68, }, /* 834 */- { 69, 15, 12, 0, 0, 18432, 68, }, /* 835 */- { 69, 26, 14, 0, 0, 18447, 236, }, /* 836 */- { 21, 26, 12, 0, 0, 18432, 68, }, /* 837 */- { 23, 7, 12, 0, 0, 18432, 292, }, /* 838 */- { 24, 7, 12, 0, 0, 18432, 82, }, /* 839 */- { 24, 6, 12, 0, 0, 18432, 136, }, /* 840 */- { 24, 26, 12, 0, 0, 28672, 68, }, /* 841 */- { 111, 7, 12, 0, 0, 18432, 82, }, /* 842 */- { 111, 6, 12, 0, 0, 18432, 142, }, /* 843 */- { 111, 21, 12, 0, 0, 18432, 106, }, /* 844 */- { 111, 21, 12, 0, 0, 18432, 124, }, /* 845 */- { 99, 7, 12, 0, 0, 18432, 82, }, /* 846 */- { 99, 6, 12, 0, 0, 18432, 136, }, /* 847 */- { 99, 21, 12, 0, 0, 28672, 106, }, /* 848 */- { 99, 21, 12, 0, 0, 28672, 124, }, /* 849 */- { 99, 13, 12, 0, 0, 18432, 138, }, /* 850 */- { 2, 9, 12, 108, 1, 18432, 74, }, /* 851 */- { 2, 5, 12, 108, -35267, 18432, 76, }, /* 852 */- { 2, 7, 12, 0, 0, 18432, 82, }, /* 853 */- { 2, 21, 12, 0, 0, 28672, 68, }, /* 854 */- { 2, 12, 3, 0, 0, 26624, 96, }, /* 855 */- { 2, 6, 12, 0, 0, 28672, 92, }, /* 856 */- { 2, 6, 12, 0, 0, 18432, 88, }, /* 857 */- { 112, 7, 12, 0, 0, 18432, 82, }, /* 858 */- { 112, 14, 12, 0, 0, 18432, 82, }, /* 859 */- { 112, 12, 3, 0, 0, 26624, 96, }, /* 860 */- { 112, 21, 12, 0, 0, 18432, 68, }, /* 861 */- { 112, 21, 12, 0, 0, 18432, 124, }, /* 862 */- { 112, 21, 12, 0, 0, 18432, 106, }, /* 863 */- { 69, 24, 12, 0, 0, 28762, 56, }, /* 864 */- { 0, 9, 12, 0, -35332, 18432, 74, }, /* 865 */- { 69, 24, 12, 0, 0, 18432, 56, }, /* 866 */- { 0, 9, 12, 0, -42280, 18432, 74, }, /* 867 */- { 0, 5, 12, 0, 48, 18432, 76, }, /* 868 */- { 0, 9, 12, 0, -42308, 18432, 74, }, /* 869 */- { 0, 9, 12, 0, -42319, 18432, 74, }, /* 870 */- { 0, 9, 12, 0, -42315, 18432, 74, }, /* 871 */- { 0, 9, 12, 0, -42305, 18432, 74, }, /* 872 */- { 0, 9, 12, 0, -42258, 18432, 74, }, /* 873 */- { 0, 9, 12, 0, -42282, 18432, 74, }, /* 874 */- { 0, 9, 12, 0, -42261, 18432, 74, }, /* 875 */- { 0, 9, 12, 0, 928, 18432, 74, }, /* 876 */- { 0, 9, 12, 0, -48, 18432, 74, }, /* 877 */- { 0, 9, 12, 0, -42307, 18432, 74, }, /* 878 */- { 0, 9, 12, 0, -35384, 18432, 74, }, /* 879 */- { 0, 6, 12, 0, 0, 18432, 142, }, /* 880 */- { 36, 7, 12, 0, 0, 18432, 82, }, /* 881 */- { 36, 12, 3, 0, 0, 26624, 130, }, /* 882 */- { 36, 12, 3, 0, 0, 26624, 182, }, /* 883 */- { 36, 10, 5, 0, 0, 18432, 144, }, /* 884 */- { 36, 26, 12, 0, 0, 28672, 68, }, /* 885 */- { 69, 15, 12, 0, 0, 18612, 68, }, /* 886 */- { 69, 15, 12, 0, 0, 18609, 68, }, /* 887 */- { 69, 26, 12, 0, 0, 18600, 68, }, /* 888 */- { 69, 23, 12, 0, 0, 14504, 68, }, /* 889 */- { 69, 26, 12, 0, 0, 14504, 68, }, /* 890 */- { 37, 7, 12, 0, 0, 18432, 82, }, /* 891 */- { 37, 21, 12, 0, 0, 28672, 68, }, /* 892 */- { 37, 21, 12, 0, 0, 28672, 124, }, /* 893 */- { 100, 10, 5, 0, 0, 18432, 144, }, /* 894 */- { 100, 7, 12, 0, 0, 18432, 82, }, /* 895 */- { 100, 12, 3, 0, 0, 26624, 146, }, /* 896 */- { 100, 12, 3, 0, 0, 26624, 130, }, /* 897 */- { 100, 21, 12, 0, 0, 18432, 124, }, /* 898 */- { 100, 13, 12, 0, 0, 18432, 138, }, /* 899 */- { 6, 12, 3, 0, 0, 26666, 96, }, /* 900 */- { 6, 7, 12, 0, 0, 18507, 82, }, /* 901 */- { 39, 13, 12, 0, 0, 18432, 138, }, /* 902 */- { 39, 7, 12, 0, 0, 18432, 82, }, /* 903 */- { 39, 12, 3, 0, 0, 26624, 130, }, /* 904 */- { 39, 12, 3, 0, 0, 26624, 96, }, /* 905 */- { 69, 21, 12, 0, 0, 18567, 188, }, /* 906 */- { 39, 21, 12, 0, 0, 18432, 124, }, /* 907 */- { 101, 7, 12, 0, 0, 18432, 82, }, /* 908 */- { 101, 12, 3, 0, 0, 26624, 130, }, /* 909 */- { 101, 10, 5, 0, 0, 18432, 144, }, /* 910 */- { 101, 10, 5, 0, 0, 18432, 172, }, /* 911 */- { 101, 21, 12, 0, 0, 18432, 68, }, /* 912 */- { 40, 12, 3, 0, 0, 26624, 130, }, /* 913 */- { 40, 10, 5, 0, 0, 18432, 144, }, /* 914 */- { 40, 7, 12, 0, 0, 18432, 82, }, /* 915 */- { 40, 12, 3, 0, 0, 26624, 96, }, /* 916 */- { 40, 10, 5, 0, 0, 18432, 172, }, /* 917 */- { 40, 21, 12, 0, 0, 18432, 68, }, /* 918 */- { 40, 21, 12, 0, 0, 18432, 106, }, /* 919 */- { 40, 21, 12, 0, 0, 18432, 124, }, /* 920 */- { 69, 6, 12, 0, 0, 18480, 136, }, /* 921 */- { 40, 13, 12, 0, 0, 18432, 138, }, /* 922 */- { 16, 6, 12, 0, 0, 18432, 136, }, /* 923 */- { 105, 7, 12, 0, 0, 18432, 82, }, /* 924 */- { 105, 12, 3, 0, 0, 26624, 130, }, /* 925 */- { 105, 10, 5, 0, 0, 18432, 144, }, /* 926 */- { 105, 13, 12, 0, 0, 18432, 138, }, /* 927 */- { 105, 21, 12, 0, 0, 18432, 68, }, /* 928 */- { 105, 21, 12, 0, 0, 18432, 124, }, /* 929 */- { 107, 7, 12, 0, 0, 18432, 82, }, /* 930 */- { 107, 12, 3, 0, 0, 26624, 130, }, /* 931 */- { 107, 7, 12, 0, 0, 18432, 156, }, /* 932 */- { 107, 12, 3, 0, 0, 26624, 96, }, /* 933 */- { 107, 7, 12, 0, 0, 18432, 294, }, /* 934 */- { 107, 6, 12, 0, 0, 18432, 136, }, /* 935 */- { 107, 21, 12, 0, 0, 18432, 68, }, /* 936 */- { 107, 21, 12, 0, 0, 18432, 106, }, /* 937 */- { 113, 7, 12, 0, 0, 18432, 82, }, /* 938 */- { 113, 10, 5, 0, 0, 18432, 144, }, /* 939 */- { 113, 12, 3, 0, 0, 26624, 130, }, /* 940 */- { 113, 21, 12, 0, 0, 18432, 124, }, /* 941 */- { 113, 6, 12, 0, 0, 18432, 136, }, /* 942 */- { 113, 12, 3, 0, 0, 26624, 146, }, /* 943 */- { 0, 5, 12, 0, -928, 18432, 76, }, /* 944 */- { 0, 6, 12, 0, 0, 18432, 92, }, /* 945 */- { 76, 5, 12, 0, -38864, 18432, 70, }, /* 946 */- { 113, 10, 5, 0, 0, 18432, 160, }, /* 947 */- { 113, 13, 12, 0, 0, 18432, 138, }, /* 948 */- { 18, 7, 9, 0, 0, 18432, 82, }, /* 949 */- { 18, 7, 10, 0, 0, 18432, 82, }, /* 950 */- { 68, 4, 12, 0, 0, 18432, 0, }, /* 951 */- { 68, 3, 12, 0, 0, 18432, 0, }, /* 952 */- { 23, 7, 12, 0, 0, 18432, 284, }, /* 953 */- { 71, 25, 12, 0, 0, 12288, 118, }, /* 954 */- { 3, 7, 12, 0, 0, 0, 296, }, /* 955 */- { 69, 18, 12, 0, 0, 28705, 54, }, /* 956 */- { 69, 22, 12, 0, 0, 28705, 54, }, /* 957 */- { 68, 2, 12, 0, 0, 6144, 298, }, /* 958 */- { 3, 7, 12, 0, 0, 39, 82, }, /* 959 */- { 3, 26, 12, 0, 0, 28711, 68, }, /* 960 */- { 84, 12, 3, 0, 0, 26624, 178, }, /* 961 */- { 84, 12, 3, 0, 0, 26624, 300, }, /* 962 */- { 69, 21, 12, 0, 0, 28672, 68, }, /* 963 */- { 69, 21, 12, 0, 0, 28672, 122, }, /* 964 */- { 69, 22, 12, 0, 0, 28672, 68, }, /* 965 */- { 69, 18, 12, 0, 0, 28672, 68, }, /* 966 */- { 69, 17, 12, 0, 0, 28672, 126, }, /* 967 */- { 69, 22, 12, 0, 0, 28672, 302, }, /* 968 */- { 69, 18, 12, 0, 0, 28672, 302, }, /* 969 */- { 69, 21, 12, 0, 0, 8192, 106, }, /* 970 */- { 69, 21, 12, 0, 0, 8192, 304, }, /* 971 */- { 69, 21, 12, 0, 0, 8192, 306, }, /* 972 */- { 69, 21, 12, 0, 0, 28672, 124, }, /* 973 */- { 69, 22, 12, 0, 0, 28672, 158, }, /* 974 */- { 69, 18, 12, 0, 0, 28672, 158, }, /* 975 */- { 69, 21, 12, 0, 0, 14336, 68, }, /* 976 */- { 69, 21, 12, 0, 0, 28672, 118, }, /* 977 */- { 69, 17, 12, 0, 0, 12288, 224, }, /* 978 */- { 69, 25, 12, 0, 0, 28672, 226, }, /* 979 */- { 69, 21, 12, 0, 0, 28672, 302, }, /* 980 */- { 69, 21, 12, 0, 0, 28672, 308, }, /* 981 */- { 69, 17, 12, 0, 0, 12288, 126, }, /* 982 */- { 69, 21, 12, 0, 0, 8192, 68, }, /* 983 */- { 69, 13, 12, 0, 0, 10240, 310, }, /* 984 */- { 0, 9, 12, 0, 32, 18432, 312, }, /* 985 */- { 69, 24, 12, 0, 0, 28672, 314, }, /* 986 */- { 0, 5, 12, 0, -32, 18432, 316, }, /* 987 */- { 69, 21, 12, 0, 0, 28825, 124, }, /* 988 */- { 69, 22, 12, 0, 0, 28825, 318, }, /* 989 */- { 69, 18, 12, 0, 0, 28825, 318, }, /* 990 */- { 69, 21, 12, 0, 0, 28825, 106, }, /* 991 */- { 69, 6, 3, 0, 0, 18525, 320, }, /* 992 */- { 69, 1, 2, 0, 0, 28672, 322, }, /* 993 */- { 31, 7, 12, 0, 0, 18432, 82, }, /* 994 */- { 69, 21, 12, 0, 0, 18552, 68, }, /* 995 */- { 69, 21, 12, 0, 0, 28792, 68, }, /* 996 */- { 69, 21, 12, 0, 0, 18483, 68, }, /* 997 */- { 69, 15, 12, 0, 0, 18555, 68, }, /* 998 */- { 69, 26, 12, 0, 0, 18483, 68, }, /* 999 */- { 1, 14, 12, 0, 0, 28672, 82, }, /* 1000 */- { 1, 15, 12, 0, 0, 28672, 68, }, /* 1001 */- { 1, 26, 12, 0, 0, 28672, 68, }, /* 1002 */- { 1, 26, 12, 0, 0, 18432, 68, }, /* 1003 */- { 102, 7, 12, 0, 0, 18432, 82, }, /* 1004 */- { 103, 7, 12, 0, 0, 18432, 82, }, /* 1005 */- { 84, 12, 3, 0, 0, 26651, 96, }, /* 1006 */- { 69, 15, 12, 0, 0, 10267, 68, }, /* 1007 */- { 81, 7, 12, 0, 0, 18432, 82, }, /* 1008 */- { 81, 15, 12, 0, 0, 18432, 68, }, /* 1009 */- { 82, 7, 12, 0, 0, 18432, 82, }, /* 1010 */- { 82, 14, 12, 0, 0, 18432, 82, }, /* 1011 */- { 53, 7, 12, 0, 0, 18432, 82, }, /* 1012 */- { 53, 12, 3, 0, 0, 26624, 130, }, /* 1013 */- { 85, 7, 12, 0, 0, 18432, 82, }, /* 1014 */- { 85, 21, 12, 0, 0, 18432, 106, }, /* 1015 */- { 91, 7, 12, 0, 0, 18432, 82, }, /* 1016 */- { 91, 21, 12, 0, 0, 18432, 106, }, /* 1017 */- { 91, 14, 12, 0, 0, 18432, 82, }, /* 1018 */- { 83, 9, 12, 0, 40, 18432, 74, }, /* 1019 */- { 83, 5, 12, 0, -40, 18432, 76, }, /* 1020 */- { 86, 7, 12, 0, 0, 18432, 82, }, /* 1021 */- { 87, 7, 12, 0, 0, 18432, 82, }, /* 1022 */- { 87, 13, 12, 0, 0, 18432, 138, }, /* 1023 */- { 145, 9, 12, 0, 40, 18432, 74, }, /* 1024 */- { 145, 5, 12, 0, -40, 18432, 76, }, /* 1025 */- { 127, 7, 12, 0, 0, 18432, 82, }, /* 1026 */- { 125, 7, 12, 0, 0, 18432, 82, }, /* 1027 */- { 125, 21, 12, 0, 0, 18432, 68, }, /* 1028 */- { 161, 9, 12, 0, 39, 18432, 74, }, /* 1029 */- { 161, 5, 12, 0, -39, 18432, 76, }, /* 1030 */- { 49, 7, 12, 0, 0, 18432, 82, }, /* 1031 */- { 0, 6, 12, 0, 0, 18432, 94, }, /* 1032 */- { 32, 7, 12, 0, 0, 34816, 82, }, /* 1033 */- { 114, 7, 12, 0, 0, 34816, 82, }, /* 1034 */- { 114, 21, 12, 0, 0, 34816, 106, }, /* 1035 */- { 114, 15, 12, 0, 0, 34816, 68, }, /* 1036 */- { 133, 7, 12, 0, 0, 34816, 82, }, /* 1037 */- { 133, 26, 12, 0, 0, 34816, 68, }, /* 1038 */- { 133, 15, 12, 0, 0, 34816, 68, }, /* 1039 */- { 132, 7, 12, 0, 0, 34816, 82, }, /* 1040 */- { 132, 15, 12, 0, 0, 34816, 68, }, /* 1041 */- { 139, 7, 12, 0, 0, 34816, 82, }, /* 1042 */- { 139, 15, 12, 0, 0, 34816, 68, }, /* 1043 */- { 95, 7, 12, 0, 0, 34816, 82, }, /* 1044 */- { 95, 15, 12, 0, 0, 34816, 68, }, /* 1045 */- { 95, 21, 12, 0, 0, 28672, 106, }, /* 1046 */- { 104, 7, 12, 0, 0, 34816, 82, }, /* 1047 */- { 104, 21, 12, 0, 0, 34816, 68, }, /* 1048 */- { 122, 7, 12, 0, 0, 34816, 82, }, /* 1049 */- { 121, 7, 12, 0, 0, 34816, 82, }, /* 1050 */- { 121, 15, 12, 0, 0, 34816, 68, }, /* 1051 */- { 92, 7, 12, 0, 0, 34816, 82, }, /* 1052 */- { 92, 12, 3, 0, 0, 26624, 130, }, /* 1053 */- { 92, 12, 3, 0, 0, 26624, 102, }, /* 1054 */- { 92, 12, 3, 0, 0, 26624, 182, }, /* 1055 */- { 92, 15, 12, 0, 0, 34816, 68, }, /* 1056 */- { 92, 21, 12, 0, 0, 34816, 68, }, /* 1057 */- { 92, 21, 12, 0, 0, 34816, 124, }, /* 1058 */- { 115, 7, 12, 0, 0, 34816, 82, }, /* 1059 */- { 115, 15, 12, 0, 0, 34816, 68, }, /* 1060 */- { 115, 21, 12, 0, 0, 34816, 68, }, /* 1061 */- { 131, 7, 12, 0, 0, 34816, 82, }, /* 1062 */- { 131, 15, 12, 0, 0, 34816, 68, }, /* 1063 */- { 51, 7, 12, 0, 0, 34816, 82, }, /* 1064 */- { 51, 26, 12, 0, 0, 34816, 68, }, /* 1065 */- { 51, 12, 3, 0, 0, 26624, 96, }, /* 1066 */- { 51, 15, 12, 0, 0, 34816, 68, }, /* 1067 */- { 51, 21, 12, 0, 0, 34816, 106, }, /* 1068 */- { 51, 21, 12, 0, 0, 34918, 106, }, /* 1069 */- { 51, 21, 12, 0, 0, 34816, 68, }, /* 1070 */- { 108, 7, 12, 0, 0, 34816, 82, }, /* 1071 */- { 108, 21, 12, 0, 0, 28672, 68, }, /* 1072 */- { 108, 21, 12, 0, 0, 28672, 106, }, /* 1073 */- { 116, 7, 12, 0, 0, 34816, 82, }, /* 1074 */- { 116, 15, 12, 0, 0, 34816, 68, }, /* 1075 */- { 117, 7, 12, 0, 0, 34816, 82, }, /* 1076 */- { 117, 15, 12, 0, 0, 34816, 68, }, /* 1077 */- { 54, 7, 12, 0, 0, 34816, 82, }, /* 1078 */- { 54, 21, 12, 0, 0, 34816, 106, }, /* 1079 */- { 54, 15, 12, 0, 0, 34816, 68, }, /* 1080 */- { 118, 7, 12, 0, 0, 34816, 82, }, /* 1081 */- { 140, 9, 12, 0, 64, 34816, 74, }, /* 1082 */- { 140, 5, 12, 0, -64, 34816, 76, }, /* 1083 */- { 140, 15, 12, 0, 0, 34816, 68, }, /* 1084 */- { 62, 7, 12, 0, 0, 0, 82, }, /* 1085 */- { 62, 7, 12, 0, 0, 0, 294, }, /* 1086 */- { 62, 12, 3, 0, 0, 26624, 128, }, /* 1087 */- { 62, 13, 12, 0, 0, 2048, 138, }, /* 1088 */- { 3, 15, 12, 0, 0, 2048, 68, }, /* 1089 */- { 65, 7, 12, 0, 0, 34816, 82, }, /* 1090 */- { 65, 12, 3, 0, 0, 26624, 130, }, /* 1091 */- { 65, 17, 12, 0, 0, 34816, 126, }, /* 1092 */- { 152, 7, 12, 0, 0, 34816, 82, }, /* 1093 */- { 152, 15, 12, 0, 0, 34816, 68, }, /* 1094 */- { 63, 7, 12, 0, 0, 0, 82, }, /* 1095 */- { 63, 12, 3, 0, 0, 26624, 96, }, /* 1096 */- { 63, 15, 12, 0, 0, 0, 68, }, /* 1097 */- { 63, 21, 12, 0, 0, 0, 124, }, /* 1098 */- { 67, 7, 12, 0, 0, 34816, 82, }, /* 1099 */- { 67, 12, 3, 0, 0, 26624, 96, }, /* 1100 */- { 67, 21, 12, 0, 0, 34816, 124, }, /* 1101 */- { 156, 7, 12, 0, 0, 34816, 82, }, /* 1102 */- { 156, 15, 12, 0, 0, 34816, 68, }, /* 1103 */- { 153, 7, 12, 0, 0, 34816, 82, }, /* 1104 */- { 120, 10, 5, 0, 0, 18432, 144, }, /* 1105 */- { 120, 12, 3, 0, 0, 26624, 130, }, /* 1106 */- { 120, 7, 12, 0, 0, 18432, 82, }, /* 1107 */- { 120, 12, 3, 0, 0, 26624, 146, }, /* 1108 */- { 120, 21, 12, 0, 0, 18432, 124, }, /* 1109 */- { 120, 21, 12, 0, 0, 18432, 106, }, /* 1110 */- { 120, 15, 12, 0, 0, 28672, 68, }, /* 1111 */- { 120, 13, 12, 0, 0, 18432, 138, }, /* 1112 */- { 120, 12, 3, 0, 0, 26624, 182, }, /* 1113 */- { 41, 12, 3, 0, 0, 26624, 102, }, /* 1114 */- { 41, 10, 5, 0, 0, 18432, 144, }, /* 1115 */- { 41, 7, 12, 0, 0, 18432, 82, }, /* 1116 */- { 41, 12, 3, 0, 0, 26624, 130, }, /* 1117 */- { 41, 12, 3, 0, 0, 26624, 146, }, /* 1118 */- { 41, 12, 3, 0, 0, 26624, 96, }, /* 1119 */- { 41, 21, 12, 0, 0, 18432, 68, }, /* 1120 */- { 41, 1, 4, 0, 0, 18432, 132, }, /* 1121 */- { 41, 21, 12, 0, 0, 18432, 124, }, /* 1122 */- { 124, 7, 12, 0, 0, 18432, 82, }, /* 1123 */- { 124, 13, 12, 0, 0, 18432, 138, }, /* 1124 */- { 43, 12, 3, 0, 0, 26624, 130, }, /* 1125 */- { 43, 7, 12, 0, 0, 18432, 82, }, /* 1126 */- { 43, 10, 5, 0, 0, 18432, 144, }, /* 1127 */- { 43, 12, 3, 0, 0, 26624, 146, }, /* 1128 */- { 43, 13, 12, 0, 0, 18432, 138, }, /* 1129 */- { 43, 21, 12, 0, 0, 18432, 68, }, /* 1130 */- { 43, 21, 12, 0, 0, 18432, 124, }, /* 1131 */- { 50, 7, 12, 0, 0, 18432, 82, }, /* 1132 */- { 50, 12, 3, 0, 0, 26624, 96, }, /* 1133 */- { 50, 21, 12, 0, 0, 18432, 68, }, /* 1134 */- { 44, 12, 3, 0, 0, 26624, 130, }, /* 1135 */- { 44, 10, 5, 0, 0, 18432, 144, }, /* 1136 */- { 44, 7, 12, 0, 0, 18432, 82, }, /* 1137 */- { 44, 10, 5, 0, 0, 18432, 172, }, /* 1138 */- { 44, 7, 4, 0, 0, 18432, 82, }, /* 1139 */- { 44, 21, 12, 0, 0, 18432, 124, }, /* 1140 */- { 44, 21, 12, 0, 0, 18432, 68, }, /* 1141 */- { 44, 12, 3, 0, 0, 26624, 102, }, /* 1142 */- { 44, 12, 3, 0, 0, 26624, 96, }, /* 1143 */- { 44, 13, 12, 0, 0, 18432, 138, }, /* 1144 */- { 15, 15, 12, 0, 0, 18432, 68, }, /* 1145 */- { 48, 7, 12, 0, 0, 18432, 82, }, /* 1146 */- { 48, 10, 5, 0, 0, 18432, 144, }, /* 1147 */- { 48, 12, 3, 0, 0, 26624, 130, }, /* 1148 */- { 48, 10, 5, 0, 0, 18432, 172, }, /* 1149 */- { 48, 12, 3, 0, 0, 26624, 96, }, /* 1150 */- { 48, 21, 12, 0, 0, 18432, 124, }, /* 1151 */- { 48, 21, 12, 0, 0, 18432, 106, }, /* 1152 */- { 48, 21, 12, 0, 0, 18432, 68, }, /* 1153 */- { 57, 7, 12, 0, 0, 18432, 82, }, /* 1154 */- { 57, 21, 12, 0, 0, 18432, 124, }, /* 1155 */- { 55, 7, 12, 0, 0, 18432, 82, }, /* 1156 */- { 55, 12, 3, 0, 0, 26624, 130, }, /* 1157 */- { 55, 10, 5, 0, 0, 18432, 144, }, /* 1158 */- { 55, 12, 3, 0, 0, 26624, 96, }, /* 1159 */- { 55, 12, 3, 0, 0, 26624, 146, }, /* 1160 */- { 55, 13, 12, 0, 0, 18432, 138, }, /* 1161 */- { 47, 12, 3, 0, 0, 26624, 130, }, /* 1162 */- { 47, 12, 3, 0, 0, 26705, 130, }, /* 1163 */- { 47, 10, 5, 0, 0, 18432, 144, }, /* 1164 */- { 47, 10, 5, 0, 0, 18513, 144, }, /* 1165 */- { 47, 7, 12, 0, 0, 18432, 82, }, /* 1166 */- { 84, 12, 3, 0, 0, 26705, 102, }, /* 1167 */- { 47, 12, 3, 0, 0, 26705, 96, }, /* 1168 */- { 47, 10, 3, 0, 0, 18432, 148, }, /* 1169 */- { 47, 10, 5, 0, 0, 18432, 172, }, /* 1170 */- { 47, 7, 12, 0, 0, 18432, 324, }, /* 1171 */- { 47, 12, 3, 0, 0, 26624, 96, }, /* 1172 */- { 144, 7, 12, 0, 0, 18432, 82, }, /* 1173 */- { 144, 10, 5, 0, 0, 18432, 144, }, /* 1174 */- { 144, 12, 3, 0, 0, 26624, 130, }, /* 1175 */- { 144, 12, 3, 0, 0, 26624, 146, }, /* 1176 */- { 144, 12, 3, 0, 0, 26624, 96, }, /* 1177 */- { 144, 21, 12, 0, 0, 18432, 124, }, /* 1178 */- { 144, 21, 12, 0, 0, 18432, 106, }, /* 1179 */- { 144, 21, 12, 0, 0, 18432, 68, }, /* 1180 */- { 144, 13, 12, 0, 0, 18432, 138, }, /* 1181 */- { 144, 12, 3, 0, 0, 26624, 102, }, /* 1182 */- { 56, 7, 12, 0, 0, 18432, 82, }, /* 1183 */- { 56, 10, 3, 0, 0, 18432, 148, }, /* 1184 */- { 56, 10, 5, 0, 0, 18432, 144, }, /* 1185 */- { 56, 12, 3, 0, 0, 26624, 130, }, /* 1186 */- { 56, 12, 3, 0, 0, 26624, 146, }, /* 1187 */- { 56, 12, 3, 0, 0, 26624, 96, }, /* 1188 */- { 56, 21, 12, 0, 0, 18432, 68, }, /* 1189 */- { 56, 13, 12, 0, 0, 18432, 138, }, /* 1190 */- { 135, 7, 12, 0, 0, 18432, 82, }, /* 1191 */- { 135, 10, 3, 0, 0, 18432, 148, }, /* 1192 */- { 135, 10, 5, 0, 0, 18432, 144, }, /* 1193 */- { 135, 12, 3, 0, 0, 26624, 130, }, /* 1194 */- { 135, 12, 3, 0, 0, 26624, 146, }, /* 1195 */- { 135, 12, 3, 0, 0, 26624, 96, }, /* 1196 */- { 135, 21, 12, 0, 0, 18432, 68, }, /* 1197 */- { 135, 21, 12, 0, 0, 18432, 124, }, /* 1198 */- { 135, 21, 12, 0, 0, 18432, 106, }, /* 1199 */- { 135, 21, 12, 0, 0, 18432, 176, }, /* 1200 */- { 52, 7, 12, 0, 0, 18432, 82, }, /* 1201 */- { 52, 10, 5, 0, 0, 18432, 144, }, /* 1202 */- { 52, 12, 3, 0, 0, 26624, 130, }, /* 1203 */- { 52, 12, 3, 0, 0, 26624, 146, }, /* 1204 */- { 52, 21, 12, 0, 0, 18432, 124, }, /* 1205 */- { 52, 21, 12, 0, 0, 18432, 68, }, /* 1206 */- { 52, 13, 12, 0, 0, 18432, 138, }, /* 1207 */- { 45, 7, 12, 0, 0, 18432, 82, }, /* 1208 */- { 45, 12, 3, 0, 0, 26624, 130, }, /* 1209 */- { 45, 10, 5, 0, 0, 18432, 144, }, /* 1210 */- { 45, 10, 5, 0, 0, 18432, 172, }, /* 1211 */- { 45, 12, 3, 0, 0, 26624, 96, }, /* 1212 */- { 45, 21, 12, 0, 0, 18432, 68, }, /* 1213 */- { 45, 13, 12, 0, 0, 18432, 138, }, /* 1214 */- { 137, 7, 12, 0, 0, 18432, 82, }, /* 1215 */- { 137, 12, 3, 0, 0, 26624, 130, }, /* 1216 */- { 137, 10, 12, 0, 0, 18432, 144, }, /* 1217 */- { 137, 10, 5, 0, 0, 18432, 144, }, /* 1218 */- { 137, 12, 3, 0, 0, 26624, 146, }, /* 1219 */- { 137, 13, 12, 0, 0, 18432, 138, }, /* 1220 */- { 137, 15, 12, 0, 0, 18432, 68, }, /* 1221 */- { 137, 21, 12, 0, 0, 18432, 124, }, /* 1222 */- { 137, 26, 12, 0, 0, 18432, 68, }, /* 1223 */- { 60, 7, 12, 0, 0, 18432, 82, }, /* 1224 */- { 60, 10, 5, 0, 0, 18432, 144, }, /* 1225 */- { 60, 12, 3, 0, 0, 26624, 130, }, /* 1226 */- { 60, 12, 3, 0, 0, 26624, 146, }, /* 1227 */- { 60, 12, 3, 0, 0, 26624, 96, }, /* 1228 */- { 60, 21, 12, 0, 0, 18432, 68, }, /* 1229 */- { 136, 9, 12, 0, 32, 18432, 74, }, /* 1230 */- { 136, 5, 12, 0, -32, 18432, 76, }, /* 1231 */- { 136, 13, 12, 0, 0, 18432, 138, }, /* 1232 */- { 136, 15, 12, 0, 0, 18432, 68, }, /* 1233 */- { 136, 7, 12, 0, 0, 18432, 82, }, /* 1234 */- { 157, 7, 12, 0, 0, 18432, 82, }, /* 1235 */- { 157, 10, 3, 0, 0, 18432, 148, }, /* 1236 */- { 157, 10, 5, 0, 0, 18432, 144, }, /* 1237 */- { 157, 12, 3, 0, 0, 26624, 130, }, /* 1238 */- { 157, 10, 5, 0, 0, 18432, 172, }, /* 1239 */- { 157, 12, 3, 0, 0, 26624, 146, }, /* 1240 */- { 157, 7, 4, 0, 0, 18432, 82, }, /* 1241 */- { 157, 12, 3, 0, 0, 26624, 96, }, /* 1242 */- { 157, 21, 12, 0, 0, 18432, 124, }, /* 1243 */- { 157, 21, 12, 0, 0, 18432, 68, }, /* 1244 */- { 157, 13, 12, 0, 0, 18432, 138, }, /* 1245 */- { 64, 7, 12, 0, 0, 18432, 82, }, /* 1246 */- { 64, 10, 5, 0, 0, 18432, 144, }, /* 1247 */- { 64, 12, 3, 0, 0, 26624, 130, }, /* 1248 */- { 64, 12, 3, 0, 0, 26624, 146, }, /* 1249 */- { 64, 21, 12, 0, 0, 18432, 68, }, /* 1250 */- { 149, 7, 12, 0, 0, 18432, 82, }, /* 1251 */- { 149, 12, 3, 0, 0, 26624, 130, }, /* 1252 */- { 149, 12, 3, 0, 0, 18432, 130, }, /* 1253 */- { 149, 12, 3, 0, 0, 26624, 102, }, /* 1254 */- { 149, 12, 3, 0, 0, 26624, 146, }, /* 1255 */- { 149, 10, 5, 0, 0, 18432, 144, }, /* 1256 */- { 149, 7, 4, 0, 0, 18432, 82, }, /* 1257 */- { 149, 21, 12, 0, 0, 18432, 68, }, /* 1258 */- { 149, 21, 12, 0, 0, 18432, 124, }, /* 1259 */- { 148, 7, 12, 0, 0, 18432, 82, }, /* 1260 */- { 148, 12, 3, 0, 0, 26624, 130, }, /* 1261 */- { 148, 10, 5, 0, 0, 18432, 144, }, /* 1262 */- { 148, 7, 4, 0, 0, 18432, 82, }, /* 1263 */- { 148, 12, 3, 0, 0, 26624, 326, }, /* 1264 */- { 148, 12, 3, 0, 0, 26624, 146, }, /* 1265 */- { 148, 21, 12, 0, 0, 18432, 68, }, /* 1266 */- { 148, 21, 12, 0, 0, 18432, 124, }, /* 1267 */- { 148, 21, 12, 0, 0, 18432, 106, }, /* 1268 */- { 134, 7, 12, 0, 0, 18432, 82, }, /* 1269 */- { 142, 7, 12, 0, 0, 18432, 82, }, /* 1270 */- { 142, 10, 5, 0, 0, 18432, 144, }, /* 1271 */- { 142, 12, 3, 0, 0, 26624, 130, }, /* 1272 */- { 142, 12, 3, 0, 0, 18432, 146, }, /* 1273 */- { 142, 21, 12, 0, 0, 18432, 124, }, /* 1274 */- { 142, 21, 12, 0, 0, 18432, 106, }, /* 1275 */- { 142, 21, 12, 0, 0, 18432, 68, }, /* 1276 */- { 142, 13, 12, 0, 0, 18432, 138, }, /* 1277 */- { 142, 15, 12, 0, 0, 18432, 68, }, /* 1278 */- { 143, 21, 12, 0, 0, 18432, 68, }, /* 1279 */- { 143, 21, 12, 0, 0, 18432, 106, }, /* 1280 */- { 143, 7, 12, 0, 0, 18432, 82, }, /* 1281 */- { 143, 12, 3, 0, 0, 26624, 130, }, /* 1282 */- { 143, 10, 5, 0, 0, 18432, 144, }, /* 1283 */- { 59, 7, 12, 0, 0, 18432, 82, }, /* 1284 */- { 59, 12, 3, 0, 0, 26624, 130, }, /* 1285 */- { 59, 12, 3, 0, 0, 26624, 96, }, /* 1286 */- { 59, 12, 3, 0, 0, 26624, 146, }, /* 1287 */- { 59, 7, 4, 0, 0, 18432, 82, }, /* 1288 */- { 59, 13, 12, 0, 0, 18432, 138, }, /* 1289 */- { 61, 7, 12, 0, 0, 18432, 82, }, /* 1290 */- { 61, 10, 5, 0, 0, 18432, 144, }, /* 1291 */- { 61, 12, 3, 0, 0, 26624, 130, }, /* 1292 */- { 61, 12, 3, 0, 0, 26624, 146, }, /* 1293 */- { 61, 13, 12, 0, 0, 18432, 138, }, /* 1294 */- { 150, 7, 12, 0, 0, 18432, 82, }, /* 1295 */- { 150, 12, 3, 0, 0, 26624, 130, }, /* 1296 */- { 150, 10, 5, 0, 0, 18432, 144, }, /* 1297 */- { 150, 21, 12, 0, 0, 18432, 124, }, /* 1298 */- { 11, 15, 12, 0, 0, 18432, 68, }, /* 1299 */- { 11, 21, 12, 0, 0, 18432, 68, }, /* 1300 */- { 94, 7, 12, 0, 0, 18432, 82, }, /* 1301 */- { 94, 14, 12, 0, 0, 18432, 82, }, /* 1302 */- { 94, 21, 12, 0, 0, 18432, 106, }, /* 1303 */- { 66, 7, 12, 0, 0, 18432, 82, }, /* 1304 */- { 66, 21, 12, 0, 0, 18432, 68, }, /* 1305 */- { 109, 7, 12, 0, 0, 18432, 82, }, /* 1306 */- { 109, 1, 2, 0, 0, 18432, 322, }, /* 1307 */- { 138, 7, 12, 0, 0, 18432, 82, }, /* 1308 */- { 130, 7, 12, 0, 0, 18432, 82, }, /* 1309 */- { 130, 13, 12, 0, 0, 18432, 138, }, /* 1310 */- { 130, 21, 12, 0, 0, 18432, 124, }, /* 1311 */- { 159, 7, 12, 0, 0, 18432, 82, }, /* 1312 */- { 159, 13, 12, 0, 0, 18432, 138, }, /* 1313 */- { 126, 7, 12, 0, 0, 18432, 82, }, /* 1314 */- { 126, 12, 3, 0, 0, 26624, 96, }, /* 1315 */- { 126, 21, 12, 0, 0, 18432, 124, }, /* 1316 */- { 128, 7, 12, 0, 0, 18432, 82, }, /* 1317 */- { 128, 12, 3, 0, 0, 26624, 96, }, /* 1318 */- { 128, 21, 12, 0, 0, 18432, 124, }, /* 1319 */- { 128, 21, 12, 0, 0, 18432, 106, }, /* 1320 */- { 128, 21, 12, 0, 0, 18432, 68, }, /* 1321 */- { 128, 26, 12, 0, 0, 18432, 68, }, /* 1322 */- { 128, 6, 12, 0, 0, 18432, 142, }, /* 1323 */- { 128, 6, 12, 0, 0, 18432, 136, }, /* 1324 */- { 128, 13, 12, 0, 0, 18432, 138, }, /* 1325 */- { 128, 15, 12, 0, 0, 18432, 68, }, /* 1326 */- { 151, 9, 12, 0, 32, 18432, 74, }, /* 1327 */- { 151, 5, 12, 0, -32, 18432, 76, }, /* 1328 */- { 151, 15, 12, 0, 0, 18432, 68, }, /* 1329 */- { 151, 21, 12, 0, 0, 18432, 106, }, /* 1330 */- { 151, 21, 12, 0, 0, 18432, 124, }, /* 1331 */- { 151, 21, 12, 0, 0, 18432, 68, }, /* 1332 */- { 123, 7, 12, 0, 0, 18432, 82, }, /* 1333 */- { 123, 12, 3, 0, 0, 26624, 130, }, /* 1334 */- { 123, 10, 5, 0, 0, 18432, 144, }, /* 1335 */- { 123, 12, 3, 0, 0, 26624, 128, }, /* 1336 */- { 123, 6, 12, 0, 0, 18432, 92, }, /* 1337 */- { 146, 6, 12, 0, 0, 18432, 136, }, /* 1338 */- { 147, 6, 12, 0, 0, 18432, 136, }, /* 1339 */- { 23, 21, 12, 0, 0, 28672, 68, }, /* 1340 */- { 158, 12, 3, 0, 0, 26624, 328, }, /* 1341 */- { 23, 10, 5, 0, 0, 18432, 164, }, /* 1342 */- { 146, 7, 12, 0, 0, 18432, 284, }, /* 1343 */- { 158, 7, 12, 0, 0, 18432, 284, }, /* 1344 */- { 21, 6, 12, 0, 0, 18432, 92, }, /* 1345 */- { 147, 7, 12, 0, 0, 18432, 284, }, /* 1346 */- { 46, 7, 12, 0, 0, 18432, 82, }, /* 1347 */- { 46, 26, 12, 0, 0, 18432, 68, }, /* 1348 */- { 46, 12, 3, 0, 0, 26624, 102, }, /* 1349 */- { 46, 12, 3, 0, 0, 26624, 130, }, /* 1350 */- { 46, 21, 12, 0, 0, 18432, 124, }, /* 1351 */- { 69, 1, 2, 0, 0, 6153, 66, }, /* 1352 */- { 69, 10, 3, 0, 0, 18432, 330, }, /* 1353 */- { 69, 10, 5, 0, 0, 18432, 138, }, /* 1354 */- { 69, 10, 5, 0, 0, 18432, 160, }, /* 1355 */- { 69, 10, 3, 0, 0, 18432, 286, }, /* 1356 */- { 1, 12, 3, 0, 0, 26624, 102, }, /* 1357 */- { 69, 25, 12, 0, 0, 18432, 118, }, /* 1358 */- { 69, 13, 12, 0, 0, 10240, 214, }, /* 1359 */- { 141, 26, 12, 0, 0, 18432, 68, }, /* 1360 */- { 141, 12, 3, 0, 0, 26624, 102, }, /* 1361 */- { 141, 21, 12, 0, 0, 18432, 106, }, /* 1362 */- { 141, 21, 12, 0, 0, 18432, 124, }, /* 1363 */- { 141, 21, 12, 0, 0, 18432, 68, }, /* 1364 */- { 35, 12, 3, 0, 0, 26624, 130, }, /* 1365 */- { 154, 7, 12, 0, 0, 18432, 82, }, /* 1366 */- { 154, 12, 3, 0, 0, 26624, 96, }, /* 1367 */- { 154, 6, 12, 0, 0, 18432, 142, }, /* 1368 */- { 154, 6, 12, 0, 0, 18432, 136, }, /* 1369 */- { 154, 13, 12, 0, 0, 18432, 138, }, /* 1370 */- { 154, 26, 12, 0, 0, 18432, 68, }, /* 1371 */- { 160, 7, 12, 0, 0, 18432, 82, }, /* 1372 */- { 160, 12, 3, 0, 0, 26624, 96, }, /* 1373 */- { 155, 7, 12, 0, 0, 18432, 82, }, /* 1374 */- { 155, 12, 3, 0, 0, 26624, 96, }, /* 1375 */- { 155, 13, 12, 0, 0, 18432, 138, }, /* 1376 */- { 155, 23, 12, 0, 0, 14336, 68, }, /* 1377 */- { 129, 7, 12, 0, 0, 34816, 82, }, /* 1378 */- { 129, 15, 12, 0, 0, 34816, 68, }, /* 1379 */- { 129, 12, 3, 0, 0, 26624, 96, }, /* 1380 */- { 58, 9, 12, 0, 34, 34816, 74, }, /* 1381 */- { 58, 5, 12, 0, -34, 34816, 76, }, /* 1382 */- { 58, 12, 3, 0, 0, 26624, 150, }, /* 1383 */- { 58, 12, 3, 0, 0, 26624, 130, }, /* 1384 */- { 58, 12, 3, 0, 0, 26624, 96, }, /* 1385 */- { 58, 6, 12, 0, 0, 34816, 142, }, /* 1386 */- { 58, 13, 12, 0, 0, 34816, 138, }, /* 1387 */- { 58, 21, 12, 0, 0, 34816, 68, }, /* 1388 */- { 69, 15, 12, 0, 0, 0, 68, }, /* 1389 */- { 69, 26, 12, 0, 0, 0, 68, }, /* 1390 */- { 69, 23, 12, 0, 0, 0, 68, }, /* 1391 */- { 3, 7, 12, 0, 0, 0, 240, }, /* 1392 */- { 69, 26, 14, 0, 0, 28672, 332, }, /* 1393 */- { 69, 26, 14, 0, 0, 28672, 334, }, /* 1394 */- { 68, 2, 14, 0, 0, 18432, 336, }, /* 1395 */- { 69, 26, 12, 0, 0, 18432, 338, }, /* 1396 */- { 69, 26, 14, 0, 0, 18432, 340, }, /* 1397 */- { 69, 26, 14, 0, 0, 18432, 334, }, /* 1398 */- { 69, 26, 11, 0, 0, 18432, 342, }, /* 1399 */- { 20, 26, 12, 0, 0, 18432, 68, }, /* 1400 */- { 69, 26, 14, 0, 0, 18432, 236, }, /* 1401 */- { 69, 26, 14, 0, 0, 18447, 334, }, /* 1402 */- { 69, 26, 14, 0, 0, 28672, 344, }, /* 1403 */- { 69, 26, 14, 0, 0, 28672, 346, }, /* 1404 */- { 69, 24, 3, 0, 0, 28672, 348, }, /* 1405 */- { 69, 26, 14, 0, 0, 28672, 350, }, /* 1406 */- { 69, 13, 12, 0, 0, 10240, 138, }, /* 1407 */- { 69, 1, 3, 0, 0, 6144, 352, }, /* 1408 */-};--const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* U+0000 */- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 42, 43, 44, 45, /* U+1000 */- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, /* U+1800 */- 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, /* U+2000 */- 78, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, /* U+2800 */- 93, 94, 95, 96, 97, 98, 99,100,101,101,101,101,101,101,101,101, /* U+3000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+3800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+4000 */-101,101,101,101,101,101,101,101,101,101,101,102,101,101,101,101, /* U+4800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+5000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+5800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+6000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+6800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+7000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+7800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+8000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+8800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+9000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+9800 */-103,104,104,104,104,104,104,104,104,105,106,106,107,108,109,110, /* U+A000 */-111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,119, /* U+A800 */-120,121,122,123,124,125,119,120,121,122,123,124,125,119,120,121, /* U+B000 */-122,123,124,125,119,120,121,122,123,124,125,119,120,121,122,123, /* U+B800 */-124,125,119,120,121,122,123,124,125,119,120,121,122,123,124,125, /* U+C000 */-119,120,121,122,123,124,125,119,120,121,122,123,124,125,119,120, /* U+C800 */-121,122,123,124,125,119,120,121,122,123,124,125,119,120,121,126, /* U+D000 */-127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, /* U+D800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+E000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+E800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F000 */-128,128,129,129,130,131,132,133,134,135,136,137,138,139,140,141, /* U+F800 */-142,143,144,145,146,147,148,149,150,151,152,153,154,154,155,156, /* U+10000 */-157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172, /* U+10800 */-173,174,175,176,177,178,179,146,180,181,146,182,183,184,185,146, /* U+11000 */-186,187,188,189,190,191,146,146,192,193,194,195,146,196,146,197, /* U+11800 */-198,198,198,198,198,198,198,199,200,198,201,146,146,146,146,146, /* U+12000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,202, /* U+12800 */-203,203,203,203,203,203,203,203,204,146,146,146,146,146,146,146, /* U+13000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+13800 */-146,146,146,146,146,146,146,146,205,205,205,205,206,146,146,146, /* U+14000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+14800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+15000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+15800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+16000 */-207,207,207,207,208,209,210,211,146,146,146,146,212,213,214,215, /* U+16800 */-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* U+17000 */-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* U+17800 */-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,217, /* U+18000 */-216,216,216,216,216,216,218,218,218,219,220,146,146,146,146,146, /* U+18800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+19000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+19800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+1A000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,221, /* U+1A800 */-222,223,224,225,225,226,146,146,146,146,146,146,146,146,146,146, /* U+1B000 */-146,146,146,146,146,146,146,146,227,228,146,146,146,146,146,146, /* U+1B800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+1C000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,229,230, /* U+1C800 */-231,232,233,234,235,236,237,146,238,239,240,241,242,243,244,245, /* U+1D000 */-246,246,246,246,247,248,146,146,146,146,146,146,146,146,249,146, /* U+1D800 */-250,146,251,146,146,252,146,146,146,146,146,146,146,146,146,253, /* U+1E000 */-254,255,256,168,168,168,168,168,257,258,259,168,260,261,168,168, /* U+1E800 */-262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277, /* U+1F000 */-278,279,280,281,282,283,284,285,267,267,267,267,267,267,267,286, /* U+1F800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+20000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+20800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+21000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+21800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+22000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+22800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+23000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+23800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+24000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+24800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+25000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+25800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+26000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+26800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+27000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+27800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+28000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+28800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+29000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+29800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,287,101,101, /* U+2A000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2A800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,288,101, /* U+2B000 */-289,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2B800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2C000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,290,101,101, /* U+2C800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2D000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2D800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2E000 */-101,101,101,101,101,101,101,291,146,146,146,146,146,146,146,146, /* U+2E800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+2F000 */-129,129,129,129,292,146,146,146,146,146,146,146,146,146,146,293, /* U+2F800 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+30000 */-101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+30800 */-101,101,101,101,101,101,294,146,146,146,146,146,146,146,146,146, /* U+31000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+31800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+32000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+32800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+33000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+33800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+34000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+34800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+35000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+35800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+36000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+36800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+37000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+37800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+38000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+38800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+39000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+39800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3A000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3A800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3B000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3B800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3C000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3C800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3D000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3D800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3E000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3E800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3F000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+3F800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+40000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+40800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+41000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+41800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+42000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+42800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+43000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+43800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+44000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+44800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+45000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+45800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+46000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+46800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+47000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+47800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+48000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+48800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+49000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+49800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4A000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4A800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4B000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4B800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4C000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4C800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4D000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4D800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4E000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4E800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4F000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+4F800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+50000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+50800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+51000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+51800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+52000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+52800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+53000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+53800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+54000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+54800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+55000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+55800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+56000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+56800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+57000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+57800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+58000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+58800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+59000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+59800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5A000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5A800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5B000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5B800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5C000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5C800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5D000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5D800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5E000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5E800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5F000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+5F800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+60000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+60800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+61000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+61800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+62000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+62800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+63000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+63800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+64000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+64800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+65000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+65800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+66000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+66800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+67000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+67800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+68000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+68800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+69000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+69800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6A000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6A800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6B000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6B800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6C000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6C800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6D000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6D800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6E000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6E800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6F000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+6F800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+70000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+70800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+71000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+71800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+72000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+72800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+73000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+73800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+74000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+74800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+75000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+75800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+76000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+76800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+77000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+77800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+78000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+78800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+79000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+79800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7A000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7A800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7B000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7B800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7C000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7C800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7D000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7D800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7E000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7E800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7F000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+7F800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+80000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+80800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+81000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+81800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+82000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+82800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+83000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+83800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+84000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+84800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+85000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+85800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+86000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+86800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+87000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+87800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+88000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+88800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+89000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+89800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8A000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8A800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8B000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8B800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8C000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8C800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8D000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8D800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8E000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8E800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8F000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+8F800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+90000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+90800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+91000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+91800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+92000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+92800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+93000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+93800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+94000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+94800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+95000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+95800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+96000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+96800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+97000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+97800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+98000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+98800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+99000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+99800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9A000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9A800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9B000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9B800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9C000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9C800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9D000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9D800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9E000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9E800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9F000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+9F800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A0000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A0800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A1000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A1800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A2000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A2800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A3000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A3800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A4000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A4800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A5000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A5800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A6000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A6800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A7000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A7800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A8000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A8800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A9000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A9800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AA000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AA800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AB000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AB800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AC000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AC800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AD000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AD800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AE000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AE800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AF000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+AF800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B0000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B0800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B1000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B1800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B2000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B2800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B3000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B3800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B4000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B4800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B5000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B5800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B6000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B6800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B7000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B7800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B8000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B8800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B9000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B9800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BA000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BA800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BB000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BB800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BC000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BC800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BD000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BD800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BE000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BE800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BF000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+BF800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C0000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C0800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C1000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C1800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C2000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C2800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C3000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C3800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C4000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C4800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C5000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C5800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C6000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C6800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C7000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C7800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C8000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C8800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C9000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C9800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CA000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CA800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CB000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CB800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CC000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CC800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CD000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CD800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CE000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CE800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CF000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+CF800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D0000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D0800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D1000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D1800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D2000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D2800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D3000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D3800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D4000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D4800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D5000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D5800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D6000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D6800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D7000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D7800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D8000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D8800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D9000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D9800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DA000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DA800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DB000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DB800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DC000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DC800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DD000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DD800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DE000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DE800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DF000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+DF800 */-295,296,297,298,296,296,296,296,296,296,296,296,296,296,296,296, /* U+E0000 */-296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296, /* U+E0800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E1000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E1800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E2000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E2800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E3000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E3800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E4000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E4800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E5000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E5800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E6000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E6800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E7000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E7800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E8000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E8800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E9000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E9800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EA000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EA800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EB000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EB800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EC000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EC800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+ED000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+ED800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EE000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EE800 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EF000 */-146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+EF800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F0000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F0800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F1000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F1800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F2000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F2800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F3000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F3800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F4000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F4800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F5000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F5800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F6000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F6800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F7000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F7800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F8000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F8800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F9000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F9800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FA000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FA800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FB000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FB800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FC000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FC800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FD000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FD800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FE000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FE800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FF000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,299, /* U+FF800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+100000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+100800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+101000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+101800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+102000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+102800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+103000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+103800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+104000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+104800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+105000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+105800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+106000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+106800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+107000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+107800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+108000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+108800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+109000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+109800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10A000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10A800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10B000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10B800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10C000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10C800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10D000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10D800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10E000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10E800 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10F000 */-128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,299, /* U+10F800 */-};--const uint16_t PRIV(ucd_stage2)[] = { /* 76800 bytes, block = 128 */--/* block 0 */- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 3, 4, 0, 0,- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 6,- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 25, 26, 27, 26, 8,- 13, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 30, 29, 29, 29, 29,- 29, 29, 29, 31, 29, 29, 29, 29, 29, 29, 29, 15, 13, 16, 32, 33,- 34, 35, 35, 35, 35, 35, 35, 36, 36, 37, 37, 38, 36, 36, 36, 36,- 36, 36, 36, 39, 36, 36, 36, 36, 36, 36, 36, 15, 27, 16, 27, 0,--/* block 1 */- 40, 40, 40, 40, 40, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,- 42, 43, 44, 44, 44, 44, 45, 43, 46, 47, 48, 49, 50, 51, 47, 46,- 52, 53, 54, 54, 46, 55, 43, 56, 46, 54, 48, 57, 58, 58, 58, 43,- 59, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,- 59, 59, 59, 59, 59, 59, 59, 50, 59, 59, 59, 59, 59, 59, 59, 61,- 62, 62, 62, 62, 62, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,- 62, 62, 62, 62, 62, 62, 62, 50, 62, 62, 62, 62, 62, 62, 62, 64,--/* block 2 */- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67,- 68, 69, 65, 66, 65, 66, 65, 66, 70, 65, 66, 65, 66, 65, 66, 65,- 66, 65, 66, 65, 66, 65, 66, 65, 66, 71, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 72, 65, 66, 65, 66, 65, 66, 73,--/* block 3 */- 74, 75, 65, 66, 65, 66, 76, 65, 66, 77, 77, 65, 66, 70, 78, 79,- 80, 65, 66, 77, 81, 82, 83, 84, 65, 66, 85, 70, 83, 86, 87, 88,- 65, 66, 65, 66, 65, 66, 89, 65, 66, 89, 70, 70, 65, 66, 89, 65,- 66, 90, 90, 65, 66, 65, 66, 91, 65, 66, 70, 92, 65, 66, 70, 93,- 92, 92, 92, 92, 94, 95, 96, 97, 98, 99,100,101,102, 65, 66, 65,- 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,103, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 69,104,105,106, 65, 66,107,108, 65, 66, 65, 66, 65, 66, 65, 66,--/* block 4 */- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,-109, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 70, 70, 70, 70, 70, 70,110, 65, 66,111,112,113,-113, 65, 66,114,115,116, 65, 66, 65, 67, 65, 66, 65, 66, 65, 66,-117,118,119,120,121, 70,122,122, 70,123, 70,124,125, 70, 70, 70,-122,126, 70,127, 70,128,129, 70,130,131,129,132,133, 70, 70,131,- 70,134,135, 70, 70,136, 70, 70, 70, 70, 70, 70, 70,137, 70, 70,--/* block 5 */-138, 70,139,138, 70, 70, 70,140,138,141,142,142,143, 70, 70, 70,- 70, 70,144, 70, 92, 70, 70, 70, 70, 70, 70, 70, 70,145,146, 70,- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,-147,147,148,147,147,147,147,147,147,149,149,150,150,150,150,150,-151,151, 46, 46, 46, 46,149,149,149,149,149,149,149,149,149,149,-152,152, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,-147,147,147,147,147, 46, 46, 46, 46, 46,153,153,149, 46,150, 46,- 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,--/* block 6 */-154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,-154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,-154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,-154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,-154,154,155,154,154,156,154,154,154,154,154,154,154,154,154,157,-154,154,154,154,154,154,154,154,158,158,158,158,158,154,154,154,-154,154,154,159,159,159,159,159,159,159,159,159,159,159,159,159,-160,161,160,161,149,162,160,161,163,163,164,165,165,165,166,167,--/* block 7 */-163,163,163,163,162, 46,168,169,170,170,170,163,171,163,172,172,-173,174,175,174,174,176,174,174,177,178,179,174,180,174,174,174,-181,182,163,183,174,174,184,174,174,185,174,174,186,187,187,187,-173,188,189,188,188,190,188,188,191,192,193,188,194,188,188,188,-195,196,197,198,188,188,199,188,188,200,188,188,201,202,202,203,-204,205,206,207,207,208,209,210,160,161,160,161,160,161,160,161,-160,161,211,212,211,212,211,212,211,212,211,212,211,212,211,212,-213,214,215,216,217,218,219,160,161,220,160,161,221,222,222,222,--/* block 8 */-223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,-224,224,225,224,226,224,224,224,224,224,224,224,224,224,227,224,-224,228,229,224,224,224,224,224,224,224,230,224,224,224,224,224,-231,231,232,231,233,231,231,231,231,231,231,231,231,231,234,231,-231,235,236,231,231,231,231,231,231,231,237,231,231,231,231,231,-238,238,238,238,238,238,239,238,239,238,238,238,238,238,238,238,-240,241,242,243,240,241,240,241,240,241,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,--/* block 9 */-240,241,244,245,246,247,247,246,248,248,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-249,240,241,240,241,240,241,240,241,240,241,240,241,240,241,250,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,--/* block 10 */-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-163,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,-251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,-251,251,251,251,251,251,251,163,163,252,253,253,253,253,253,254,-255,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,--/* block 11 */-256,256,256,256,256,256,256,257,255,258,259,163,163,260,260,261,-262,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,-263,263,264,263,263,263,263,263,263,263,263,263,263,263,263,263,-265,265,265,265,265,265,265,265,265,265,265,265,265,265,266,265,-267,265,265,268,265,269,267,269,262,262,262,262,262,262,262,262,-270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,-270,270,270,270,270,270,270,270,270,270,270,262,262,262,262,270,-270,270,270,267,271,262,262,262,262,262,262,262,262,262,262,262,--/* block 12 */-272,272,272,272,272,273,274,274,275,276,276,277,278,279,280,280,-281,281,281,281,281,281,281,281,281,281,281,282,283,284,284,285,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-287,286,286,286,286,286,286,286,286,286,286,288,288,288,288,288,-288,288,288,289,289,289,281,290,291,281,281,281,281,281,281,281,-292,292,292,292,292,292,292,292,292,292,276,293,293,279,286,286,-289,286,286,294,286,286,286,286,286,286,286,286,286,286,286,286,--/* block 13 */-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,295,286,281,281,281,281,281,281,281,273,280,291,-291,281,281,281,281,296,296,281,281,280,291,291,291,281,286,286,-297,297,297,297,297,297,297,297,297,297,286,286,286,298,298,286,--/* block 14 */-299,299,299,300,300,300,300,300,300,300,300,301,300,301,302,303,-304,305,304,304,304,304,304,304,304,304,304,304,304,304,304,304,-304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,-306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,-307,307,307,307,307,307,307,307,307,307,307,302,302,304,304,304,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,--/* block 15 */-308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,-308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,-308,308,308,308,308,308,309,309,309,309,309,309,309,309,309,309,-309,308,302,302,302,302,302,302,302,302,302,302,302,302,302,302,-310,310,310,310,310,310,310,310,310,310,311,311,311,311,311,311,-311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,-311,311,311,311,311,311,311,311,311,311,311,312,312,312,312,312,-312,312,312,312,313,313,314,315,316,317,318,262,262,319,320,320,--/* block 16 */-321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,-321,321,321,321,321,321,322,322,323,323,324,322,322,322,322,322,-322,322,322,322,324,322,322,322,324,322,322,322,322,325,262,262,-326,326,326,326,326,326,326,327,326,327,326,326,326,327,327,262,-328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,-328,328,328,328,328,328,328,328,328,329,329,329,262,262,330,262,-304,304,304,304,304,304,304,304,304,304,304,302,302,302,302,302,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,--/* block 17 */-286,286,286,286,286,286,286,286,331,286,286,286,286,286,286,302,-272,272,302,302,302,302,302,302,291,291,291,291,291,291,291,291,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,296,291,291,291,291,291,291,-291,291,291,332,281,281,281,281,281,281,281,281,281,281,281,281,-332,332,273,290,290,290,290,290,290,290,291,291,291,291,291,291,-290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,281,--/* block 18 */-333,333,333,334,335,335,335,335,335,335,335,335,335,335,335,335,-335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,-335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,-335,335,335,335,335,335,335,335,335,335,333,334,336,335,334,334,-334,333,333,333,333,333,333,333,333,334,334,334,334,337,334,334,-335,338,339,154,154,333,333,333,335,335,335,335,335,335,335,335,-335,335,333,333,340,341,342,342,342,342,342,342,342,342,342,342,-343,344,335,335,335,335,335,335,335,335,335,335,335,335,335,335,--/* block 19 */-345,346,347,347,163,345,345,345,345,345,345,345,345,163,163,345,-345,163,163,345,345,345,345,345,345,345,345,345,345,345,345,345,-345,345,345,345,345,345,345,345,345,163,345,345,345,345,345,345,-345,163,345,163,163,163,345,345,345,345,163,163,348,345,349,347,-347,346,346,346,346,163,163,347,347,163,163,347,347,350,345,163,-163,163,163,163,163,163,163,349,163,163,163,163,345,345,163,345,-345,345,346,346,163,163,351,351,351,351,351,351,351,351,351,351,-345,345,352,352,353,353,353,353,353,353,354,352,345,355,356,163,--/* block 20 */-163,357,357,358,163,359,359,359,359,359,359,163,163,163,163,359,-359,163,163,359,359,359,359,359,359,359,359,359,359,359,359,359,-359,359,359,359,359,359,359,359,359,163,359,359,359,359,359,359,-359,163,359,359,163,359,359,163,359,359,163,163,360,163,358,358,-358,357,357,163,163,163,163,357,357,163,163,357,357,361,163,163,-163,357,163,163,163,163,163,163,163,359,359,359,359,163,359,163,-163,163,163,163,163,163,362,362,362,362,362,362,362,362,362,362,-357,357,359,359,359,357,363,163,163,163,163,163,163,163,163,163,--/* block 21 */-163,364,364,365,163,366,366,366,366,366,366,366,366,366,163,366,-366,366,163,366,366,366,366,366,366,366,366,366,366,366,366,366,-366,366,366,366,366,366,366,366,366,163,366,366,366,366,366,366,-366,163,366,366,163,366,366,366,366,366,163,163,367,366,365,365,-365,364,364,364,364,364,163,364,364,365,163,365,365,368,163,163,-366,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-366,366,364,364,163,163,369,369,369,369,369,369,369,369,369,369,-370,371,163,163,163,163,163,163,163,366,364,364,364,367,367,367,--/* block 22 */-163,372,373,373,163,374,374,374,374,374,374,374,374,163,163,374,-374,163,163,374,374,374,374,374,374,374,374,374,374,374,374,374,-374,374,374,374,374,374,374,374,374,163,374,374,374,374,374,374,-374,163,374,374,163,374,374,374,374,374,163,163,375,374,376,372,-373,372,372,372,372,163,163,373,373,163,163,373,373,377,163,163,-163,163,163,163,163,378,372,376,163,163,163,163,374,374,163,374,-374,374,372,372,163,163,379,379,379,379,379,379,379,379,379,379,-380,374,381,381,381,381,381,381,163,163,163,163,163,163,163,163,--/* block 23 */-163,163,382,383,163,383,383,383,383,383,383,163,163,163,383,383,-383,163,383,383,383,383,163,163,163,383,383,163,383,163,383,383,-163,163,163,383,383,163,163,163,383,383,383,163,163,163,383,383,-383,383,383,383,383,383,383,383,383,383,163,163,163,163,384,385,-382,385,385,163,163,163,385,385,385,163,385,385,385,386,163,163,-383,163,163,163,163,163,163,384,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,387,387,387,387,387,387,387,387,387,387,-388,388,388,389,390,390,390,390,390,391,390,163,163,163,163,163,--/* block 24 */-392,393,393,393,394,395,395,395,395,395,395,395,395,163,395,395,-395,163,395,395,395,395,395,395,395,395,395,395,395,395,395,395,-395,395,395,395,395,395,395,395,395,163,395,395,395,395,395,395,-395,395,395,395,395,395,395,395,395,395,163,163,396,395,392,392,-392,393,393,393,393,163,392,392,392,163,392,392,392,397,163,163,-163,163,163,163,163,392,392,163,395,395,395,163,163,395,163,163,-395,395,392,392,163,163,398,398,398,398,398,398,398,398,398,398,-163,163,163,163,163,163,163,399,400,400,400,400,400,400,400,401,--/* block 25 */-402,403,404,404,405,402,402,402,402,402,402,402,402,163,402,402,-402,163,402,402,402,402,402,402,402,402,402,402,402,402,402,402,-402,402,402,402,402,402,402,402,402,163,402,402,402,402,402,402,-402,402,402,402,163,402,402,402,402,402,163,163,406,402,404,407,-404,404,408,404,404,163,407,404,404,163,404,404,403,409,163,163,-163,163,163,163,163,408,408,163,163,163,163,163,163,402,402,163,-402,402,403,403,163,163,410,410,410,410,410,410,410,410,410,410,-163,402,402,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 26 */-411,411,412,412,413,413,413,413,413,413,413,413,413,163,413,413,-413,163,413,413,413,413,413,413,413,413,413,413,413,413,413,413,-413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,-413,413,413,413,413,413,413,413,413,413,413,414,414,413,415,412,-412,411,411,411,411,163,412,412,412,163,412,412,412,414,416,417,-163,163,163,163,413,413,413,415,418,418,418,418,418,418,418,413,-413,413,411,411,163,163,419,419,419,419,419,419,419,419,419,419,-418,418,418,418,418,418,418,418,418,417,413,413,413,413,413,413,--/* block 27 */-163,420,421,421,163,422,422,422,422,422,422,422,422,422,422,422,-422,422,422,422,422,422,422,163,163,163,422,422,422,422,422,422,-422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,-422,422,163,422,422,422,422,422,422,422,422,422,163,422,163,163,-422,422,422,422,422,422,422,163,163,163,423,163,163,163,163,424,-421,421,420,420,420,163,420,163,421,421,421,421,421,421,421,424,-163,163,163,163,163,163,425,425,425,425,425,425,425,425,425,425,-163,163,421,421,426,163,163,163,163,163,163,163,163,163,163,163,--/* block 28 */-163,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,-427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,-427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,-427,428,427,429,428,428,428,428,428,428,430,163,163,163,163,431,-432,432,432,432,432,427,433,434,434,434,434,434,434,428,434,435,-436,436,436,436,436,436,436,436,436,436,437,437,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 29 */-163,438,438,163,438,163,438,438,438,438,438,163,438,438,438,438,-438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,-438,438,438,438,163,438,163,438,438,438,438,438,438,438,438,438,-438,439,438,440,439,439,439,439,439,439,441,439,439,438,163,163,-442,442,442,442,442,163,443,163,444,444,444,444,444,439,163,163,-445,445,445,445,445,445,445,445,445,445,163,163,438,438,438,438,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 30 */-446,447,447,447,448,448,448,448,449,448,448,448,448,449,449,449,-449,449,449,447,448,447,447,447,450,450,447,447,447,447,447,447,-451,451,451,451,451,451,451,451,451,451,452,452,452,452,452,452,-452,452,452,452,447,450,447,450,447,450,453,454,453,454,455,455,-446,446,446,446,446,446,446,446,163,446,446,446,446,446,446,446,-446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,-446,446,446,446,446,446,446,446,446,446,446,446,446,163,163,163,-163,456,456,456,456,456,456,457,456,457,456,456,456,456,456,458,--/* block 31 */-456,456,450,450,459,448,450,450,446,446,446,446,446,456,456,456,-456,456,456,456,456,456,456,456,163,456,456,456,456,456,456,456,-456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,-456,456,456,456,456,456,456,456,456,456,456,456,456,163,447,447,-447,447,447,447,447,447,450,447,447,447,447,447,447,163,447,447,-448,448,448,448,448,460,460,460,460,448,448,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 32 */-461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,-461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,-461,461,461,461,461,461,461,461,461,461,461,462,462,463,463,463,-463,464,463,463,463,463,463,465,462,466,466,464,464,463,463,461,-467,467,467,467,467,467,467,467,467,467,468,468,469,469,469,469,-461,461,461,461,461,461,464,464,463,463,461,461,461,461,463,463,-463,461,462,470,470,461,461,462,462,470,470,470,470,470,461,461,-461,463,463,463,463,461,461,461,461,461,461,461,461,461,461,461,--/* block 33 */-461,461,463,462,464,463,463,470,470,470,470,470,470,471,461,470,-472,472,472,472,472,472,472,472,472,472,470,470,462,463,473,473,-474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,-474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,-474,474,474,474,474,474,163,474,163,163,163,163,163,474,163,163,-475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,-475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,-475,475,475,475,475,475,475,475,475,475,475,476,477,475,475,475,--/* block 34 */-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,479,-480,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,--/* block 35 */-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,-481,481,481,481,481,481,481,481,482,482,482,482,482,482,482,482,-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,--/* block 36 */-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,163,483,483,483,483,163,163,-483,483,483,483,483,483,483,163,483,163,483,483,483,483,163,163,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,--/* block 37 */-483,483,483,483,483,483,483,483,483,163,483,483,483,483,163,163,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,163,483,483,483,483,163,163,483,483,483,483,483,483,483,163,-483,163,483,483,483,483,163,163,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,--/* block 38 */-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,163,483,483,483,483,163,163,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,483,483,483,483,163,163,484,484,484,-485,486,487,486,486,486,486,487,487,488,488,488,488,488,488,488,-488,488,489,489,489,489,489,489,489,489,489,489,489,163,163,163,--/* block 39 */-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-490,490,490,490,490,490,490,490,490,490,163,163,163,163,163,163,-491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,-491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,-491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,-491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,-491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,-492,492,492,492,492,492,163,163,493,493,493,493,493,493,163,163,--/* block 40 */-494,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,--/* block 41 */-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,--/* block 42 */-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,496,497,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,--/* block 43 */-498,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,-499,499,499,499,499,499,499,499,499,499,499,500,501,163,163,163,-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,-502,502,502,502,502,502,502,502,502,502,502,503,503,503,504,504,-504,502,502,502,502,502,502,502,502,163,163,163,163,163,163,163,--/* block 44 */-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,-505,505,506,506,507,508,163,163,163,163,163,163,163,163,163,505,-509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,-509,509,510,510,511,512,512,163,163,163,163,163,163,163,163,163,-513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,-513,513,514,514,163,163,163,163,163,163,163,163,163,163,163,163,-515,515,515,515,515,515,515,515,515,515,515,515,515,163,515,515,-515,163,516,516,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 45 */-517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,-517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,-517,517,517,518,518,517,517,517,517,517,517,517,517,517,517,517,-517,517,517,517,519,519,520,521,521,521,521,521,521,521,520,520,-520,520,520,520,520,520,521,520,520,522,522,522,522,522,522,522,-522,522,523,522,524,524,524,525,526,526,524,527,517,522,163,163,-528,528,528,528,528,528,528,528,528,528,163,163,163,163,163,163,-529,529,529,529,529,529,529,529,529,529,163,163,163,163,163,163,--/* block 46 */-530,530,531,532,533,531,534,530,533,535,536,537,537,537,538,537,-539,539,539,539,539,539,539,539,539,539,163,163,163,163,163,163,-540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,-540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,-540,540,540,541,540,540,540,540,540,540,540,540,540,540,540,540,-540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,-540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,-540,540,540,540,540,540,540,540,540,163,163,163,163,163,163,163,--/* block 47 */-540,540,540,540,540,542,542,540,540,540,540,540,540,540,540,540,-540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,-540,540,540,540,540,540,540,540,540,543,540,163,163,163,163,163,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-495,495,495,495,495,495,163,163,163,163,163,163,163,163,163,163,--/* block 48 */-544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,-544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,163,-545,545,545,546,546,546,546,545,545,546,546,546,163,163,163,163,-546,546,545,546,546,546,546,546,546,547,547,547,163,163,163,163,-548,163,163,163,549,549,550,550,550,550,550,550,550,550,550,550,-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,-551,551,551,551,551,551,551,551,551,551,551,551,551,551,163,163,-551,551,551,551,551,163,163,163,163,163,163,163,163,163,163,163,--/* block 49 */-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,-552,552,552,552,552,552,552,552,552,552,552,552,163,163,163,163,-552,552,552,552,552,553,553,553,552,552,553,552,552,552,552,552,-552,552,552,552,552,552,552,552,552,552,163,163,163,163,163,163,-554,554,554,554,554,554,554,554,554,554,555,163,163,163,556,556,-557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,-557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,--/* block 50 */-558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,-558,558,558,558,558,558,558,559,559,560,560,559,163,163,561,561,-562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,-562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,-562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,-562,562,562,562,562,563,564,563,564,564,564,564,564,564,564,163,-565,566,564,566,566,564,564,564,564,564,564,564,564,563,563,563,-563,563,563,564,564,567,567,567,567,567,567,567,567,163,163,567,--/* block 51 */-568,568,568,568,568,568,568,568,568,568,163,163,163,163,163,163,-568,568,568,568,568,568,568,568,568,568,163,163,163,163,163,163,-569,569,569,569,569,569,569,570,571,571,571,571,569,569,163,163,-154,154,154,154,154,154,154,154,154,154,154,154,154,154,572,573,-573,154,154,154,154,154,154,154,154,154,154,154,573,573,573,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 52 */-574,574,574,574,575,576,576,576,576,576,576,576,576,576,576,576,-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,-576,576,576,576,577,578,574,574,574,574,574,575,574,575,575,575,-575,575,574,575,579,576,576,576,576,576,576,576,576,163,163,163,-580,580,580,580,580,580,580,580,580,580,581,581,582,583,581,581,-582,584,584,584,584,584,584,584,584,584,584,577,577,577,577,577,-577,577,577,577,584,584,584,584,584,584,584,584,584,581,581,163,--/* block 53 */-585,585,586,587,587,587,587,587,587,587,587,587,587,587,587,587,-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,-587,586,585,585,585,585,586,586,585,585,588,589,585,585,587,587,-590,590,590,590,590,590,590,590,590,590,587,587,587,587,587,587,-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,-591,591,591,591,591,591,592,593,594,594,593,593,593,594,593,594,-594,594,595,595,163,163,163,163,163,163,163,163,596,596,596,596,--/* block 54 */-597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,-597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,-597,597,597,597,598,598,598,598,598,598,598,598,599,599,599,599,-599,599,599,599,598,598,600,601,163,163,163,602,602,603,603,603,-604,604,604,604,604,604,604,604,604,604,163,163,163,597,597,597,-605,605,605,605,605,605,605,605,605,605,606,606,606,606,606,606,-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,-606,606,606,606,606,606,606,606,607,607,607,608,607,607,609,609,--/* block 55 */-610,611,612,613,614,615,616,617,618,163,163,163,163,163,163,163,-619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,-619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,-619,619,619,619,619,619,619,619,619,619,619,163,163,619,619,619,-620,620,620,620,620,620,620,620,163,163,163,163,163,163,163,163,-621,622,621,623,622,624,624,625,624,625,626,622,625,625,622,622,-625,627,622,622,622,622,622,622,622,628,629,630,630,624,630,630,-630,630,631,632,633,629,629,634,635,635,636,163,163,163,163,163,--/* block 56 */- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,- 70, 70, 70, 70, 70, 70,221,221,221,221,221,637,147,147,147,147,-147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,-147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,-147,147,147,147,147,147,147,147,147,147,147,147,147,638,638,638,-638,638,148,147,147,147,638,638,638,638,638, 70, 70, 70, 70, 70,- 70, 70, 70, 70, 70, 70, 70, 70,639,640, 70, 70, 70,641, 70, 70,--/* block 57 */- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,642, 70,- 70, 70, 70, 70, 70, 70,643, 70, 70, 70, 70,644,644,644,644,644,-644,644,644,644,645,644,644,644,645,644,644,644,644,644,644,644,-644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,646,-647,647,158,158,154,154,154,154,154,154,154,154,154,154,154,154,-158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,-158,158,158,158,158,158,158,573,573,573,573,573,573,573,573,573,-573,573,573,573,573,154,154,154,648,154,649,154,154,154,154,154,--/* block 58 */- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,-650,651, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,--/* block 59 */- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 69, 69, 69, 69,652,653, 70, 70,654, 70,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,--/* block 60 */-655,655,655,655,655,655,655,655,656,656,656,656,656,656,656,656,-655,655,655,655,655,655,163,163,656,656,656,656,656,656,163,163,-655,655,655,655,655,655,655,655,656,656,656,656,656,656,656,656,-655,655,655,655,655,655,655,655,656,656,656,656,656,656,656,656,-655,655,655,655,655,655,163,163,656,656,656,656,656,656,163,163,-173,655,173,655,173,655,173,655,163,656,163,656,163,656,163,656,-655,655,655,655,655,655,655,655,656,656,656,656,656,656,656,656,-657,657,658,658,658,658,659,659,660,660,661,661,662,662,163,163,--/* block 61 */-663,663,663,663,663,663,663,663,664,664,664,664,664,664,664,664,-663,663,663,663,663,663,663,663,664,664,664,664,664,664,664,664,-663,663,663,663,663,663,663,663,664,664,664,664,664,664,664,664,-655,655,665,666,665,163,173,665,656,656,667,667,668,162,669,162,-162,162,665,666,665,163,173,665,670,670,670,670,668,162,162,162,-655,655,173,173,163,163,173,173,656,656,671,671,163,162,162,162,-655,655,173,173,173,215,173,173,656,656,672,672,220,162,162,162,-163,163,665,666,665,163,173,665,673,673,674,674,668,162,162,163,--/* block 62 */-675,675,675,675,675,675,675,675,675,675,675, 51,676,677,678,679,-680,680,680,680,680,680,681, 43,682,683,684,685,685,686,684,685,- 43, 43, 43, 43,687, 43, 43,687,688,689,690,691,692,693,694,695,-696,696,697,697,697, 43, 43, 43, 43, 49, 57, 43,698,699, 43,700,-701, 43, 43, 43,702,703,704,699,699,698, 43, 43, 43, 43, 43, 43,- 43, 43, 50,705,700, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,675,- 51,706,706,706,706,707,708,709,710,711,712,712,712,712,712,712,- 54,645,163,163, 54, 54, 54, 54, 54, 54,713,714,715,716,717,644,--/* block 63 */- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,713,714,715,716,717,163,-644,644,644,644,644,644,644,644,644,644,644,644,644,163,163,163,-431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,-431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,-431,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,-719,719,719,719,719,719,719,719,719,719,719,719,719,720,720,720,-720,719,720,721,720,719,719,158,158,158,158,719,719,719,719,719,-722,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 64 */-723,723,724,723,723,723,723,724,723,723,725,724,724,724,725,725,-724,724,724,725,723,724,723,723,726,724,724,724,724,724,723,723,-723,723,727,723,724,723,728,723,724,729,730,731,724,724,732,725,-724,724,733,724,725,734,734,734,734,735,723,723,725,725,724,724,-715,715,715,715,715,724,725,725,736,736,723,715,723,723,737,460,- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,-738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,-739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,--/* block 65 */-740,740,740, 65, 66,740,740,740,740, 58,723,723,163,163,163,163,- 50, 50, 50, 50,741,742,742,742,742,742, 50, 50,743,743,743,743,- 50,743,743, 50,743,743, 50,743, 45,742,742,743,743,743, 50, 45,-743,743, 45, 45, 45, 45,743,743, 45, 45, 45, 45,743,743,743,743,-743,743,743,743,743,743,743,743,743,743,743,743,743,743, 50, 50,-743,743, 50,743, 50,743,743,743,743,743,743,743, 45,743, 45, 45,- 45, 45, 45, 45,743,743, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,--/* block 66 */- 50, 50, 50, 50, 50, 50, 50, 50,744,744,744,744,744,744, 50, 50,- 50, 50,745, 53, 50,744, 50, 50, 50, 50, 50, 50, 50, 50, 50,744,-744,744,744, 50,744, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,744,744, 50, 50,- 50, 50, 50,744, 50,744, 50, 50, 50, 50, 50, 50,744, 50, 50, 50,- 50, 50,744,744,744,744, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50,744,744,744,744,744,744,744,744, 50, 50,744,744,-744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,--/* block 67 */-744,744,744,744,744,744,744,744,744,744,744,744, 50, 50, 50,744,-744,744,744, 50, 50, 50, 50, 50,744, 50, 50, 50, 50, 50, 50, 50,- 50, 50,744,744, 50, 50,744, 50,744,744, 50,744, 50, 50, 50, 50,-744,744,744,744,744,744,744,744,744, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50,744,744,744,744,744, 50, 50,-744,744, 50, 50, 50, 50,744,744,744,744,744,744,744,744,744,744,-744,744,744,744,744,744,744,744,744,744,744,744,744,744, 50, 50,-744,744,744,744,744, 50,744,744, 50, 50,744,744,744,744,744, 50,--/* block 68 */- 45, 45, 45, 45, 45, 45, 45, 45,746,747,746,747, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,748,748, 45, 45, 45, 45,- 50, 50, 45, 45, 45, 45, 45, 45, 47,749,750, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45,751,751,751,751,751,751,751,751,751,751,-751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,-751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,-751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,-751,751,751,751,751,751,751,751,751,751,751, 45, 50, 45, 45, 45,--/* block 69 */- 45, 45, 45, 45, 45, 45, 45, 45,752, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45,751, 45, 45, 45, 45, 45, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50,743,743, 45,743, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 47,-743, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50, 50,- 50, 50,743, 45, 45, 45, 45, 45, 45,748,748,748,748, 47, 47, 47,-748, 47, 47,748, 45, 45, 45, 45, 47, 47, 47, 45, 45, 45, 45, 45,--/* block 70 */- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45,753,753,753,753,753,753,753,753,753,-753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,753,753,753,753,753,-753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,--/* block 71 */- 58, 58, 58, 58, 58, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54,- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,754,754,754,754,754,754,754,754,754,754,-754,754,755,754,754,754,754,754,754,754,754,754,754,754,754,754,-756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,-756,756,756,756,756,756,756,756,756,756, 58, 58, 58, 58, 58, 58,- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,--/* block 72 */- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,--/* block 73 */- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,-743,743, 45, 45, 45, 45, 45, 45, 45, 45, 47, 47, 45, 45,743,743,-743,743,743,743,743,743,742, 50, 45, 45, 45, 45,743,743,743,743,-742, 50, 45, 45, 45, 45,743,743, 45, 45,743,743, 45, 45, 45,743,-743,743,743,743, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45,743, 45,743, 45, 45,743,743,743,743,743,743, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50,741,741,757,757, 50,--/* block 74 */- 47, 47, 47, 47, 47,758,743,752,752,752,752,752,752,752, 47,752,-752, 47,752, 45,748,748,752,752, 47,752,752,752,752,759,752,752,- 47,752, 47, 47,752,752, 47,752,752,752, 47,752,752,752, 47, 47,-752,752,752,752,752,752,752,752, 47, 47, 47,752,752,752,752,752,-742,752,742,752,752,752,752,752,748,748,748,748,748,748,748,748,-748,748,748,748,752,752,752,752,752,752,752,752,752,752,752, 47,-742,758,758,742,752, 47, 47,752, 47,752,752,752,752,758,758,760,-752,752,752,752,752,752,752,752,752,752,752, 47,752,752, 47,748,--/* block 75 */-752,752,752,752,752,752, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,-752,752, 47,748, 47, 47, 47, 47,752, 47,752, 47, 47,752,752,752,- 47,748,752,752,752,752,752, 47,752,752,748,748,761,752,752,752,- 47, 47,752,752,752,752,752,752,752,752,752,752,752,748,748,752,-752,752,752,752,748,748,752,752, 47,752,752,752,752,752,748, 47,-752, 47,752, 47,748,752,752,752,752,752,752,752,752,752,752,752,-752,752,752,752,752,752,752,752,752, 47,748,752,752,752,752,752,- 47, 47,748,748, 47,748,752, 47, 47,759,748,752,752,748,752,752,--/* block 76 */-752,752, 47,752,752,748, 45, 45, 47, 47,762,762,759,759,752, 47,-752,752, 47, 45, 47, 45, 47, 45, 45, 45, 45, 45, 45, 47, 45, 45,- 45, 47, 45, 45, 45, 45, 45, 45,748, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 47, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 47, 45, 45, 47, 45, 45, 45, 45,748, 45,748, 45,- 45, 45, 45,748,748,748, 45,748, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 47, 47,752,752,752,703,704,703,704,703,704,703,704,-703,704,703,704,703,704, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,--/* block 77 */- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,- 58, 58, 58, 58, 45,748,748,748, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,-748, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,748,- 50, 50, 50,744,744,746,747, 50,744,744, 50,744, 50,744, 50, 50,- 50, 50, 50, 50, 50,744,744, 50, 50, 50, 50, 50,744,744,744, 50,- 50, 50,744,744,744,744,746,747,746,747,746,747,746,747,746,747,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,--/* block 78 */-763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,-763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,-763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,-763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,-763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,-763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,-763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,-763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,--/* block 79 */- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50,741,741, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,--/* block 80 */- 50, 50, 50,746,747,746,747,746,747,746,747,746,747,746,747,746,-747,746,747,746,747,746,747,746,747, 50, 50,744, 50, 50, 50, 50,-744, 50, 50,744,744,744, 50, 50,744,744,744,744,744,744,744,744,- 50, 50, 50, 50, 50, 50, 50, 50,744, 50, 50, 50, 50, 50, 50, 50,-744,744, 50, 50,744,744, 50, 50, 50, 50, 50, 50, 50, 50, 50,744,-744,744,744, 50,744,744, 50, 50,746,747,746,747, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50,744,744, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50,744, 50, 50,744,744, 50, 50,746,747, 50, 50,--/* block 81 */- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,744,744,744,744, 50,- 50, 50, 50, 50,744,744, 50, 50, 50, 50, 50, 50,744,744, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50,744,744, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 50, 50, 50, 50,744,744,744,744,744,744,744,--/* block 82 */-744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,-744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,-744,744,744, 50, 50, 50,744,744,744,744,744,744,744,744, 50,744,-744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,-744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,-744,744,744,744,744,744,744, 50, 50, 50, 50, 50, 50, 50,744, 50,- 50, 50, 50,744,744,744, 50, 50, 50, 50, 50, 50,744,744,744, 50,- 50, 50, 50, 50, 50, 50, 50,744,744,744,744, 50, 50, 50, 50, 50,--/* block 83 */- 45, 45, 45, 45, 45, 47, 47, 47, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,748,748, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,- 50, 50, 50, 50, 50, 45, 45, 50, 50, 50, 50, 50, 50, 45, 45, 45,-748, 45, 45, 45, 45,748, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45,753,753, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,--/* block 84 */- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45,753, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,764, 45,--/* block 85 */-765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,-765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,-765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,-766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,-766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,-766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,- 65, 66,767,768,769,770,771, 65, 66, 65, 66, 65, 66,772,773,774,-775, 70, 65, 66, 70, 65, 66, 70, 70, 70, 70, 70,645,644,776,776,--/* block 86 */-211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,-211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,-211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,-211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,-211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,-211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,-211,212,211,212,777,778,778,778,778,778,778,211,212,211,212,779,-779,779,211,212,163,163,163,163,163,780,780,780,780,781,780,780,--/* block 87 */-782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,-782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,-782,782,782,782,782,782,163,782,163,163,163,163,163,782,163,163,-783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,-783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,-783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,-783,783,783,783,783,783,783,783,163,163,163,163,163,163,163,784,-785,163,163,163,163,163,163,163,163,163,163,163,163,163,163,786,--/* block 88 */-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,-483,483,483,483,483,483,483,163,163,163,163,163,163,163,163,163,-483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,-483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,-483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,-483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,-787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,-787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,--/* block 89 */- 43, 43,788,789,788,789, 43, 43, 43,788,789, 43,788,789, 43, 43,- 43, 43, 43, 43, 43, 43, 43,680, 43, 43,680, 43,788,789, 43, 43,-788,789,703,704,703,704,703,704,703,704, 43, 43, 43, 43,699,790,- 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,680,680,699, 43, 43, 43,-680,791,684,792, 43, 43, 43, 43, 43, 43, 43, 43,791, 43,791,791,- 45, 45, 43,699,699,703,704,703,704,703,704,703,704,680,753,753,-753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,-753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,--/* block 90 */-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,163,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 91 */-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,--/* block 92 */-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,-793,793,793,793,793,793,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-794,794,795,795,794,794,794,794,794,794,794,794,163,163,163,163,--/* block 93 */-675,796,797,798,723,799,800,801,802,803,802,803,804,805,804,805,-802,803, 45,806,802,803,802,803,802,803,802,803,807,808,809,809,- 45,801,801,801,801,801,801,801,801,801,810,810,810,810,811,811,-812,813,813,813,813,813,723,814,801,801,801,815,816,817,818,818,-163,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,--/* block 94 */-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,163,163,820,820,821,821,822,822,819,-823,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,-824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,-824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,-824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,-824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,-824,824,824,824,824,824,824,824,824,824,824,825,826,827,827,824,--/* block 95 */-163,163,163,163,163,828,828,828,828,828,828,828,828,828,828,828,-828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,-828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,-163,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,-829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,-829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,-829,829,829,829,830,829,829,829,829,829,829,829,829,829,829,829,-829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,--/* block 96 */-829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,163,-831,831,832,832,832,832,831,831,831,831,831,831,831,831,831,831,-828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,-828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,-818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,-818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,-818,818,818,818,163,163,163,163,163,163,163,163,163,163,163,163,-824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,--/* block 97 */-833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,-833,833,833,833,833,833,833,833,833,833,833,833,833,834,834,163,-832,832,832,832,832,832,832,832,832,832,831,831,831,831,831,831,-831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,-831,831,831,831,831,831,831,831,835,835,835,835,835,835,835,835,-723, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,-833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,-833,833,833,833,833,833,833,833,833,833,833,833,834,834,834,460,--/* block 98 */-832,832,832,832,832,832,832,832,832,832,831,831,831,831,831,831,-831,831,831,831,831,831,831,836,831,836,831,831,831,831,831,831,-831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,-831, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,-831,831,831,831,831,831,831,831,831,831,831,831,723,723,723,723,-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,831,--/* block 99 */-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,-837,837,837,837,837,837,837,837,831,831,831,831,831,831,831,831,-831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,-831,460,460,460,460,460,460,723,723,723,723,831,831,831,831,831,--/* block 100 */-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,723,723,-831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,-831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,723,--/* block 101 */-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,--/* block 102 */-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,--/* block 103 */-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,840,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,--/* block 104 */-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,-839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,--/* block 105 */-839,839,839,839,839,839,839,839,839,839,839,839,839,163,163,163,-841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,-841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,-841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,-841,841,841,841,841,841,841,163,163,163,163,163,163,163,163,163,-842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,-842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,-842,842,842,842,842,842,842,842,843,843,843,843,843,843,844,845,--/* block 106 */-846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,-846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,-846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,-846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,-846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,-846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,-846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,-846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,--/* block 107 */-846,846,846,846,846,846,846,846,846,846,846,846,847,848,849,849,-846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,-850,850,850,850,850,850,850,850,850,850,846,846,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-240,241,240,241,240,241,240,241,240,241,851,852,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,240,241,853,246,-248,248,248,854,787,787,787,787,787,787,787,787,855,855,854,856,--/* block 108 */-240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,-240,241,240,241,240,241,240,241,240,241,240,241,857,857,787,787,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,859,859,859,859,859,859,859,859,859,859,-860,860,861,862,863,863,863,862,163,163,163,163,163,163,163,163,--/* block 109 */-864,864,864,864,864,864,864,864, 46, 46, 46, 46, 46, 46, 46, 46,- 46, 46, 46, 46, 46, 46, 46,149,149,149,149,149,149,149,149,149,- 46, 46, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 70, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,-644, 70, 70, 70, 70, 70, 70, 70, 70, 65, 66, 65, 66,865, 65, 66,--/* block 110 */- 65, 66, 65, 66, 65, 66, 65, 66,149,866,866, 65, 66,867, 70, 92,- 65, 66, 65, 66,868, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,869,870,871,872,869, 70,-873,874,875,876, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,- 65, 66, 65, 66,877,878,879, 65, 66, 65, 66,163,163,163,163,163,- 65, 66,163, 70,163, 70, 65, 66, 65, 66,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,880,880,880, 65, 66, 92,147,147, 70, 92, 92, 92, 92, 92,--/* block 111 */-881,881,882,881,881,881,883,881,881,881,881,882,881,881,881,881,-881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,-881,881,881,884,884,882,882,884,885,885,885,885,883,163,163,163,-886,886,886,887,887,887,888,888,889,890,163,163,163,163,163,163,-891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,-891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,-891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,-891,891,891,891,892,892,893,893,163,163,163,163,163,163,163,163,--/* block 112 */-894,894,895,895,895,895,895,895,895,895,895,895,895,895,895,895,-895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,-895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,-895,895,895,895,894,894,894,894,894,894,894,894,894,894,894,894,-894,894,894,894,896,897,163,163,163,163,163,163,163,163,898,898,-899,899,899,899,899,899,899,899,899,899,163,163,163,163,163,163,-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,-336,900,335,901,335,335,335,335,343,343,343,335,343,335,335,333,--/* block 113 */-902,902,902,902,902,902,902,902,902,902,903,903,903,903,903,903,-903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,-903,903,903,903,903,903,904,904,904,904,904,905,905,905,906,907,-908,908,908,908,908,908,908,908,908,908,908,908,908,908,908,908,-908,908,908,908,908,908,908,909,909,909,909,909,909,909,909,909,-909,909,910,911,163,163,163,163,163,163,163,163,163,163,163,912,-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,-478,478,478,478,478,478,478,478,478,478,478,478,478,163,163,163,--/* block 114 */-913,913,913,914,915,915,915,915,915,915,915,915,915,915,915,915,-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,-915,915,915,916,914,914,913,913,913,913,914,914,913,913,914,914,-917,918,918,918,918,918,918,919,920,920,918,918,918,918,163,921,-922,922,922,922,922,922,922,922,922,922,163,163,163,163,918,918,-461,461,461,461,461,471,923,461,461,461,461,461,461,461,461,461,-472,472,472,472,472,472,472,472,472,472,461,461,461,461,461,163,--/* block 115 */-924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,-924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,-924,924,924,924,924,924,924,924,924,925,925,925,925,925,925,926,-926,925,925,926,926,925,925,163,163,163,163,163,163,163,163,163,-924,924,924,925,924,924,924,924,924,924,924,924,925,926,163,163,-927,927,927,927,927,927,927,927,927,927,163,163,928,929,929,929,-461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,-923,461,461,461,461,461,461,473,473,473,461,470,471,470,461,461,--/* block 116 */-930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,-930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,-930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,-931,930,931,931,931,932,932,931,931,932,930,932,932,930,931,933,-934,933,934,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,930,930,935,936,937,-938,938,938,938,938,938,938,938,938,938,938,939,940,940,939,939,-941,941,938,942,942,939,943,163,163,163,163,163,163,163,163,163,--/* block 117 */-163,483,483,483,483,483,483,163,163,483,483,483,483,483,483,163,-163,483,483,483,483,483,483,163,163,163,163,163,163,163,163,163,-483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,- 70, 70, 70,944, 70, 70, 70, 70, 70, 70, 70,866,147,147,147,147,- 70, 70, 70, 70, 70,221, 70, 70, 70,945, 46, 46,163,163,163,163,-946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,--/* block 118 */-946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,-946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,-946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,-946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,-938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,-938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,-938,938,938,939,939,940,939,939,940,939,939,941,947,943,163,163,-948,948,948,948,948,948,948,948,948,948,163,163,163,163,163,163,--/* block 119 */-949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,--/* block 120 */-950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,--/* block 121 */-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,--/* block 122 */-950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,--/* block 123 */-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,--/* block 124 */-950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,--/* block 125 */-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,--/* block 126 */-950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,-950,950,950,950,163,163,163,163,163,163,163,163,163,163,163,163,-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,-481,481,481,481,481,481,481,163,163,163,163,482,482,482,482,482,-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,-482,482,482,482,482,482,482,482,482,482,482,482,163,163,163,163,--/* block 127 */-951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,-951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,-951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,-951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,-951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,-951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,-951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,-951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,--/* block 128 */-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,--/* block 129 */-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,--/* block 130 */-953,953,953,953,953,953,953,953,953,953,953,953,953,953,838,838,-953,838,953,838,838,953,953,953,953,953,953,953,953,953,953,838,-953,838,953,838,838,953,953,838,838,838,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,163,163,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,--/* block 131 */-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 132 */-652,652,652,652,652,652,652,163,163,163,163,163,163,163,163,163,-163,163,163,257,257,257,257,257,163,163,163,163,163,270,265,270,-270,270,270,270,270,270,270,270,270,954,270,270,270,270,270,270,-270,270,270,270,270,270,270,262,270,270,270,270,270,262,270,262,-270,270,262,270,270,262,270,270,270,270,270,270,270,270,270,270,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,--/* block 133 */-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,331,331,331,331,331,331,331,331,331,331,331,331,331,331,-331,331,331,302,302,302,302,302,302,302,302,302,302,302,302,302,-302,302,302,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,--/* block 134 */-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,955,955,-955,955,955,955,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,--/* block 135 */-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,--/* block 136 */-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,956,957,-280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,--/* block 137 */-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-302,302,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,302,302,302,302,302,302,302,280,-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,-286,286,959,286,286,286,286,286,286,286,955,955,277,960,280,280,--/* block 138 */-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,962,-963,963,963,964,963,963,963,965,966,963,163,163,163,163,163,163,-154,154,154,154,154,154,154,154,154,154,154,154,154,154,855,855,-963,967,967,700,700,965,966,965,966,965,966,965,966,965,966,965,-966,968,969,968,969,798,798,965,966,963,963,963,963,700,700,700,-970,166,971,163,166,972,973,973,967,974,975,974,975,974,975,976,-963,977,713,978,979,979,715,163,977,431,976,963,163,163,163,163,-955,286,955,286,955,302,955,286,955,286,955,286,955,286,955,286,--/* block 139 */-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,-286,286,286,286,286,286,286,286,286,286,286,286,286,302,302, 51,--/* block 140 */-163,973,980,976,431,976,963,981,974,975,963,713,970,982,971,983,-984,984,984,984,984,984,984,984,984,984,972,166,979,715,979,973,-963,985,985,985,985,985,985, 59, 59, 59, 59, 59, 59, 59, 59, 59,- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,974,977,975,986,700,- 46,987,987,987,987,987,987, 62, 62, 62, 62, 62, 62, 62, 62, 62,- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,974,715,975,715,974,-975,988,989,990,991,825,824,824,824,824,824,824,824,824,824,824,-826,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,--/* block 141 */-824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,-824,824,824,824,824,824,824,824,824,824,824,824,824,824,992,992,-830,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,-829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,163,-163,163,829,829,829,829,829,829,163,163,829,829,829,829,829,829,-163,163,829,829,829,829,829,829,163,163,829,829,829,163,163,163,-431,431,715, 46,723,431,431,163,723,715,715,715,715,723,723,163,-707,707,707,707,707,707,707,707,707,993,993,993,723,723,958,958,--/* block 142 */-994,994,994,994,994,994,994,994,994,994,994,994,163,994,994,994,-994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,-994,994,994,994,994,994,994,163,994,994,994,994,994,994,994,994,-994,994,994,994,994,994,994,994,994,994,994,163,994,994,163,994,-994,994,994,994,994,994,994,994,994,994,994,994,994,994,163,163,-994,994,994,994,994,994,994,994,994,994,994,994,994,994,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 143 */-994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,-994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,-994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,-994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,-994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,-994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,-994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,-994,994,994,994,994,994,994,994,994,994,994,163,163,163,163,163,--/* block 144 */-995,996,997,163,163,163,163,998,998,998,998,998,998,998,998,998,-998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,-998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,-998,998,998,998,163,163,163,999,999,999,999,999,999,999,999,999,-1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,-1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,-1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,-1000,1000,1000,1000,1000,1001,1001,1001,1001,1002,1002,1002,1002,1002,1002,1002,--/* block 145 */-1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1001,1001,1002,1003,1003,163,-723,723,723,723,723,723,723,723,723,723,723,723,723,163,163,163,-1002,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,158,163,163,--/* block 146 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 147 */-1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,-1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,163,163,163,-1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,-1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,-1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,-1005,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1006,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,-1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,163,163,163,163,--/* block 148 */-1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,-1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,-1009,1009,1009,1009,163,163,163,163,163,163,163,163,163,1008,1008,1008,-1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,-1010,1011,1010,1010,1010,1010,1010,1010,1010,1010,1011,163,163,163,163,163,-1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,-1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,-1012,1012,1012,1012,1012,1012,1013,1013,1013,1013,1013,163,163,163,163,163,--/* block 149 */-1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,-1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,163,1015,-1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,-1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,-1016,1016,1016,1016,163,163,163,163,1016,1016,1016,1016,1016,1016,1016,1016,-1017,1018,1018,1018,1018,1018,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 150 */-1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,-1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,-1019,1019,1019,1019,1019,1019,1019,1019,1020,1020,1020,1020,1020,1020,1020,1020,-1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,-1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,-1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,-1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,-1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,--/* block 151 */-1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,-1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,163,163,-1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,163,163,163,163,163,163,-1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,-1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,-1024,1024,1024,1024,163,163,163,163,1025,1025,1025,1025,1025,1025,1025,1025,-1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,-1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,163,163,163,163,--/* block 152 */-1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,-1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,-1026,1026,1026,1026,1026,1026,1026,1026,163,163,163,163,163,163,163,163,-1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,-1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,-1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,-1027,1027,1027,1027,163,163,163,163,163,163,163,163,163,163,163,1028,-1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,163,1029,1029,1029,1029,--/* block 153 */-1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,163,1029,1029,1029,1029,-1029,1029,1029,163,1029,1029,163,1030,1030,1030,1030,1030,1030,1030,1030,1030,-1030,1030,163,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,-1030,1030,163,1030,1030,1030,1030,1030,1030,1030,163,1030,1030,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 154 */-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,--/* block 155 */-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,1031,163,163,163,163,163,163,163,163,163,-1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,-1031,1031,1031,1031,1031,1031,163,163,163,163,163,163,163,163,163,163,-1031,1031,1031,1031,1031,1031,1031,1031,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 156 */-147,1032,1032,147,147,147,163,147,147,147,147,147,147,147,147,147,-147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,-147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,-147,163,147,147,147,147,147,147,147,147,147,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 157 */-1033,1033,1033,1033,1033,1033,262,262,1033,262,1033,1033,1033,1033,1033,1033,-1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,-1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,-1033,1033,1033,1033,1033,1033,262,1033,1033,262,262,262,1033,262,262,1033,-1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,-1034,1034,1034,1034,1034,1034,262,1035,1036,1036,1036,1036,1036,1036,1036,1036,-1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,-1037,1037,1037,1037,1037,1037,1037,1038,1038,1039,1039,1039,1039,1039,1039,1039,--/* block 158 */-1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,-1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,262,-262,262,262,262,262,262,262,1041,1041,1041,1041,1041,1041,1041,1041,1041,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,-1042,1042,1042,262,1042,1042,262,262,262,262,262,1043,1043,1043,1043,1043,--/* block 159 */-1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,-1044,1044,1044,1044,1044,1044,1045,1045,1045,1045,1045,1045,262,262,262,1046,-1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,-1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,262,262,262,262,262,1048,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 160 */-1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,-1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,-1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,-1050,1050,1050,1050,1050,1050,1050,1050,262,262,262,262,1051,1051,1050,1050,-1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,-262,262,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,-1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,-1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,--/* block 161 */-1052,1053,1053,1053,262,1053,1053,262,262,262,262,262,1053,1053,1053,1053,-1052,1052,1052,1052,262,1052,1052,1052,262,1052,1052,1052,1052,1052,1052,1052,-1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,-1052,1052,1052,1052,1052,1052,262,262,1054,1054,1054,262,262,262,262,1055,-1056,1056,1056,1056,1056,1056,1056,1056,1056,262,262,262,262,262,262,262,-1057,1057,1057,1057,1057,1057,1058,1058,1057,262,262,262,262,262,262,262,-1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,-1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1060,1060,1061,--/* block 162 */-1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,-1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1063,1063,1063,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-1064,1064,1064,1064,1064,1064,1064,1064,1065,1064,1064,1064,1064,1064,1064,1064,-1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,-1064,1064,1064,1064,1064,1066,1066,262,262,262,262,1067,1067,1067,1067,1067,-1068,1068,1069,1068,1068,1068,1070,262,262,262,262,262,262,262,262,262,--/* block 163 */-1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,-1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,-1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,-1071,1071,1071,1071,1071,1071,262,262,262,1072,1073,1073,1073,1073,1073,1073,-1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,-1074,1074,1074,1074,1074,1074,262,262,1075,1075,1075,1075,1075,1075,1075,1075,-1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,-1076,1076,1076,262,262,262,262,262,1077,1077,1077,1077,1077,1077,1077,1077,--/* block 164 */-1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,-1078,1078,262,262,262,262,262,262,262,1079,1079,1079,1079,262,262,262,-262,262,262,262,262,262,262,262,262,1080,1080,1080,1080,1080,1080,1080,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 165 */-1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,-1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,-1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,-1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,-1081,1081,1081,1081,1081,1081,1081,1081,1081,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 166 */-1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,-1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,-1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,-1082,1082,1082,262,262,262,262,262,262,262,262,262,262,262,262,262,-1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,-1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,-1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,-1083,1083,1083,262,262,262,262,262,262,262,1084,1084,1084,1084,1084,1084,--/* block 167 */-1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,-1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,-1085,1085,1086,1086,1087,1087,1087,1087,302,302,302,302,302,302,302,302,-1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,302,302,302,302,302,302,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 168 */-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 169 */-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,-1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,262,--/* block 170 */-1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,-1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,-1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,262,1091,1091,1092,262,262,-1090,1090,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 171 */-1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,-1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1094,1094,1094,-1094,1094,1094,1094,1094,1094,1094,1093,262,262,262,262,262,262,262,262,-1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,-1095,1095,1095,1095,1095,1095,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,-1096,1097,1097,1097,1097,1098,1098,1098,1098,1098,302,302,302,302,302,302,-302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,-1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,--/* block 172 */-1099,1099,1100,1100,1100,1100,1101,1101,1101,1101,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,-1102,1102,1102,1102,1102,1103,1103,1103,1103,1103,1103,1103,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,-1104,1104,1104,1104,1104,1104,1104,262,262,262,262,262,262,262,262,262,--/* block 173 */-1105,1106,1105,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,-1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,-1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,-1107,1107,1107,1107,1107,1107,1107,1107,1106,1106,1106,1106,1106,1106,1106,1106,-1106,1106,1106,1106,1106,1106,1108,1109,1109,1110,1110,1110,1110,1110,163,163,-163,163,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,-1111,1111,1111,1111,1111,1111,1112,1112,1112,1112,1112,1112,1112,1112,1112,1112,-1108,1107,1107,1106,1106,1107,163,163,163,163,163,163,163,163,163,1113,--/* block 174 */-1114,1114,1115,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,-1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,-1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,-1115,1115,1115,1117,1117,1117,1117,1115,1115,1118,1119,1120,1120,1121,1122,1122,-1122,1122,1117,163,163,163,163,163,163,163,163,163,163,1121,163,163,-1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,-1123,1123,1123,1123,1123,1123,1123,1123,1123,163,163,163,163,163,163,163,-1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,163,163,163,163,163,163,--/* block 175 */-1125,1125,1125,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,-1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,-1126,1126,1126,1126,1126,1126,1126,1125,1125,1125,1125,1125,1127,1125,1125,1125,-1125,1125,1125,1128,1128,163,1129,1129,1129,1129,1129,1129,1129,1129,1129,1129,-1130,1131,1131,1131,1126,1127,1127,1126,163,163,163,163,163,163,163,163,-1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,-1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,-1132,1132,1132,1133,1134,1134,1132,163,163,163,163,163,163,163,163,163,--/* block 176 */-1135,1135,1136,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,-1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,-1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,-1137,1137,1137,1136,1136,1136,1135,1135,1135,1135,1135,1135,1135,1135,1135,1136,-1138,1137,1139,1139,1137,1140,1140,1141,1141,1142,1143,1143,1143,1140,1136,1135,-1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1137,1141,1137,1141,1140,1140,-163,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,-1145,1145,1145,1145,1145,163,163,163,163,163,163,163,163,163,163,163,--/* block 177 */-1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,-1146,1146,163,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,-1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1147,1147,1147,1148,-1148,1148,1147,1147,1148,1149,1150,1148,1151,1151,1152,1151,1151,1153,1148,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 178 */-1154,1154,1154,1154,1154,1154,1154,163,1154,163,1154,1154,1154,1154,163,1154,-1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,163,1154,-1154,1154,1154,1154,1154,1154,1154,1154,1154,1155,163,163,163,163,163,163,-1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,-1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,-1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1157,-1158,1158,1158,1157,1157,1157,1157,1157,1157,1159,1160,163,163,163,163,163,-1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,163,163,163,163,163,163,--/* block 179 */-1162,1163,1164,1165,163,1166,1166,1166,1166,1166,1166,1166,1166,163,163,1166,-1166,163,163,1166,1166,1166,1166,1166,1166,1166,1166,1166,1166,1166,1166,1166,-1166,1166,1166,1166,1166,1166,1166,1166,1166,163,1166,1166,1166,1166,1166,1166,-1166,163,1166,1166,163,1166,1166,1166,1166,1166,163,1167,1168,1166,1169,1164,-1162,1164,1164,1164,1164,163,163,1164,1164,163,163,1164,1164,1170,163,163,-1166,163,163,163,163,163,163,1169,163,163,163,163,163,1171,1166,1166,-1166,1166,1164,1164,163,163,1172,1172,1172,1172,1172,1172,1172,163,163,163,-1172,1172,1172,1172,1172,163,163,163,163,163,163,163,163,163,163,163,--/* block 180 */-1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,-1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,-1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,-1173,1173,1173,1173,1173,1174,1174,1174,1175,1175,1175,1175,1175,1175,1175,1175,-1174,1174,1176,1175,1175,1174,1177,1173,1173,1173,1173,1178,1178,1179,1180,1180,-1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1179,1179,163,1180,1182,1173,-1173,1173,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 181 */-1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,-1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,-1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,-1184,1185,1185,1186,1186,1186,1186,1186,1186,1185,1186,1185,1185,1184,1185,1186,-1186,1185,1187,1188,1183,1183,1189,1183,163,163,163,163,163,163,163,163,-1190,1190,1190,1190,1190,1190,1190,1190,1190,1190,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 182 */-1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,-1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,-1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1192,-1193,1193,1194,1194,1194,1194,163,163,1193,1193,1193,1193,1194,1194,1193,1195,-1196,1197,1198,1198,1199,1199,1200,1200,1200,1198,1198,1198,1198,1198,1198,1198,-1198,1198,1198,1198,1198,1198,1198,1198,1191,1191,1191,1191,1194,1194,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 183 */-1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,-1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,-1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,-1202,1202,1202,1203,1203,1203,1203,1203,1203,1203,1203,1202,1202,1203,1202,1204,-1203,1205,1205,1206,1201,163,163,163,163,163,163,163,163,163,163,163,-1207,1207,1207,1207,1207,1207,1207,1207,1207,1207,163,163,163,163,163,163,-530,530,530,530,530,530,530,530,530,530,530,530,530,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 184 */-1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,-1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,-1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1209,1210,1209,1210,1210,-1209,1209,1209,1209,1209,1209,1211,1212,1208,1213,163,163,163,163,163,163,-1214,1214,1214,1214,1214,1214,1214,1214,1214,1214,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 185 */-1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,-1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,163,163,1216,1216,1216,-1217,1217,1216,1216,1216,1216,1218,1216,1216,1216,1216,1219,163,163,163,163,-1220,1220,1220,1220,1220,1220,1220,1220,1220,1220,1221,1221,1222,1222,1222,1223,-1215,1215,1215,1215,1215,1215,1215,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 186 */-1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,-1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,-1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1225,1225,1225,1226,-1226,1226,1226,1226,1226,1226,1226,1226,1225,1227,1228,1229,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 187 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,-1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,-1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,-1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,-1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1233,1233,1233,1233,1233,1233,-1233,1233,1233,163,163,163,163,163,163,163,163,163,163,163,163,1234,--/* block 188 */-1235,1235,1235,1235,1235,1235,1235,163,163,1235,163,163,1235,1235,1235,1235,-1235,1235,1235,1235,163,1235,1235,163,1235,1235,1235,1235,1235,1235,1235,1235,-1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,-1236,1237,1237,1237,1237,1237,163,1237,1237,163,163,1238,1238,1239,1240,1241,-1237,1241,1237,1242,1243,1244,1243,163,163,163,163,163,163,163,163,163,-1245,1245,1245,1245,1245,1245,1245,1245,1245,1245,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 189 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1246,1246,1246,1246,1246,1246,1246,1246,163,163,1246,1246,1246,1246,1246,1246,-1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,-1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,-1246,1247,1247,1247,1248,1248,1248,1248,163,163,1248,1248,1247,1247,1247,1247,-1249,1246,1250,1246,1247,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 190 */-1251,1252,1252,1252,1252,1252,1252,1253,1253,1252,1252,1251,1251,1251,1251,1251,-1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,-1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,-1251,1251,1251,1254,1255,1252,1252,1252,1252,1256,1257,1252,1252,1252,1252,1258,-1258,1258,1259,1259,1258,1258,1258,1255,163,163,163,163,163,163,163,163,-1260,1261,1261,1261,1261,1261,1261,1262,1262,1261,1261,1261,1260,1260,1260,1260,-1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,-1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,--/* block 191 */-1260,1260,1260,1260,1263,1263,1263,1263,1263,1263,1261,1261,1261,1261,1261,1261,-1261,1261,1261,1261,1261,1261,1261,1262,1264,1265,1266,1267,1267,1260,1266,1266,-1266,1268,1268,163,163,163,163,163,163,163,163,163,163,163,163,163,-495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,-1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,-1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,-1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,-1269,1269,1269,1269,1269,1269,1269,1269,1269,163,163,163,163,163,163,163,--/* block 192 */-1270,1270,1270,1270,1270,1270,1270,1270,1270,163,1270,1270,1270,1270,1270,1270,-1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,-1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1271,-1272,1272,1272,1272,1272,1272,1272,163,1272,1272,1272,1272,1272,1272,1271,1273,-1270,1274,1274,1275,1276,1276,163,163,163,163,163,163,163,163,163,163,-1277,1277,1277,1277,1277,1277,1277,1277,1277,1277,1278,1278,1278,1278,1278,1278,-1278,1278,1278,1278,1278,1278,1278,1278,1278,1278,1278,1278,1278,163,163,163,-1279,1280,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,--/* block 193 */-1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,-163,163,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,-1282,1282,1282,1282,1282,1282,1282,1282,163,1283,1282,1282,1282,1282,1282,1282,-1282,1283,1282,1282,1283,1282,1282,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 194 */-1284,1284,1284,1284,1284,1284,1284,163,1284,1284,163,1284,1284,1284,1284,1284,-1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,-1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,-1284,1285,1285,1285,1285,1285,1285,163,163,163,1285,163,1285,1285,163,1285,-1285,1285,1286,1285,1287,1287,1288,1285,163,163,163,163,163,163,163,163,-1289,1289,1289,1289,1289,1289,1289,1289,1289,1289,163,163,163,163,163,163,-1290,1290,1290,1290,1290,1290,163,1290,1290,163,1290,1290,1290,1290,1290,1290,-1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,--/* block 195 */-1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1291,1291,1291,1291,1291,163,-1292,1292,163,1291,1291,1292,1291,1293,1290,163,163,163,163,163,163,163,-1294,1294,1294,1294,1294,1294,1294,1294,1294,1294,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 196 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,-1295,1295,1295,1296,1296,1297,1297,1298,1298,163,163,163,163,163,163,163,--/* block 197 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-842,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,-388,388,1299,388,1299,390,390,390,390,390,390,390,390,391,391,391,-391,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,-390,390,163,163,163,163,163,163,163,163,163,163,163,163,163,1300,--/* block 198 */-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,--/* block 199 */-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 200 */-1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,-1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,-1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,-1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,-1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,-1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,-1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,163,-1303,1303,1303,1303,1303,163,163,163,163,163,163,163,163,163,163,163,--/* block 201 */-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,-1301,1301,1301,1301,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 202 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,-1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,-1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,-1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,-1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,-1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,-1304,1305,1305,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 203 */-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,--/* block 204 */-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,-1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,163,-1307,1307,1307,1307,1307,1307,1307,1307,1307,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 205 */-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,--/* block 206 */-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,-1308,1308,1308,1308,1308,1308,1308,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 207 */-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,--/* block 208 */-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,-858,858,858,858,858,858,858,858,858,163,163,163,163,163,163,163,-1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,-1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,163,-1310,1310,1310,1310,1310,1310,1310,1310,1310,1310,163,163,163,163,1311,1311,-1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,--/* block 209 */-1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,-1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,-1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,-1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,163,-1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,163,163,163,163,163,163,-1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,-1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,163,163,-1315,1315,1315,1315,1315,1316,163,163,163,163,163,163,163,163,163,163,--/* block 210 */-1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,-1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,-1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,-1318,1318,1318,1318,1318,1318,1318,1319,1319,1320,1321,1321,1322,1322,1322,1322,-1323,1323,1324,1324,1319,1322,163,163,163,163,163,163,163,163,163,163,-1325,1325,1325,1325,1325,1325,1325,1325,1325,1325,163,1326,1326,1326,1326,1326,-1326,1326,163,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,-1317,1317,1317,1317,1317,1317,1317,1317,163,163,163,163,163,1317,1317,1317,--/* block 211 */-1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 212 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,-1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,-1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,-1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,--/* block 213 */-1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,-1329,1329,1329,1329,1329,1329,1329,1330,1331,1332,1332,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 214 */-1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,-1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,-1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,-1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,-1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,163,163,163,163,1334,-1333,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,-1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,-1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,--/* block 215 */-1335,1335,1335,1335,1335,1335,1335,1335,163,163,163,163,163,163,163,1336,-1336,1336,1336,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1338,1339,1340,799,1341,163,163,163,163,163,163,163,163,163,163,163,-1342,1342,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 216 */-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,--/* block 217 */-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,-1343,1343,1343,1343,1343,1343,1343,1343,163,163,163,163,163,163,163,163,--/* block 218 */-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,--/* block 219 */-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,-1344,1344,1344,1344,1344,1344,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 220 */-1343,1343,1343,1343,1343,1343,1343,1343,1343,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 221 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1345,1345,1345,1345,163,1345,1345,1345,1345,1345,1345,1345,163,1345,1345,163,--/* block 222 */-824,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,--/* block 223 */-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,--/* block 224 */-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,-824,824,824,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-819,819,819,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,824,824,824,824,163,163,163,163,163,163,163,163,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,--/* block 225 */-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,--/* block 226 */-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,-1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,163,163,163,163,--/* block 227 */-1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,-1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,-1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,-1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,-1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,-1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,-1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,163,163,163,163,163,-1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,163,163,163,--/* block 228 */-1347,1347,1347,1347,1347,1347,1347,1347,1347,163,163,163,163,163,163,163,-1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,163,163,1348,1349,1350,1351,-1352,1352,1352,1352,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 229 */-154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,-154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,-154,154,154,154,154,154,154,154,154,154,154,154,154,154,163,163,-154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,-154,154,154,154,154,154,154,163,163,163,163,163,163,163,163,163,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,--/* block 230 */-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 231 */-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,--/* block 232 */-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,163,163,163,163,163,163,163,163,163,163,--/* block 233 */-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,163,163,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,1353,1354,154,154,154,460,460,460,1355,1356,1356,-1356,1356,1356, 51, 51, 51, 51, 51, 51, 51, 51,154,154,154,154,154,--/* block 234 */-154,154,154,460,460,154,154,154,154,154,154,154,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,154,154,154,154,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,723,723,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 235 */-1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,-1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,-1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,-1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,-1002,1002,1357,1357,1357,1002,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 236 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,-835,835,835,835,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 237 */-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,163,163,163,163,163,163,163,163,163,-832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,-832,832,835,835,835,835,835,835,835,163,163,163,163,163,163,163,--/* block 238 */-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,725,725,725,725,725,725,-725,725,736,736,725,725,725,725,725,725,725,725,725,725,725,725,-725,725,725,725,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,725,725,-725,725,725,725,725,163,736,736,725,725,725,725,725,725,725,725,-725,725,725,725,725,725,725,725,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,--/* block 239 */-724,724,725,725,725,725,725,725,725,725,736,736,725,725,725,725,-725,725,725,725,725,725,725,725,725,725,725,725,724,163,724,724,-163,163,724,163,163,724,724,163,163,724,724,724,724,163,724,724,-724,724,724,724,724,724,725,725,725,725,163,725,163,725,736,736,-725,725,725,725,163,725,725,725,725,725,725,725,725,725,725,725,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,725,725,725,725,725,725,-725,725,736,736,725,725,725,725,725,725,725,725,725,725,725,725,--/* block 240 */-725,725,725,725,724,724,163,724,724,724,724,163,163,724,724,724,-724,724,724,724,724,163,724,724,724,724,724,724,724,163,725,725,-725,725,725,725,725,725,736,736,725,725,725,725,725,725,725,725,-725,725,725,725,725,725,725,725,724,724,163,724,724,724,724,163,-724,724,724,724,724,163,724,163,163,163,724,724,724,724,724,724,-724,163,725,725,725,725,725,725,725,725,736,736,725,725,725,725,-725,725,725,725,725,725,725,725,725,725,725,725,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,--/* block 241 */-724,724,724,724,724,724,725,725,725,725,725,725,725,725,736,736,-725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,725,725,725,725,725,725,-725,725,736,736,725,725,725,725,725,725,725,725,725,725,725,725,-725,725,725,725,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,725,725,-725,725,725,725,725,725,736,736,725,725,725,725,725,725,725,725,--/* block 242 */-725,725,725,725,725,725,725,725,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,725,725,725,725,725,725,725,725,736,736,725,725,725,725,-725,725,725,725,725,725,725,725,725,725,725,725,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,725,725,725,725,725,725,725,725,736,736,-725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,--/* block 243 */-724,724,724,724,724,724,724,724,724,724,725,725,725,725,725,725,-725,725,736,736,725,725,725,725,725,725,725,725,725,725,725,725,-725,725,725,725,725,725,163,163,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,-724,1358,725,725,725,725,725,725,725,725,725,725,725,725,725,725,-725,725,725,725,725,725,725,725,725,725,725,715,725,725,725,725,-725,725,724,724,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,1358,725,725,725,725,--/* block 244 */-725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,-725,725,725,725,725,715,725,725,725,725,725,725,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,1358,725,725,725,725,725,725,725,725,725,725,-725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,715,-725,725,725,725,725,725,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,1358,-725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,--/* block 245 */-725,725,725,725,725,725,725,725,725,715,725,725,725,725,725,725,-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,-724,724,724,724,724,724,724,724,724,1358,725,725,725,725,725,725,-725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,-725,725,725,715,725,725,725,725,725,725,724,725,163,163,1359,1359,-1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,-1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,-1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,--/* block 246 */-1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,-1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,-1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,-1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,-1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,-1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,-1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,-1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,--/* block 247 */-1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,-1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,-1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,-1361,1361,1361,1361,1361,1361,1361,1360,1360,1360,1360,1361,1361,1361,1361,1361,-1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,-1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,-1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1360,1360,1360,-1360,1360,1360,1360,1360,1361,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,--/* block 248 */-1360,1360,1360,1360,1361,1360,1360,1362,1363,1362,1362,1364,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,1361,1361,1361,1361,1361,-163,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 249 */- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 92, 70, 70, 70, 70, 70,- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,643, 70, 70, 70, 70,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 250 */-1365,1365,1365,1365,1365,1365,1365,163,1365,1365,1365,1365,1365,1365,1365,1365,-1365,1365,1365,1365,1365,1365,1365,1365,1365,163,163,1365,1365,1365,1365,1365,-1365,1365,163,1365,1365,163,1365,1365,1365,1365,1365,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 251 */-1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,-1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,-1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,163,163,163,-1367,1367,1367,1367,1367,1367,1367,1368,1368,1368,1368,1368,1369,1369,163,163,-1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,163,163,163,163,1366,1371,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 252 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,-1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1373,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,-1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,-1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1375,1375,1375,1375,-1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,163,163,163,163,163,1377,--/* block 253 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-483,483,483,483,483,483,483,163,483,483,483,483,163,483,483,163,-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,163,--/* block 254 */-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,--/* block 255 */-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,-1378,1378,1378,1378,1378,262,262,1379,1379,1379,1379,1379,1379,1379,1379,1379,-1380,1380,1380,1380,1380,1380,1380,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 256 */-1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,-1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,-1381,1381,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,-1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,-1382,1382,1382,1382,1383,1383,1383,1384,1385,1385,1385,1386,262,262,262,262,-1387,1387,1387,1387,1387,1387,1387,1387,1387,1387,262,262,262,262,1388,1388,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 257 */-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-302,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,--/* block 258 */-1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,-1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,-1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1390,1389,1389,1389,-1391,1389,1389,1389,1389,302,302,302,302,302,302,302,302,302,302,302,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 259 */-302,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,-1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,-1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1390,1389,-1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,302,302,-302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,-262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,--/* block 260 */-1392,1392,1392,1392,302,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,-1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,-302,1392,1392,302,1392,302,302,1392,302,1392,1392,1392,1392,1392,1392,1392,-1392,1392,1392,302,1392,1392,1392,1392,302,1392,302,1392,302,302,302,302,-302,302,1392,302,302,302,302,1392,302,1392,302,1392,302,1392,1392,1392,-302,1392,1392,302,1392,302,302,1392,302,1392,302,1392,302,1392,302,1392,-302,1392,1392,302,1392,302,302,1392,1392,1392,1392,302,1392,1392,1392,1392,-1392,1392,1392,302,1392,1392,1392,1392,302,1392,1392,1392,1392,302,1392,302,--/* block 261 */-1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,302,1392,1392,1392,1392,1392,-1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,302,302,302,302,-302,1392,1392,1392,302,1392,1392,1392,1392,1392,302,1392,1392,1392,1392,1392,-1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,302,302,302,302,-302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,-302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,-302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,-274,274,302,302,302,302,302,302,302,302,302,302,302,302,302,302,--/* block 262 */-1393,1393,1393,1393,1394,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1395,1395,1395,1395,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,--/* block 263 */-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1395,-1395,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1395,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1394,-1395,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,--/* block 264 */- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 58, 58,1393,1393,1393,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,1393,-1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,-1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,460,460,460,460,460,460,-1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,-1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,723,723,1393,1393,1393,1393,-1397,1397,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1397,1397,--/* block 265 */-1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,460,460,460,460,1398,460,-460,1398,1398,1398,1398,1398,1398,1398,1398,1398,1398,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,1393,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,-1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,--/* block 266 */-1400,1398,1401,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-460,460,460,460,460,460,460,460,460,460,1398,460,460,460,460,460,-460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,1398,-460,460,1398,1398,1398,1398,1398,1401,1398,1398,1398,460,1395,1395,1395,1395,-460,460,460,460,460,460,460,460,460,1395,1395,1395,1395,1395,1395,1395,-1402,1402,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1393,1393,1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,--/* block 267 */-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,--/* block 268 */-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,727,1393,1393,727,727,727,727,727,727,727,727,727,1394,1394,1394,-1394,1394,1394,1394,1394,1394,727,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,727,1394,1394,--/* block 269 */-1394,1394,1394,1394,1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1393,1393,727,727,1393,727,727,727,1393,1393,727,727,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1403,1403,1403,1394,1394,1403,1394,1394,1403,1404,1404,727,727,1394,-1394,1394,1394,1394,727,727,727,727,727,727,727,727,727,727,727,727,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1393,1393,727,1394,727,1393,727,1394,1394,1394,1405,1405,1405,1405,1405,--/* block 270 */-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,727,-1394,727,1403,1403,1394,1394,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,-1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,-1403,1403,1403,1403,1403,1403,1403,1403,1403,1394,1394,1394,1403,1394,1394,1394,--/* block 271 */-1394,1403,1403,1403,1394,1403,1403,1403,1394,1394,1394,1394,1394,1394,1394,1403,-1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1403,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,727,1393,1394,--/* block 272 */-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,723,723,-723,723,723,723,723,723,1393,1393,1393,727,727,1394,1394,1394,1394,1393,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1393,1393,1393,1393,1393,1393,1393,727,-727,1393,1393,727,1404,1404,727,727,727,727,1403,1393,1393,1393,1393,1393,--/* block 273 */-1393,1393,1393,1393,1393,1393,1393,727,1393,1393,727,727,727,727,1393,1393,-1404,1393,1393,1393,1393,1403,1403,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1394,727,1393,1393,727,1393,1393,1393,1393,1393,1393,1393,-1393,727,727,1393,1393,1393,1393,1393,1393,1393,1393,1393,727,1393,1393,1393,-1393,1393,727,727,727,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,727,727,727,1393,1393,1393,1393,1393,1393,1393,1393,727,727,727,1393,-1393,727,1393,727,1393,1393,1393,1393,727,1393,1393,1393,1393,1393,1393,727,-1393,1393,1393,727,1393,1393,1393,1393,1393,1393,727,1394,1394,1394,1394,1394,--/* block 274 */-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1403,1403,1403,1394,1394,1394,1403,1403,1403,1403,1403,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,--/* block 275 */-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1403,1403,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1403,1394,1394,1394,1394,1394,1393,1393,1393,1393,1393,727,1403,727,727,727,-1394,1394,1394,1393,1393,1394,1394,1394,1395,1395,1395,1395,1395,1394,1394,1394,-727,727,727,727,727,727,1393,1393,1393,727,1393,1394,1394,1395,1395,1395,-727,1393,1393,727,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,--/* block 276 */-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,--/* block 277 */-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,-1394,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,--/* block 278 */-723,723,723,723,723,723,723,723,723,723,723,723,1395,1395,1395,1395,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,1395,1395,1395,1395,1395,1395,1395,1395,-723,723,723,723,723,723,723,723,723,723,1395,1395,1395,1395,1395,1395,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,--/* block 279 */-723,723,723,723,723,723,723,723,1395,1395,1395,1395,1395,1395,1395,1395,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,1395,1395,-1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,--/* block 280 */-723,723,723,723,723,723,723,723,723,723,723,723,1403,1394,1394,1403,-1394,1394,1394,1394,1394,1394,1394,1394,1403,1403,1403,1403,1403,1403,1403,1403,-1394,1394,1394,1394,1394,1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1394,723,1403,1403,1403,1394,-1394,1394,1394,1394,1394,1394,723,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,--/* block 281 */-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1406,1406,1406,1406,1394,1403,1403,1394,1403,1403,1394,1403,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1403,1403,1403,-1394,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,--/* block 282 */-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,-1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1395,1395,-1394,1394,1394,1394,1394,1395,1395,1395,1394,1394,1394,1394,1394,1395,1395,1395,--/* block 283 */-1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,1395,-1394,1394,1394,1403,1403,1403,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,1395,1395,-1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,1395,1395,1395,1395,-1403,1403,1403,1403,1403,1403,1403,1395,1395,1395,1395,1395,1395,1395,1395,1395,--/* block 284 */-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,--/* block 285 */-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,163,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,-723,723,723,723,723,723,723,723,723,723,723,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,163,163,163,163,163,163,--/* block 286 */-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,-1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,958,958,--/* block 287 */-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 288 */-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,163,163,163,163,163,163,163,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,--/* block 289 */-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,163,163,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,--/* block 290 */-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,--/* block 291 */-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 292 */-953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,-953,953,953,953,953,953,953,953,953,953,953,953,953,953,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 293 */-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,958,958,--/* block 294 */-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,-838,838,838,838,838,838,838,838,838,838,838,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,-163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,--/* block 295 */-707,712,707,707,707,707,707,707,707,707,707,707,707,707,707,707,-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,-1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,-1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,-1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,-1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,-1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,-1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,--/* block 296 */-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,--/* block 297 */-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,--/* block 298 */-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,--/* block 299 */-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,-952,952,952,952,952,952,952,952,952,952,952,952,952,952,958,958,+const ucd_record PRIV(ucd_records)[] = {{0,0,0,0,0,0,0}};+const uint16_t PRIV(ucd_stage1)[] = {0};+const uint16_t PRIV(ucd_stage2)[] = {0};+const uint32_t PRIV(ucd_caseless_sets)[] = {0};+#else++/* Total size: 112564 bytes, block size: 128. */++const char *PRIV(unicode_version) = "15.0.0";++/* When recompiling tables with a new Unicode version, please check the types+in this structure definition with those in pcre2_internal.h (the actual field+names will be different).++typedef struct {+uint8_t property_0;+uint8_t property_1;+uint8_t property_2;+uint8_t property_3;+int32_t property_4;+uint16_t property_5;+uint16_t property_6;+} ucd_record;+*/++/* 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. */++#if PCRE2_CODE_UNIT_WIDTH == 32+const ucd_record PRIV(dummy_ucd_record)[] = {{+ ucp_Unknown, /* script */+ ucp_Cn, /* type unassigned */+ ucp_gbOther, /* grapheme break property */+ 0, /* case set */+ 0, /* other case */+ 0 | (ucp_bidiL << UCD_BIDICLASS_SHIFT), /* script extension and bidi class */+ 0, /* bool properties offset */+ }};+#endif++/* This table contains lists of characters that are caseless sets of+more than one character. Each list is terminated by NOTACHAR. */++const uint32_t PRIV(ucd_caseless_sets)[] = {+ NOTACHAR,+ 0x0053, 0x0073, 0x017f, NOTACHAR,+ 0x01c4, 0x01c5, 0x01c6, NOTACHAR,+ 0x01c7, 0x01c8, 0x01c9, NOTACHAR,+ 0x01ca, 0x01cb, 0x01cc, NOTACHAR,+ 0x01f1, 0x01f2, 0x01f3, NOTACHAR,+ 0x0345, 0x0399, 0x03b9, 0x1fbe, NOTACHAR,+ 0x00b5, 0x039c, 0x03bc, NOTACHAR,+ 0x03a3, 0x03c2, 0x03c3, NOTACHAR,+ 0x0392, 0x03b2, 0x03d0, NOTACHAR,+ 0x0398, 0x03b8, 0x03d1, 0x03f4, NOTACHAR,+ 0x03a6, 0x03c6, 0x03d5, NOTACHAR,+ 0x03a0, 0x03c0, 0x03d6, NOTACHAR,+ 0x039a, 0x03ba, 0x03f0, NOTACHAR,+ 0x03a1, 0x03c1, 0x03f1, NOTACHAR,+ 0x0395, 0x03b5, 0x03f5, NOTACHAR,+ 0x0412, 0x0432, 0x1c80, NOTACHAR,+ 0x0414, 0x0434, 0x1c81, NOTACHAR,+ 0x041e, 0x043e, 0x1c82, NOTACHAR,+ 0x0421, 0x0441, 0x1c83, NOTACHAR,+ 0x0422, 0x0442, 0x1c84, 0x1c85, NOTACHAR,+ 0x042a, 0x044a, 0x1c86, NOTACHAR,+ 0x0462, 0x0463, 0x1c87, NOTACHAR,+ 0x1e60, 0x1e61, 0x1e9b, NOTACHAR,+ 0x03a9, 0x03c9, 0x2126, NOTACHAR,+ 0x004b, 0x006b, 0x212a, NOTACHAR,+ 0x00c5, 0x00e5, 0x212b, NOTACHAR,+ 0x1c88, 0xa64a, 0xa64b, NOTACHAR,+};++/* When #included in pcre2test, we don't need the table of digit sets, nor the+the large main UCD tables. */++#ifndef PCRE2_PCRE2TEST++/* This table lists the code points for the '9' characters in each set of+decimal digits. It is used to ensure that all the digits in a script run come+from the same set. */++const uint32_t PRIV(ucd_digit_sets)[] = {+ 68, /* Number of subsequent values */+ 0x00039, 0x00669, 0x006f9, 0x007c9, 0x0096f, 0x009ef, 0x00a6f, 0x00aef,+ 0x00b6f, 0x00bef, 0x00c6f, 0x00cef, 0x00d6f, 0x00def, 0x00e59, 0x00ed9,+ 0x00f29, 0x01049, 0x01099, 0x017e9, 0x01819, 0x0194f, 0x019d9, 0x01a89,+ 0x01a99, 0x01b59, 0x01bb9, 0x01c49, 0x01c59, 0x0a629, 0x0a8d9, 0x0a909,+ 0x0a9d9, 0x0a9f9, 0x0aa59, 0x0abf9, 0x0ff19, 0x104a9, 0x10d39, 0x1106f,+ 0x110f9, 0x1113f, 0x111d9, 0x112f9, 0x11459, 0x114d9, 0x11659, 0x116c9,+ 0x11739, 0x118e9, 0x11959, 0x11c59, 0x11d59, 0x11da9, 0x11f59, 0x16a69,+ 0x16ac9, 0x16b59, 0x1d7d7, 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e149,+ 0x1e2f9, 0x1e4f9, 0x1e959, 0x1fbf9,+};++/* This vector is a list of script bitsets for the Script Extension property.+The number of 32-bit words in each bitset is #defined in pcre2_ucp.h as+ucd_script_sets_item_size. */++const uint32_t PRIV(ucd_script_sets)[] = {+ 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000080u, 0x00000000u, 0x00000000u,+ 0x00000040u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x00004000u, 0x00000000u,+ 0x00000002u, 0x00000000u, 0x00000000u,+ 0x00800000u, 0x00000000u, 0x00000000u,+ 0x00000001u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x00000000u, 0x00000001u,+ 0x00000010u, 0x00000000u, 0x00000000u,+ 0x00000008u, 0x00000004u, 0x00000000u,+ 0x00000008u, 0x40000000u, 0x00000000u,+ 0x00000008u, 0x00000040u, 0x00000000u,+ 0x00000018u, 0x00000000u, 0x00000000u,+ 0x00000028u, 0x00000000u, 0x00000000u,+ 0x000000c0u, 0x00000000u, 0x00000000u,+ 0x00c00000u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x00000102u, 0x00000000u,+ 0x80000000u, 0x00000001u, 0x00000000u,+ 0x00000004u, 0x00000008u, 0x00000000u,+ 0x00000005u, 0x00000000u, 0x00000000u,+ 0x00000004u, 0x00200000u, 0x00000000u,+ 0x00000014u, 0x00000000u, 0x00000000u,+ 0x00000040u, 0x00008000u, 0x00000000u,+ 0x00000040u, 0x00000000u, 0x00000001u,+ 0x00000040u, 0x00001000u, 0x00000000u,+ 0x00000840u, 0x00000000u, 0x00000000u,+ 0x00020001u, 0x00000000u, 0x00000000u,+ 0x00000800u, 0x00008000u, 0x00000000u,+ 0x00000200u, 0x00010000u, 0x00000000u,+ 0x00000100u, 0x02000000u, 0x00000000u,+ 0x00800001u, 0x00000000u, 0x00000000u,+ 0x00300000u, 0x00000000u, 0x00000000u,+ 0x00002000u, 0x00000000u, 0x00000001u,+ 0x00080001u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x00080000u, 0x00000008u,+ 0x00080000u, 0x00000020u, 0x00000000u,+ 0x00000038u, 0x00000000u, 0x00000000u,+ 0x00000028u, 0x00000000u, 0x00000002u,+ 0x00000080u, 0x00000810u, 0x00000000u,+ 0x40010000u, 0x00000800u, 0x00000000u,+ 0x80000000u, 0x00000001u, 0x00000004u,+ 0x80000000u, 0x00020001u, 0x00000000u,+ 0x00002040u, 0x00008000u, 0x00000000u,+ 0x00000041u, 0x00008000u, 0x00000000u,+ 0x00b00000u, 0x00000000u, 0x00000000u,+ 0x00010001u, 0x00000080u, 0x00000000u,+ 0x000020c0u, 0x00008000u, 0x00000000u,+ 0x1e000000u, 0x00000000u, 0x00000000u,+ 0x00000040u, 0x10040200u, 0x00000000u,+ 0x00f40000u, 0x00000000u, 0x00000000u,+ 0x00000038u, 0x40000040u, 0x00000002u,+ 0x01f40000u, 0x00000000u, 0x00000000u,+ 0x00007c40u, 0x00000000u, 0x00000000u,+ 0x00000038u, 0x44000040u, 0x00000002u,+ 0x000034c0u, 0x01008000u, 0x00000001u,+ 0x00000018u, 0xc4480400u, 0x00000008u,+ 0x00000340u, 0x11952200u, 0x00000000u,+ 0x00007fc1u, 0x01008000u, 0x00000000u,+ 0x00007fc1u, 0x01009000u, 0x00000000u,+ 0x00002340u, 0x11952200u, 0x00000001u,+ 0x00006340u, 0x11952200u, 0x00000001u,+ 0x0000ffc0u, 0x3984a010u, 0x00000001u,+ 0x2000ffc0u, 0x3984a010u, 0x00000001u,+};++/* This vector is a list of bitsets for Boolean properties. The number of+32_bit words in each bitset is #defined as ucd_boolprop_sets_item_size in+pcre2_ucp.h. */++const uint32_t PRIV(ucd_boolprop_sets)[] = {+ 0x00000000u, 0x00000000u,+ 0x00000001u, 0x00000000u,+ 0x00000001u, 0x00020040u,+ 0x00800001u, 0x00020040u,+ 0x00800001u, 0x00002820u,+ 0x00800001u, 0x00000120u,+ 0x00830001u, 0x00000020u,+ 0x00800001u, 0x00000020u,+ 0x00800021u, 0x00000120u,+ 0x00800011u, 0x00000020u,+ 0x00800001u, 0x00000028u,+ 0x00800001u, 0x00002020u,+ 0x00801001u, 0x00000020u,+ 0x00800021u, 0x00002820u,+ 0x24830003u, 0x00040000u,+ 0x00800021u, 0x00002020u,+ 0x00800011u, 0x00000028u,+ 0x648003c7u, 0x000c8000u,+ 0x608003c5u, 0x000c8000u,+ 0x00808021u, 0x00000028u,+ 0x20800001u, 0x00040000u,+ 0x00808021u, 0x00000020u,+ 0x64800d47u, 0x000c0004u,+ 0x60800d45u, 0x000c0004u,+ 0x60800d45u, 0x000c1004u,+ 0x00000000u, 0x00020040u,+ 0x00800000u, 0x00020000u,+ 0x00800000u, 0x00000020u,+ 0x00808020u, 0x00000000u,+ 0x00a10000u, 0x00000020u,+ 0x60800044u, 0x000c0004u,+ 0x00800010u, 0x00000120u,+ 0x00800000u, 0x00000028u,+ 0x00002020u, 0x00000000u,+ 0x00800000u, 0x00000000u,+ 0x60800dc4u, 0x000c0004u,+ 0x20c08020u, 0x00040000u,+ 0x608003c4u, 0x000c8000u,+ 0x60800d44u, 0x000c0004u,+ 0x60800d44u, 0x000c1004u,+ 0x60804dc4u, 0x000c0004u,+ 0x60800004u, 0x000c0000u,+ 0x608007c4u, 0x000c8000u,+ 0x60800bc4u, 0x000c0000u,+ 0x60808064u, 0x000c0004u,+ 0x60808064u, 0x000c1004u,+ 0x60808024u, 0x000c0000u,+ 0x60c08024u, 0x000c0000u,+ 0x21008020u, 0x00040000u,+ 0x21008de4u, 0x00040004u,+ 0x21002020u, 0x00040000u,+ 0x21000020u, 0x00040000u,+ 0x60808064u, 0x00000004u,+ 0x00800000u, 0x00002000u,+ 0x20800020u, 0x00042000u,+ 0x60800dc4u, 0x000c000cu,+ 0x60800044u, 0x000c8008u,+ 0x60800044u, 0x000c8000u,+ 0x608003c4u, 0x000c8008u,+ 0x00800000u, 0x00000008u,+ 0x01000020u, 0x00000000u,+ 0x00800020u, 0x00000000u,+ 0x00800000u, 0x00002800u,+ 0x00801000u, 0x00000000u,+ 0x21008024u, 0x00040000u,+ 0x21000024u, 0x00040000u,+ 0x00000020u, 0x00000080u,+ 0x00002028u, 0x00000000u,+ 0x60c00024u, 0x000c0000u,+ 0x20800000u, 0x00040000u,+ 0x60804004u, 0x000c0000u,+ 0x60800024u, 0x000c0000u,+ 0x20800004u, 0x00040000u,+ 0x23008020u, 0x00040000u,+ 0x21000004u, 0x00040000u,+ 0x21408020u, 0x00040000u,+ 0x60800004u, 0x00040000u,+ 0x23000024u, 0x00040000u,+ 0x60800004u, 0x000c0002u,+ 0x00800010u, 0x00000000u,+ 0x20808000u, 0x00040000u,+ 0x21004024u, 0x00040000u,+ 0x20808004u, 0x00040000u,+ 0x60800944u, 0x000c0004u,+ 0x60800064u, 0x000c0004u,+ 0x60802004u, 0x000c0000u,+ 0x60800344u, 0x000c8000u,+ 0x22808000u, 0x00040000u,+ 0x22800000u, 0x00040000u,+ 0x00c00000u, 0x00000000u,+ 0x21002020u, 0x00050000u,+ 0x61000024u, 0x000c0000u,+ 0x23000020u, 0x00040000u,+ 0x01008020u, 0x00000000u,+ 0x21408024u, 0x00040000u,+ 0x00808000u, 0x00000000u,+ 0x60800044u, 0x000c1004u,+ 0x60800064u, 0x000c1004u,+ 0x01002020u, 0x00000001u,+ 0x00022020u, 0x00000001u,+ 0x00002028u, 0x00000040u,+ 0x00801000u, 0x00000020u,+ 0x00800020u, 0x00000120u,+ 0x00800000u, 0x00000120u,+ 0x00800020u, 0x00000020u,+ 0x00a10000u, 0x00002820u,+ 0x00800000u, 0x00002820u,+ 0x20800000u, 0x00040008u,+ 0x00800010u, 0x00000020u,+ 0x00002020u, 0x00000008u,+ 0x00002000u, 0x00000000u,+ 0x00006020u, 0x00000000u,+ 0x00801000u, 0x00000008u,+ 0x00800010u, 0x00000008u,+ 0x21000020u, 0x00040008u,+ 0x01020020u, 0x00000000u,+ 0x60800044u, 0x000c000cu,+ 0x60800000u, 0x000c0008u,+ 0x00a10000u, 0x00000000u,+ 0x60800000u, 0x000c0000u,+ 0x60800004u, 0x000c0008u,+ 0x60a10044u, 0x000c0004u,+ 0x60800044u, 0x000c100cu,+ 0x00a10000u, 0x00000028u,+ 0x00800010u, 0x00000028u,+ 0x00801000u, 0x00000028u,+ 0x00b10000u, 0x00000020u,+ 0x00804010u, 0x00000020u,+ 0x00a00000u, 0x00000020u,+ 0x00000000u, 0x00000020u,+ 0x008003c4u, 0x00008000u,+ 0x00a103c4u, 0x00008000u,+ 0x00800d44u, 0x00000004u,+ 0x00b10000u, 0x00000028u,+ 0x00a00000u, 0x00000028u,+ 0x00a90000u, 0x00000020u,+ 0x00b90000u, 0x00000020u,+ 0x00808024u, 0x00000020u,+ 0x00800000u, 0x00002020u,+ 0x00800000u, 0x00000200u,+ 0x08800000u, 0x00000000u,+ 0x10800000u, 0x00000000u,+ 0xe0800004u, 0x000c0000u,+ 0x21008000u, 0x00040000u,+ 0x00a11000u, 0x00000020u,+ 0x60808020u, 0x00000000u,+ 0xe0800004u, 0x000c4000u,+ 0x60808004u, 0x000c0000u,+ 0x60800004u, 0x00000000u,+ 0x00000000u, 0x00000010u,+ 0x21022020u, 0x00050000u,+ 0x00800000u, 0x00000100u,+ 0x00800020u, 0x00002800u,+ 0x00800020u, 0x00002000u,+ 0x00800020u, 0x00000100u,+ 0x24800000u, 0x00040000u,+ 0x648003c4u, 0x000c8000u,+ 0x00808020u, 0x00000008u,+ 0x64800d44u, 0x000c0004u,+ 0x00800010u, 0x00000100u,+ 0x61008024u, 0x00040000u,+ 0x00000020u, 0x00000000u,+ 0x60c00004u, 0x000c0000u,+ 0x21400020u, 0x00040000u,+ 0xa1000020u, 0x00040000u,+ 0x21000000u, 0x00040000u,+ 0x00a00000u, 0x00000000u,+ 0x00b10000u, 0x00000000u,+ 0x00200000u, 0x00000000u,+ 0x00800044u, 0x00008000u,+ 0x00a10044u, 0x00008000u,+ 0x00930000u, 0x00000400u,+ 0x00b90000u, 0x00000000u,+ 0x00a90000u, 0x00000000u,+ 0x00970020u, 0x00000000u,+ 0x00b30000u, 0x00000000u,+ 0x01022020u, 0x00000000u,+};++/* These are the main two-stage UCD tables. The fields in each record are:+script (8 bits), character type (8 bits), grapheme break property (8 bits),+offset to multichar other cases or zero (8 bits), offset to other case or zero+(32 bits, signed), bidi class (5 bits) and script extension (11 bits) packed+into a 16-bit field, and offset in binary properties table (16 bits). */++const ucd_record PRIV(ucd_records)[] = { /* 17076 bytes, record size 12 */+ { 69, 0, 2, 0, 0, 6144, 2, }, /* 0 */+ { 69, 0, 2, 0, 0, 43008, 4, }, /* 1 */+ { 69, 0, 1, 0, 0, 4096, 4, }, /* 2 */+ { 69, 0, 2, 0, 0, 45056, 4, }, /* 3 */+ { 69, 0, 0, 0, 0, 4096, 4, }, /* 4 */+ { 69, 0, 2, 0, 0, 4096, 2, }, /* 5 */+ { 69, 0, 2, 0, 0, 43008, 2, }, /* 6 */+ { 69, 29, 12, 0, 0, 45056, 6, }, /* 7 */+ { 69, 21, 12, 0, 0, 28672, 8, }, /* 8 */+ { 69, 21, 12, 0, 0, 28672, 10, }, /* 9 */+ { 69, 21, 12, 0, 0, 14336, 12, }, /* 10 */+ { 69, 23, 12, 0, 0, 14336, 14, }, /* 11 */+ { 69, 21, 12, 0, 0, 14336, 14, }, /* 12 */+ { 69, 21, 12, 0, 0, 28672, 14, }, /* 13 */+ { 69, 21, 12, 0, 0, 28672, 16, }, /* 14 */+ { 69, 22, 12, 0, 0, 28672, 18, }, /* 15 */+ { 69, 18, 12, 0, 0, 28672, 18, }, /* 16 */+ { 69, 21, 12, 0, 0, 28672, 12, }, /* 17 */+ { 69, 25, 12, 0, 0, 12288, 20, }, /* 18 */+ { 69, 21, 12, 0, 0, 8192, 22, }, /* 19 */+ { 69, 17, 12, 0, 0, 12288, 24, }, /* 20 */+ { 69, 21, 12, 0, 0, 8192, 26, }, /* 21 */+ { 69, 21, 12, 0, 0, 8192, 14, }, /* 22 */+ { 69, 13, 12, 0, 0, 10240, 28, }, /* 23 */+ { 69, 21, 12, 0, 0, 8192, 30, }, /* 24 */+ { 69, 21, 12, 0, 0, 28672, 22, }, /* 25 */+ { 69, 25, 12, 0, 0, 28672, 32, }, /* 26 */+ { 69, 25, 12, 0, 0, 28672, 20, }, /* 27 */+ { 0, 9, 12, 0, 32, 18432, 34, }, /* 28 */+ { 0, 9, 12, 0, 32, 18432, 36, }, /* 29 */+ { 0, 9, 12, 100, 32, 18432, 36, }, /* 30 */+ { 0, 9, 12, 1, 32, 18432, 36, }, /* 31 */+ { 69, 24, 12, 0, 0, 28672, 38, }, /* 32 */+ { 69, 16, 12, 0, 0, 28672, 40, }, /* 33 */+ { 69, 24, 12, 0, 0, 28672, 42, }, /* 34 */+ { 0, 5, 12, 0, -32, 18432, 44, }, /* 35 */+ { 0, 5, 12, 0, -32, 18432, 46, }, /* 36 */+ { 0, 5, 12, 0, -32, 18432, 48, }, /* 37 */+ { 0, 5, 12, 100, -32, 18432, 46, }, /* 38 */+ { 0, 5, 12, 1, -32, 18432, 46, }, /* 39 */+ { 69, 0, 2, 0, 0, 6144, 0, }, /* 40 */+ { 69, 0, 2, 0, 0, 4096, 50, }, /* 41 */+ { 69, 29, 12, 0, 0, 8192, 52, }, /* 42 */+ { 69, 21, 12, 0, 0, 28672, 54, }, /* 43 */+ { 69, 23, 12, 0, 0, 14336, 54, }, /* 44 */+ { 69, 26, 12, 0, 0, 28672, 54, }, /* 45 */+ { 69, 24, 12, 0, 0, 28672, 56, }, /* 46 */+ { 69, 26, 14, 0, 0, 28672, 58, }, /* 47 */+ { 0, 7, 12, 0, 0, 18432, 60, }, /* 48 */+ { 69, 20, 12, 0, 0, 28672, 62, }, /* 49 */+ { 69, 25, 12, 0, 0, 28672, 64, }, /* 50 */+ { 69, 1, 2, 0, 0, 6144, 66, }, /* 51 */+ { 69, 26, 12, 0, 0, 14336, 54, }, /* 52 */+ { 69, 25, 12, 0, 0, 14336, 64, }, /* 53 */+ { 69, 15, 12, 0, 0, 10240, 68, }, /* 54 */+ { 69, 5, 12, 26, 775, 18432, 70, }, /* 55 */+ { 69, 21, 12, 0, 0, 28672, 72, }, /* 56 */+ { 69, 19, 12, 0, 0, 28672, 62, }, /* 57 */+ { 69, 15, 12, 0, 0, 28672, 68, }, /* 58 */+ { 0, 9, 12, 0, 32, 18432, 74, }, /* 59 */+ { 0, 9, 12, 104, 32, 18432, 74, }, /* 60 */+ { 0, 5, 12, 0, 7615, 18432, 70, }, /* 61 */+ { 0, 5, 12, 0, -32, 18432, 76, }, /* 62 */+ { 0, 5, 12, 104, -32, 18432, 76, }, /* 63 */+ { 0, 5, 12, 0, 121, 18432, 76, }, /* 64 */+ { 0, 9, 12, 0, 1, 18432, 74, }, /* 65 */+ { 0, 5, 12, 0, -1, 18432, 76, }, /* 66 */+ { 0, 5, 12, 0, -1, 18432, 78, }, /* 67 */+ { 0, 9, 12, 0, 0, 18432, 74, }, /* 68 */+ { 0, 5, 12, 0, 0, 18432, 76, }, /* 69 */+ { 0, 5, 12, 0, 0, 18432, 60, }, /* 70 */+ { 0, 5, 12, 0, 0, 18432, 80, }, /* 71 */+ { 0, 9, 12, 0, -121, 18432, 74, }, /* 72 */+ { 0, 5, 12, 1, 0, 18432, 70, }, /* 73 */+ { 0, 5, 12, 0, 195, 18432, 76, }, /* 74 */+ { 0, 9, 12, 0, 210, 18432, 74, }, /* 75 */+ { 0, 9, 12, 0, 206, 18432, 74, }, /* 76 */+ { 0, 9, 12, 0, 205, 18432, 74, }, /* 77 */+ { 0, 9, 12, 0, 79, 18432, 74, }, /* 78 */+ { 0, 9, 12, 0, 202, 18432, 74, }, /* 79 */+ { 0, 9, 12, 0, 203, 18432, 74, }, /* 80 */+ { 0, 9, 12, 0, 207, 18432, 74, }, /* 81 */+ { 0, 5, 12, 0, 97, 18432, 76, }, /* 82 */+ { 0, 9, 12, 0, 211, 18432, 74, }, /* 83 */+ { 0, 9, 12, 0, 209, 18432, 74, }, /* 84 */+ { 0, 5, 12, 0, 163, 18432, 76, }, /* 85 */+ { 0, 9, 12, 0, 213, 18432, 74, }, /* 86 */+ { 0, 5, 12, 0, 130, 18432, 76, }, /* 87 */+ { 0, 9, 12, 0, 214, 18432, 74, }, /* 88 */+ { 0, 9, 12, 0, 218, 18432, 74, }, /* 89 */+ { 0, 9, 12, 0, 217, 18432, 74, }, /* 90 */+ { 0, 9, 12, 0, 219, 18432, 74, }, /* 91 */+ { 0, 7, 12, 0, 0, 18432, 82, }, /* 92 */+ { 0, 5, 12, 0, 56, 18432, 76, }, /* 93 */+ { 0, 9, 12, 5, 2, 18432, 84, }, /* 94 */+ { 0, 8, 12, 5, 1, 18432, 86, }, /* 95 */+ { 0, 5, 12, 5, -2, 18432, 76, }, /* 96 */+ { 0, 9, 12, 9, 2, 18432, 84, }, /* 97 */+ { 0, 8, 12, 9, 1, 18432, 86, }, /* 98 */+ { 0, 5, 12, 9, -2, 18432, 76, }, /* 99 */+ { 0, 9, 12, 13, 2, 18432, 84, }, /* 100 */+ { 0, 8, 12, 13, 1, 18432, 86, }, /* 101 */+ { 0, 5, 12, 13, -2, 18432, 76, }, /* 102 */+ { 0, 5, 12, 0, -79, 18432, 76, }, /* 103 */+ { 0, 9, 12, 17, 2, 18432, 84, }, /* 104 */+ { 0, 8, 12, 17, 1, 18432, 86, }, /* 105 */+ { 0, 5, 12, 17, -2, 18432, 76, }, /* 106 */+ { 0, 9, 12, 0, -97, 18432, 74, }, /* 107 */+ { 0, 9, 12, 0, -56, 18432, 74, }, /* 108 */+ { 0, 9, 12, 0, -130, 18432, 74, }, /* 109 */+ { 0, 9, 12, 0, 10795, 18432, 74, }, /* 110 */+ { 0, 9, 12, 0, -163, 18432, 74, }, /* 111 */+ { 0, 9, 12, 0, 10792, 18432, 74, }, /* 112 */+ { 0, 5, 12, 0, 10815, 18432, 76, }, /* 113 */+ { 0, 9, 12, 0, -195, 18432, 74, }, /* 114 */+ { 0, 9, 12, 0, 69, 18432, 74, }, /* 115 */+ { 0, 9, 12, 0, 71, 18432, 74, }, /* 116 */+ { 0, 5, 12, 0, 10783, 18432, 76, }, /* 117 */+ { 0, 5, 12, 0, 10780, 18432, 76, }, /* 118 */+ { 0, 5, 12, 0, 10782, 18432, 76, }, /* 119 */+ { 0, 5, 12, 0, -210, 18432, 76, }, /* 120 */+ { 0, 5, 12, 0, -206, 18432, 76, }, /* 121 */+ { 0, 5, 12, 0, -205, 18432, 76, }, /* 122 */+ { 0, 5, 12, 0, -202, 18432, 76, }, /* 123 */+ { 0, 5, 12, 0, -203, 18432, 76, }, /* 124 */+ { 0, 5, 12, 0, 42319, 18432, 76, }, /* 125 */+ { 0, 5, 12, 0, 42315, 18432, 76, }, /* 126 */+ { 0, 5, 12, 0, -207, 18432, 76, }, /* 127 */+ { 0, 5, 12, 0, 42280, 18432, 76, }, /* 128 */+ { 0, 5, 12, 0, 42308, 18432, 76, }, /* 129 */+ { 0, 5, 12, 0, -209, 18432, 78, }, /* 130 */+ { 0, 5, 12, 0, -211, 18432, 76, }, /* 131 */+ { 0, 5, 12, 0, 10743, 18432, 76, }, /* 132 */+ { 0, 5, 12, 0, 42305, 18432, 76, }, /* 133 */+ { 0, 5, 12, 0, 10749, 18432, 76, }, /* 134 */+ { 0, 5, 12, 0, -213, 18432, 76, }, /* 135 */+ { 0, 5, 12, 0, -214, 18432, 76, }, /* 136 */+ { 0, 5, 12, 0, 10727, 18432, 76, }, /* 137 */+ { 0, 5, 12, 0, -218, 18432, 76, }, /* 138 */+ { 0, 5, 12, 0, 42307, 18432, 76, }, /* 139 */+ { 0, 5, 12, 0, 42282, 18432, 76, }, /* 140 */+ { 0, 5, 12, 0, -69, 18432, 76, }, /* 141 */+ { 0, 5, 12, 0, -217, 18432, 76, }, /* 142 */+ { 0, 5, 12, 0, -71, 18432, 76, }, /* 143 */+ { 0, 5, 12, 0, -219, 18432, 76, }, /* 144 */+ { 0, 5, 12, 0, 42261, 18432, 78, }, /* 145 */+ { 0, 5, 12, 0, 42258, 18432, 76, }, /* 146 */+ { 0, 6, 12, 0, 0, 18432, 88, }, /* 147 */+ { 0, 6, 12, 0, 0, 18432, 90, }, /* 148 */+ { 69, 6, 12, 0, 0, 28672, 92, }, /* 149 */+ { 69, 6, 12, 0, 0, 18432, 92, }, /* 150 */+ { 69, 6, 12, 0, 0, 18432, 88, }, /* 151 */+ { 69, 6, 12, 0, 0, 18432, 94, }, /* 152 */+ { 22, 24, 12, 0, 0, 28672, 56, }, /* 153 */+ { 84, 12, 3, 0, 0, 26624, 96, }, /* 154 */+ { 84, 12, 3, 0, 0, 26636, 96, }, /* 155 */+ { 84, 12, 3, 21, 116, 26636, 98, }, /* 156 */+ { 84, 12, 3, 0, 0, 26624, 100, }, /* 157 */+ { 84, 12, 3, 0, 0, 26624, 102, }, /* 158 */+ { 84, 12, 3, 0, 0, 26642, 102, }, /* 159 */+ { 1, 9, 12, 0, 1, 18432, 74, }, /* 160 */+ { 1, 5, 12, 0, -1, 18432, 76, }, /* 161 */+ { 1, 24, 12, 0, 0, 28672, 56, }, /* 162 */+ { 68, 2, 12, 0, 0, 18432, 0, }, /* 163 */+ { 1, 6, 12, 0, 0, 18432, 104, }, /* 164 */+ { 1, 5, 12, 0, 130, 18432, 76, }, /* 165 */+ { 69, 21, 12, 0, 0, 28672, 106, }, /* 166 */+ { 1, 9, 12, 0, 116, 18432, 74, }, /* 167 */+ { 1, 9, 12, 0, 38, 18432, 74, }, /* 168 */+ { 69, 21, 12, 0, 0, 28672, 108, }, /* 169 */+ { 1, 9, 12, 0, 37, 18432, 74, }, /* 170 */+ { 1, 9, 12, 0, 64, 18432, 74, }, /* 171 */+ { 1, 9, 12, 0, 63, 18432, 74, }, /* 172 */+ { 1, 5, 12, 0, 0, 18432, 76, }, /* 173 */+ { 1, 9, 12, 0, 32, 18432, 74, }, /* 174 */+ { 1, 9, 12, 34, 32, 18432, 74, }, /* 175 */+ { 1, 9, 12, 59, 32, 18432, 74, }, /* 176 */+ { 1, 9, 12, 38, 32, 18432, 74, }, /* 177 */+ { 1, 9, 12, 21, 32, 18432, 74, }, /* 178 */+ { 1, 9, 12, 51, 32, 18432, 74, }, /* 179 */+ { 1, 9, 12, 26, 32, 18432, 74, }, /* 180 */+ { 1, 9, 12, 47, 32, 18432, 74, }, /* 181 */+ { 1, 9, 12, 55, 32, 18432, 74, }, /* 182 */+ { 1, 9, 12, 30, 32, 18432, 74, }, /* 183 */+ { 1, 9, 12, 43, 32, 18432, 74, }, /* 184 */+ { 1, 9, 12, 96, 32, 18432, 74, }, /* 185 */+ { 1, 5, 12, 0, -38, 18432, 76, }, /* 186 */+ { 1, 5, 12, 0, -37, 18432, 76, }, /* 187 */+ { 1, 5, 12, 0, -32, 18432, 76, }, /* 188 */+ { 1, 5, 12, 34, -32, 18432, 76, }, /* 189 */+ { 1, 5, 12, 59, -32, 18432, 76, }, /* 190 */+ { 1, 5, 12, 38, -32, 18432, 76, }, /* 191 */+ { 1, 5, 12, 21, -116, 18432, 76, }, /* 192 */+ { 1, 5, 12, 51, -32, 18432, 76, }, /* 193 */+ { 1, 5, 12, 26, -775, 18432, 76, }, /* 194 */+ { 1, 5, 12, 47, -32, 18432, 76, }, /* 195 */+ { 1, 5, 12, 55, -32, 18432, 76, }, /* 196 */+ { 1, 5, 12, 30, 1, 18432, 70, }, /* 197 */+ { 1, 5, 12, 30, -32, 18432, 76, }, /* 198 */+ { 1, 5, 12, 43, -32, 18432, 76, }, /* 199 */+ { 1, 5, 12, 96, -32, 18432, 76, }, /* 200 */+ { 1, 5, 12, 0, -64, 18432, 76, }, /* 201 */+ { 1, 5, 12, 0, -63, 18432, 76, }, /* 202 */+ { 1, 9, 12, 0, 8, 18432, 74, }, /* 203 */+ { 1, 5, 12, 34, -30, 18432, 110, }, /* 204 */+ { 1, 5, 12, 38, -25, 18432, 110, }, /* 205 */+ { 1, 9, 12, 0, 0, 18432, 112, }, /* 206 */+ { 1, 9, 12, 0, 0, 18432, 114, }, /* 207 */+ { 1, 5, 12, 43, -15, 18432, 110, }, /* 208 */+ { 1, 5, 12, 47, -22, 18432, 70, }, /* 209 */+ { 1, 5, 12, 0, -8, 18432, 76, }, /* 210 */+ { 34, 9, 12, 0, 1, 18432, 74, }, /* 211 */+ { 34, 5, 12, 0, -1, 18432, 76, }, /* 212 */+ { 1, 5, 12, 51, -54, 18432, 110, }, /* 213 */+ { 1, 5, 12, 55, -48, 18432, 110, }, /* 214 */+ { 1, 5, 12, 0, 7, 18432, 76, }, /* 215 */+ { 1, 5, 12, 0, -116, 18432, 78, }, /* 216 */+ { 1, 9, 12, 38, -60, 18432, 116, }, /* 217 */+ { 1, 5, 12, 59, -64, 18432, 110, }, /* 218 */+ { 1, 25, 12, 0, 0, 28672, 118, }, /* 219 */+ { 1, 9, 12, 0, -7, 18432, 74, }, /* 220 */+ { 1, 5, 12, 0, 0, 18432, 60, }, /* 221 */+ { 1, 9, 12, 0, -130, 18432, 74, }, /* 222 */+ { 2, 9, 12, 0, 80, 18432, 74, }, /* 223 */+ { 2, 9, 12, 0, 32, 18432, 74, }, /* 224 */+ { 2, 9, 12, 63, 32, 18432, 74, }, /* 225 */+ { 2, 9, 12, 67, 32, 18432, 74, }, /* 226 */+ { 2, 9, 12, 71, 32, 18432, 74, }, /* 227 */+ { 2, 9, 12, 75, 32, 18432, 74, }, /* 228 */+ { 2, 9, 12, 79, 32, 18432, 74, }, /* 229 */+ { 2, 9, 12, 84, 32, 18432, 74, }, /* 230 */+ { 2, 5, 12, 0, -32, 18432, 76, }, /* 231 */+ { 2, 5, 12, 63, -32, 18432, 76, }, /* 232 */+ { 2, 5, 12, 67, -32, 18432, 76, }, /* 233 */+ { 2, 5, 12, 71, -32, 18432, 76, }, /* 234 */+ { 2, 5, 12, 75, -32, 18432, 76, }, /* 235 */+ { 2, 5, 12, 79, -32, 18432, 76, }, /* 236 */+ { 2, 5, 12, 84, -32, 18432, 76, }, /* 237 */+ { 2, 5, 12, 0, -80, 18432, 76, }, /* 238 */+ { 2, 5, 12, 0, -80, 18432, 78, }, /* 239 */+ { 2, 9, 12, 0, 1, 18432, 74, }, /* 240 */+ { 2, 5, 12, 0, -1, 18432, 76, }, /* 241 */+ { 2, 9, 12, 88, 1, 18432, 74, }, /* 242 */+ { 2, 5, 12, 88, -1, 18432, 76, }, /* 243 */+ { 2, 26, 12, 0, 0, 18432, 68, }, /* 244 */+ { 2, 12, 3, 0, 0, 26684, 96, }, /* 245 */+ { 2, 12, 3, 0, 0, 26678, 96, }, /* 246 */+ { 84, 12, 3, 0, 0, 26681, 96, }, /* 247 */+ { 2, 11, 3, 0, 0, 26624, 120, }, /* 248 */+ { 2, 9, 12, 0, 15, 18432, 74, }, /* 249 */+ { 2, 5, 12, 0, -15, 18432, 76, }, /* 250 */+ { 70, 9, 12, 0, 48, 18432, 74, }, /* 251 */+ { 70, 6, 12, 0, 0, 18432, 92, }, /* 252 */+ { 70, 21, 12, 0, 0, 18432, 68, }, /* 253 */+ { 70, 21, 12, 0, 0, 18432, 122, }, /* 254 */+ { 70, 5, 12, 0, 0, 18432, 60, }, /* 255 */+ { 70, 5, 12, 0, -48, 18432, 76, }, /* 256 */+ { 70, 5, 12, 0, 0, 18432, 70, }, /* 257 */+ { 70, 21, 12, 0, 0, 18432, 124, }, /* 258 */+ { 70, 17, 12, 0, 0, 28672, 126, }, /* 259 */+ { 70, 26, 12, 0, 0, 28672, 68, }, /* 260 */+ { 70, 23, 12, 0, 0, 14336, 68, }, /* 261 */+ { 68, 2, 12, 0, 0, 34816, 0, }, /* 262 */+ { 71, 12, 3, 0, 0, 26624, 96, }, /* 263 */+ { 71, 12, 3, 0, 0, 26624, 102, }, /* 264 */+ { 71, 12, 3, 0, 0, 26624, 128, }, /* 265 */+ { 71, 17, 12, 0, 0, 34816, 126, }, /* 266 */+ { 71, 21, 12, 0, 0, 34816, 68, }, /* 267 */+ { 71, 21, 12, 0, 0, 34816, 106, }, /* 268 */+ { 71, 12, 3, 0, 0, 26624, 130, }, /* 269 */+ { 71, 7, 12, 0, 0, 34816, 82, }, /* 270 */+ { 71, 21, 12, 0, 0, 34816, 122, }, /* 271 */+ { 3, 1, 4, 0, 0, 2048, 132, }, /* 272 */+ { 69, 1, 4, 0, 0, 2048, 132, }, /* 273 */+ { 3, 25, 12, 0, 0, 28672, 118, }, /* 274 */+ { 3, 25, 12, 0, 0, 0, 118, }, /* 275 */+ { 3, 21, 12, 0, 0, 14336, 68, }, /* 276 */+ { 3, 23, 12, 0, 0, 0, 68, }, /* 277 */+ { 69, 21, 12, 0, 0, 8342, 106, }, /* 278 */+ { 3, 21, 12, 0, 0, 0, 68, }, /* 279 */+ { 3, 26, 12, 0, 0, 28672, 68, }, /* 280 */+ { 3, 12, 3, 0, 0, 26624, 130, }, /* 281 */+ { 69, 21, 12, 0, 0, 150, 106, }, /* 282 */+ { 3, 1, 2, 0, 0, 108, 134, }, /* 283 */+ { 3, 21, 12, 0, 0, 0, 124, }, /* 284 */+ { 69, 21, 12, 0, 0, 159, 124, }, /* 285 */+ { 3, 7, 12, 0, 0, 0, 82, }, /* 286 */+ { 69, 6, 12, 0, 0, 165, 136, }, /* 287 */+ { 84, 12, 3, 0, 0, 26660, 128, }, /* 288 */+ { 84, 12, 3, 0, 0, 26660, 130, }, /* 289 */+ { 3, 12, 3, 0, 0, 26624, 128, }, /* 290 */+ { 3, 12, 3, 0, 0, 26624, 96, }, /* 291 */+ { 3, 13, 12, 0, 0, 2159, 138, }, /* 292 */+ { 3, 21, 12, 0, 0, 2048, 68, }, /* 293 */+ { 3, 7, 12, 0, 0, 0, 140, }, /* 294 */+ { 3, 21, 12, 0, 0, 30, 124, }, /* 295 */+ { 3, 6, 12, 0, 0, 0, 92, }, /* 296 */+ { 3, 13, 12, 0, 0, 10240, 138, }, /* 297 */+ { 3, 26, 12, 0, 0, 0, 68, }, /* 298 */+ { 4, 21, 12, 0, 0, 0, 124, }, /* 299 */+ { 4, 21, 12, 0, 0, 0, 106, }, /* 300 */+ { 4, 21, 12, 0, 0, 0, 68, }, /* 301 */+ { 68, 2, 12, 0, 0, 0, 0, }, /* 302 */+ { 4, 1, 4, 0, 0, 0, 132, }, /* 303 */+ { 4, 7, 12, 0, 0, 0, 82, }, /* 304 */+ { 4, 12, 3, 0, 0, 26624, 130, }, /* 305 */+ { 4, 12, 3, 0, 0, 26624, 128, }, /* 306 */+ { 4, 12, 3, 0, 0, 26624, 96, }, /* 307 */+ { 5, 7, 12, 0, 0, 0, 82, }, /* 308 */+ { 5, 12, 3, 0, 0, 26624, 128, }, /* 309 */+ { 38, 13, 12, 0, 0, 34816, 138, }, /* 310 */+ { 38, 7, 12, 0, 0, 34816, 82, }, /* 311 */+ { 38, 12, 3, 0, 0, 26624, 96, }, /* 312 */+ { 38, 6, 12, 0, 0, 34816, 92, }, /* 313 */+ { 38, 26, 12, 0, 0, 28672, 68, }, /* 314 */+ { 38, 21, 12, 0, 0, 28672, 68, }, /* 315 */+ { 38, 21, 12, 0, 0, 28672, 106, }, /* 316 */+ { 38, 21, 12, 0, 0, 28672, 124, }, /* 317 */+ { 38, 6, 12, 0, 0, 34816, 136, }, /* 318 */+ { 38, 12, 3, 0, 0, 26624, 102, }, /* 319 */+ { 38, 23, 12, 0, 0, 34816, 68, }, /* 320 */+ { 110, 7, 12, 0, 0, 34816, 82, }, /* 321 */+ { 110, 12, 3, 0, 0, 26624, 130, }, /* 322 */+ { 110, 12, 3, 0, 0, 26624, 96, }, /* 323 */+ { 110, 6, 12, 0, 0, 34816, 142, }, /* 324 */+ { 110, 12, 3, 0, 0, 26624, 102, }, /* 325 */+ { 110, 21, 12, 0, 0, 34816, 106, }, /* 326 */+ { 110, 21, 12, 0, 0, 34816, 124, }, /* 327 */+ { 42, 7, 12, 0, 0, 34816, 82, }, /* 328 */+ { 42, 12, 3, 0, 0, 26624, 102, }, /* 329 */+ { 42, 21, 12, 0, 0, 34816, 106, }, /* 330 */+ { 3, 24, 12, 0, 0, 0, 122, }, /* 331 */+ { 3, 12, 3, 0, 0, 26624, 102, }, /* 332 */+ { 6, 12, 3, 0, 0, 26624, 130, }, /* 333 */+ { 6, 10, 5, 0, 0, 18432, 144, }, /* 334 */+ { 6, 7, 12, 0, 0, 18432, 82, }, /* 335 */+ { 6, 12, 3, 0, 0, 26624, 96, }, /* 336 */+ { 6, 12, 3, 0, 0, 26624, 146, }, /* 337 */+ { 84, 12, 3, 0, 0, 26798, 96, }, /* 338 */+ { 84, 12, 3, 0, 0, 26795, 96, }, /* 339 */+ { 69, 21, 12, 0, 0, 18615, 124, }, /* 340 */+ { 69, 21, 12, 0, 0, 18618, 124, }, /* 341 */+ { 6, 13, 12, 0, 0, 18576, 138, }, /* 342 */+ { 6, 21, 12, 0, 0, 18432, 68, }, /* 343 */+ { 6, 6, 12, 0, 0, 18432, 92, }, /* 344 */+ { 7, 7, 12, 0, 0, 18432, 82, }, /* 345 */+ { 7, 12, 3, 0, 0, 26624, 130, }, /* 346 */+ { 7, 10, 5, 0, 0, 18432, 144, }, /* 347 */+ { 7, 12, 3, 0, 0, 26624, 96, }, /* 348 */+ { 7, 10, 3, 0, 0, 18432, 148, }, /* 349 */+ { 7, 12, 3, 0, 0, 26624, 146, }, /* 350 */+ { 7, 13, 12, 0, 0, 18546, 138, }, /* 351 */+ { 7, 23, 12, 0, 0, 14336, 68, }, /* 352 */+ { 7, 15, 12, 0, 0, 18432, 68, }, /* 353 */+ { 7, 26, 12, 0, 0, 18432, 68, }, /* 354 */+ { 7, 21, 12, 0, 0, 18432, 68, }, /* 355 */+ { 7, 12, 3, 0, 0, 26624, 102, }, /* 356 */+ { 8, 12, 3, 0, 0, 26624, 130, }, /* 357 */+ { 8, 10, 5, 0, 0, 18432, 144, }, /* 358 */+ { 8, 7, 12, 0, 0, 18432, 82, }, /* 359 */+ { 8, 12, 3, 0, 0, 26624, 96, }, /* 360 */+ { 8, 12, 3, 0, 0, 26624, 146, }, /* 361 */+ { 8, 13, 12, 0, 0, 18519, 138, }, /* 362 */+ { 8, 21, 12, 0, 0, 18432, 68, }, /* 363 */+ { 9, 12, 3, 0, 0, 26624, 130, }, /* 364 */+ { 9, 10, 5, 0, 0, 18432, 144, }, /* 365 */+ { 9, 7, 12, 0, 0, 18432, 82, }, /* 366 */+ { 9, 12, 3, 0, 0, 26624, 96, }, /* 367 */+ { 9, 12, 3, 0, 0, 26624, 146, }, /* 368 */+ { 9, 13, 12, 0, 0, 18516, 138, }, /* 369 */+ { 9, 21, 12, 0, 0, 18432, 68, }, /* 370 */+ { 9, 23, 12, 0, 0, 14336, 68, }, /* 371 */+ { 10, 12, 3, 0, 0, 26624, 130, }, /* 372 */+ { 10, 10, 5, 0, 0, 18432, 144, }, /* 373 */+ { 10, 7, 12, 0, 0, 18432, 82, }, /* 374 */+ { 10, 12, 3, 0, 0, 26624, 96, }, /* 375 */+ { 10, 10, 3, 0, 0, 18432, 148, }, /* 376 */+ { 10, 12, 3, 0, 0, 26624, 146, }, /* 377 */+ { 10, 12, 3, 0, 0, 26624, 150, }, /* 378 */+ { 10, 13, 12, 0, 0, 18432, 138, }, /* 379 */+ { 10, 26, 12, 0, 0, 18432, 68, }, /* 380 */+ { 10, 15, 12, 0, 0, 18432, 68, }, /* 381 */+ { 11, 12, 3, 0, 0, 26624, 130, }, /* 382 */+ { 11, 7, 12, 0, 0, 18432, 82, }, /* 383 */+ { 11, 10, 3, 0, 0, 18432, 148, }, /* 384 */+ { 11, 10, 5, 0, 0, 18432, 144, }, /* 385 */+ { 11, 12, 3, 0, 0, 26624, 146, }, /* 386 */+ { 11, 13, 12, 0, 0, 18513, 138, }, /* 387 */+ { 11, 15, 12, 0, 0, 18513, 68, }, /* 388 */+ { 11, 26, 12, 0, 0, 28753, 68, }, /* 389 */+ { 11, 26, 12, 0, 0, 28672, 68, }, /* 390 */+ { 11, 23, 12, 0, 0, 14336, 68, }, /* 391 */+ { 12, 12, 3, 0, 0, 26624, 130, }, /* 392 */+ { 12, 10, 5, 0, 0, 18432, 144, }, /* 393 */+ { 12, 7, 12, 0, 0, 18432, 82, }, /* 394 */+ { 12, 12, 3, 0, 0, 26624, 96, }, /* 395 */+ { 12, 12, 3, 0, 0, 26624, 146, }, /* 396 */+ { 12, 13, 12, 0, 0, 18432, 138, }, /* 397 */+ { 12, 21, 12, 0, 0, 18432, 68, }, /* 398 */+ { 12, 15, 12, 0, 0, 28672, 68, }, /* 399 */+ { 12, 26, 12, 0, 0, 18432, 68, }, /* 400 */+ { 13, 7, 12, 0, 0, 18432, 82, }, /* 401 */+ { 13, 12, 3, 0, 0, 26624, 130, }, /* 402 */+ { 13, 10, 5, 0, 0, 18432, 144, }, /* 403 */+ { 13, 21, 12, 0, 0, 18432, 68, }, /* 404 */+ { 13, 12, 3, 0, 0, 26624, 96, }, /* 405 */+ { 13, 12, 3, 0, 0, 18432, 130, }, /* 406 */+ { 13, 10, 3, 0, 0, 18432, 148, }, /* 407 */+ { 13, 12, 3, 0, 0, 26624, 146, }, /* 408 */+ { 13, 13, 12, 0, 0, 18528, 138, }, /* 409 */+ { 14, 12, 3, 0, 0, 26624, 130, }, /* 410 */+ { 14, 10, 5, 0, 0, 18432, 144, }, /* 411 */+ { 14, 7, 12, 0, 0, 18432, 82, }, /* 412 */+ { 14, 12, 3, 0, 0, 26624, 146, }, /* 413 */+ { 14, 10, 3, 0, 0, 18432, 148, }, /* 414 */+ { 14, 7, 4, 0, 0, 18432, 82, }, /* 415 */+ { 14, 26, 12, 0, 0, 18432, 68, }, /* 416 */+ { 14, 15, 12, 0, 0, 18432, 68, }, /* 417 */+ { 14, 13, 12, 0, 0, 18432, 138, }, /* 418 */+ { 15, 12, 3, 0, 0, 26624, 130, }, /* 419 */+ { 15, 10, 5, 0, 0, 18432, 144, }, /* 420 */+ { 15, 7, 12, 0, 0, 18432, 82, }, /* 421 */+ { 15, 12, 3, 0, 0, 26624, 146, }, /* 422 */+ { 15, 10, 3, 0, 0, 18432, 148, }, /* 423 */+ { 15, 13, 12, 0, 0, 18432, 138, }, /* 424 */+ { 15, 21, 12, 0, 0, 18432, 68, }, /* 425 */+ { 72, 7, 12, 0, 0, 18432, 82, }, /* 426 */+ { 72, 12, 3, 0, 0, 26624, 130, }, /* 427 */+ { 72, 7, 5, 0, 0, 18432, 152, }, /* 428 */+ { 72, 12, 3, 0, 0, 26624, 154, }, /* 429 */+ { 69, 23, 12, 0, 0, 14336, 68, }, /* 430 */+ { 72, 7, 12, 0, 0, 18432, 156, }, /* 431 */+ { 72, 6, 12, 0, 0, 18432, 136, }, /* 432 */+ { 72, 12, 3, 0, 0, 26624, 96, }, /* 433 */+ { 72, 21, 12, 0, 0, 18432, 68, }, /* 434 */+ { 72, 13, 12, 0, 0, 18432, 138, }, /* 435 */+ { 72, 21, 12, 0, 0, 18432, 106, }, /* 436 */+ { 73, 7, 12, 0, 0, 18432, 82, }, /* 437 */+ { 73, 12, 3, 0, 0, 26624, 130, }, /* 438 */+ { 73, 7, 5, 0, 0, 18432, 152, }, /* 439 */+ { 73, 12, 3, 0, 0, 26624, 146, }, /* 440 */+ { 73, 7, 12, 0, 0, 18432, 156, }, /* 441 */+ { 73, 6, 12, 0, 0, 18432, 136, }, /* 442 */+ { 73, 12, 3, 0, 0, 26624, 96, }, /* 443 */+ { 73, 12, 3, 0, 0, 26624, 102, }, /* 444 */+ { 73, 13, 12, 0, 0, 18432, 138, }, /* 445 */+ { 74, 7, 12, 0, 0, 18432, 82, }, /* 446 */+ { 74, 26, 12, 0, 0, 18432, 68, }, /* 447 */+ { 74, 21, 12, 0, 0, 18432, 68, }, /* 448 */+ { 74, 21, 12, 0, 0, 18432, 106, }, /* 449 */+ { 74, 12, 3, 0, 0, 26624, 96, }, /* 450 */+ { 74, 13, 12, 0, 0, 18432, 138, }, /* 451 */+ { 74, 15, 12, 0, 0, 18432, 68, }, /* 452 */+ { 74, 22, 12, 0, 0, 28672, 158, }, /* 453 */+ { 74, 18, 12, 0, 0, 28672, 158, }, /* 454 */+ { 74, 10, 5, 0, 0, 18432, 160, }, /* 455 */+ { 74, 12, 3, 0, 0, 26624, 130, }, /* 456 */+ { 74, 12, 3, 0, 0, 26624, 162, }, /* 457 */+ { 74, 10, 5, 0, 0, 18432, 144, }, /* 458 */+ { 74, 12, 3, 0, 0, 26624, 128, }, /* 459 */+ { 74, 12, 3, 0, 0, 26624, 146, }, /* 460 */+ { 69, 26, 12, 0, 0, 18432, 68, }, /* 461 */+ { 16, 7, 12, 0, 0, 18432, 82, }, /* 462 */+ { 16, 10, 12, 0, 0, 18432, 144, }, /* 463 */+ { 16, 12, 3, 0, 0, 26624, 130, }, /* 464 */+ { 16, 10, 5, 0, 0, 18432, 144, }, /* 465 */+ { 16, 12, 3, 0, 0, 26624, 96, }, /* 466 */+ { 16, 12, 3, 0, 0, 26624, 146, }, /* 467 */+ { 16, 13, 12, 0, 0, 18549, 138, }, /* 468 */+ { 16, 21, 12, 0, 0, 18432, 124, }, /* 469 */+ { 16, 21, 12, 0, 0, 18432, 68, }, /* 470 */+ { 16, 10, 12, 0, 0, 18432, 164, }, /* 471 */+ { 16, 12, 3, 0, 0, 26624, 128, }, /* 472 */+ { 16, 13, 12, 0, 0, 18432, 138, }, /* 473 */+ { 16, 26, 12, 0, 0, 18432, 68, }, /* 474 */+ { 17, 9, 12, 0, 7264, 18432, 74, }, /* 475 */+ { 17, 5, 12, 0, 3008, 18432, 166, }, /* 476 */+ { 69, 21, 12, 0, 0, 18510, 68, }, /* 477 */+ { 17, 6, 12, 0, 0, 18432, 168, }, /* 478 */+ { 18, 7, 6, 0, 0, 18432, 82, }, /* 479 */+ { 18, 7, 6, 0, 0, 18432, 170, }, /* 480 */+ { 18, 7, 7, 0, 0, 18432, 170, }, /* 481 */+ { 18, 7, 7, 0, 0, 18432, 82, }, /* 482 */+ { 18, 7, 8, 0, 0, 18432, 82, }, /* 483 */+ { 75, 7, 12, 0, 0, 18432, 82, }, /* 484 */+ { 75, 12, 3, 0, 0, 26624, 96, }, /* 485 */+ { 75, 21, 12, 0, 0, 18432, 68, }, /* 486 */+ { 75, 21, 12, 0, 0, 18432, 106, }, /* 487 */+ { 75, 21, 12, 0, 0, 18432, 124, }, /* 488 */+ { 75, 15, 12, 0, 0, 18432, 138, }, /* 489 */+ { 75, 15, 12, 0, 0, 18432, 68, }, /* 490 */+ { 75, 26, 12, 0, 0, 28672, 68, }, /* 491 */+ { 76, 9, 12, 0, 38864, 18432, 172, }, /* 492 */+ { 76, 9, 12, 0, 8, 18432, 172, }, /* 493 */+ { 76, 5, 12, 0, -8, 18432, 70, }, /* 494 */+ { 77, 17, 12, 0, 0, 28672, 126, }, /* 495 */+ { 77, 7, 12, 0, 0, 18432, 82, }, /* 496 */+ { 77, 26, 12, 0, 0, 18432, 68, }, /* 497 */+ { 77, 21, 12, 0, 0, 18432, 124, }, /* 498 */+ { 78, 29, 12, 0, 0, 45056, 52, }, /* 499 */+ { 78, 7, 12, 0, 0, 18432, 82, }, /* 500 */+ { 78, 22, 12, 0, 0, 28672, 158, }, /* 501 */+ { 78, 18, 12, 0, 0, 28672, 158, }, /* 502 */+ { 79, 7, 12, 0, 0, 18432, 82, }, /* 503 */+ { 69, 21, 12, 0, 0, 18432, 106, }, /* 504 */+ { 79, 14, 12, 0, 0, 18432, 82, }, /* 505 */+ { 25, 7, 12, 0, 0, 18432, 82, }, /* 506 */+ { 25, 12, 3, 0, 0, 26624, 130, }, /* 507 */+ { 25, 12, 3, 0, 0, 26624, 146, }, /* 508 */+ { 25, 10, 5, 0, 0, 18432, 174, }, /* 509 */+ { 26, 7, 12, 0, 0, 18432, 82, }, /* 510 */+ { 26, 12, 3, 0, 0, 26624, 130, }, /* 511 */+ { 26, 10, 5, 0, 0, 18432, 176, }, /* 512 */+ { 69, 21, 12, 0, 0, 18573, 124, }, /* 513 */+ { 27, 7, 12, 0, 0, 18432, 82, }, /* 514 */+ { 27, 12, 3, 0, 0, 26624, 130, }, /* 515 */+ { 28, 7, 12, 0, 0, 18432, 82, }, /* 516 */+ { 28, 12, 3, 0, 0, 26624, 130, }, /* 517 */+ { 80, 7, 12, 0, 0, 18432, 82, }, /* 518 */+ { 80, 7, 12, 0, 0, 18432, 140, }, /* 519 */+ { 80, 12, 3, 0, 0, 26624, 100, }, /* 520 */+ { 80, 10, 5, 0, 0, 18432, 144, }, /* 521 */+ { 80, 12, 3, 0, 0, 26624, 130, }, /* 522 */+ { 80, 12, 3, 0, 0, 26624, 96, }, /* 523 */+ { 80, 12, 3, 0, 0, 26624, 146, }, /* 524 */+ { 80, 21, 12, 0, 0, 18432, 106, }, /* 525 */+ { 80, 6, 12, 0, 0, 18432, 142, }, /* 526 */+ { 80, 21, 12, 0, 0, 18432, 68, }, /* 527 */+ { 80, 23, 12, 0, 0, 14336, 68, }, /* 528 */+ { 80, 13, 12, 0, 0, 18432, 138, }, /* 529 */+ { 80, 15, 12, 0, 0, 28672, 68, }, /* 530 */+ { 19, 21, 12, 0, 0, 28672, 68, }, /* 531 */+ { 69, 21, 12, 0, 0, 28777, 106, }, /* 532 */+ { 69, 21, 12, 0, 0, 28777, 124, }, /* 533 */+ { 19, 21, 12, 0, 0, 28672, 106, }, /* 534 */+ { 19, 17, 12, 0, 0, 28672, 126, }, /* 535 */+ { 19, 21, 12, 0, 0, 28672, 124, }, /* 536 */+ { 19, 21, 12, 0, 0, 28672, 178, }, /* 537 */+ { 19, 12, 3, 0, 0, 26624, 180, }, /* 538 */+ { 19, 1, 2, 0, 0, 6144, 66, }, /* 539 */+ { 19, 13, 12, 0, 0, 18432, 138, }, /* 540 */+ { 19, 7, 12, 0, 0, 18432, 82, }, /* 541 */+ { 19, 6, 12, 0, 0, 18432, 136, }, /* 542 */+ { 19, 12, 3, 0, 0, 26624, 182, }, /* 543 */+ { 19, 12, 3, 0, 0, 26624, 130, }, /* 544 */+ { 29, 7, 12, 0, 0, 18432, 82, }, /* 545 */+ { 29, 12, 3, 0, 0, 26624, 130, }, /* 546 */+ { 29, 10, 5, 0, 0, 18432, 144, }, /* 547 */+ { 29, 12, 3, 0, 0, 26624, 96, }, /* 548 */+ { 29, 26, 12, 0, 0, 28672, 68, }, /* 549 */+ { 29, 21, 12, 0, 0, 28672, 124, }, /* 550 */+ { 29, 13, 12, 0, 0, 18432, 138, }, /* 551 */+ { 30, 7, 12, 0, 0, 18432, 82, }, /* 552 */+ { 89, 7, 12, 0, 0, 18432, 82, }, /* 553 */+ { 89, 7, 12, 0, 0, 18432, 156, }, /* 554 */+ { 89, 13, 12, 0, 0, 18432, 138, }, /* 555 */+ { 89, 15, 12, 0, 0, 18432, 138, }, /* 556 */+ { 89, 26, 12, 0, 0, 28672, 68, }, /* 557 */+ { 80, 26, 12, 0, 0, 28672, 68, }, /* 558 */+ { 33, 7, 12, 0, 0, 18432, 82, }, /* 559 */+ { 33, 12, 3, 0, 0, 26624, 130, }, /* 560 */+ { 33, 10, 5, 0, 0, 18432, 144, }, /* 561 */+ { 33, 21, 12, 0, 0, 18432, 68, }, /* 562 */+ { 106, 7, 12, 0, 0, 18432, 82, }, /* 563 */+ { 106, 10, 5, 0, 0, 18432, 144, }, /* 564 */+ { 106, 12, 3, 0, 0, 26624, 130, }, /* 565 */+ { 106, 12, 3, 0, 0, 26624, 184, }, /* 566 */+ { 106, 10, 12, 0, 0, 18432, 144, }, /* 567 */+ { 106, 12, 3, 0, 0, 26624, 96, }, /* 568 */+ { 106, 13, 12, 0, 0, 18432, 138, }, /* 569 */+ { 106, 21, 12, 0, 0, 18432, 68, }, /* 570 */+ { 106, 6, 12, 0, 0, 18432, 136, }, /* 571 */+ { 106, 21, 12, 0, 0, 18432, 124, }, /* 572 */+ { 84, 11, 3, 0, 0, 26624, 186, }, /* 573 */+ { 84, 12, 3, 0, 0, 26624, 130, }, /* 574 */+ { 93, 12, 3, 0, 0, 26624, 130, }, /* 575 */+ { 93, 10, 5, 0, 0, 18432, 144, }, /* 576 */+ { 93, 7, 12, 0, 0, 18432, 82, }, /* 577 */+ { 93, 12, 3, 0, 0, 26624, 96, }, /* 578 */+ { 93, 10, 3, 0, 0, 18432, 148, }, /* 579 */+ { 93, 10, 5, 0, 0, 18432, 174, }, /* 580 */+ { 93, 13, 12, 0, 0, 18432, 138, }, /* 581 */+ { 93, 21, 12, 0, 0, 18432, 124, }, /* 582 */+ { 93, 21, 12, 0, 0, 18432, 68, }, /* 583 */+ { 93, 21, 12, 0, 0, 18432, 106, }, /* 584 */+ { 93, 26, 12, 0, 0, 18432, 68, }, /* 585 */+ { 96, 12, 3, 0, 0, 26624, 130, }, /* 586 */+ { 96, 10, 5, 0, 0, 18432, 144, }, /* 587 */+ { 96, 7, 12, 0, 0, 18432, 82, }, /* 588 */+ { 96, 10, 5, 0, 0, 18432, 174, }, /* 589 */+ { 96, 12, 3, 0, 0, 26624, 146, }, /* 590 */+ { 96, 13, 12, 0, 0, 18432, 138, }, /* 591 */+ { 119, 7, 12, 0, 0, 18432, 82, }, /* 592 */+ { 119, 12, 3, 0, 0, 26624, 102, }, /* 593 */+ { 119, 10, 5, 0, 0, 18432, 144, }, /* 594 */+ { 119, 12, 3, 0, 0, 26624, 130, }, /* 595 */+ { 119, 10, 5, 0, 0, 18432, 176, }, /* 596 */+ { 119, 21, 12, 0, 0, 18432, 68, }, /* 597 */+ { 97, 7, 12, 0, 0, 18432, 82, }, /* 598 */+ { 97, 10, 5, 0, 0, 18432, 144, }, /* 599 */+ { 97, 12, 3, 0, 0, 26624, 130, }, /* 600 */+ { 97, 12, 3, 0, 0, 26624, 188, }, /* 601 */+ { 97, 12, 3, 0, 0, 26624, 96, }, /* 602 */+ { 97, 21, 12, 0, 0, 18432, 124, }, /* 603 */+ { 97, 21, 12, 0, 0, 18432, 106, }, /* 604 */+ { 97, 13, 12, 0, 0, 18432, 138, }, /* 605 */+ { 98, 13, 12, 0, 0, 18432, 138, }, /* 606 */+ { 98, 7, 12, 0, 0, 18432, 82, }, /* 607 */+ { 98, 6, 12, 0, 0, 18432, 92, }, /* 608 */+ { 98, 6, 12, 0, 0, 18432, 94, }, /* 609 */+ { 98, 21, 12, 0, 0, 18432, 124, }, /* 610 */+ { 2, 5, 12, 63, -6222, 18432, 70, }, /* 611 */+ { 2, 5, 12, 67, -6221, 18432, 70, }, /* 612 */+ { 2, 5, 12, 71, -6212, 18432, 70, }, /* 613 */+ { 2, 5, 12, 75, -6210, 18432, 70, }, /* 614 */+ { 2, 5, 12, 79, -6210, 18432, 70, }, /* 615 */+ { 2, 5, 12, 79, -6211, 18432, 70, }, /* 616 */+ { 2, 5, 12, 84, -6204, 18432, 70, }, /* 617 */+ { 2, 5, 12, 88, -6180, 18432, 70, }, /* 618 */+ { 2, 5, 12, 108, 35267, 18432, 70, }, /* 619 */+ { 17, 9, 12, 0, -3008, 18432, 74, }, /* 620 */+ { 96, 21, 12, 0, 0, 18432, 68, }, /* 621 */+ { 84, 12, 3, 0, 0, 26762, 96, }, /* 622 */+ { 84, 12, 3, 0, 0, 26630, 96, }, /* 623 */+ { 69, 21, 12, 0, 0, 18498, 190, }, /* 624 */+ { 84, 12, 3, 0, 0, 26666, 96, }, /* 625 */+ { 84, 12, 3, 0, 0, 26696, 96, }, /* 626 */+ { 84, 12, 3, 0, 0, 26780, 96, }, /* 627 */+ { 69, 10, 5, 0, 0, 18474, 160, }, /* 628 */+ { 69, 7, 12, 0, 0, 18501, 82, }, /* 629 */+ { 69, 7, 12, 0, 0, 18474, 82, }, /* 630 */+ { 69, 7, 12, 0, 0, 18438, 82, }, /* 631 */+ { 69, 7, 12, 0, 0, 18594, 82, }, /* 632 */+ { 69, 7, 12, 0, 0, 18498, 82, }, /* 633 */+ { 84, 12, 3, 0, 0, 26750, 96, }, /* 634 */+ { 69, 10, 5, 0, 0, 18435, 160, }, /* 635 */+ { 84, 12, 3, 0, 0, 26690, 96, }, /* 636 */+ { 69, 7, 12, 0, 0, 18453, 82, }, /* 637 */+ { 2, 5, 12, 0, 0, 18432, 60, }, /* 638 */+ { 1, 6, 12, 0, 0, 18432, 88, }, /* 639 */+ { 2, 6, 12, 0, 0, 18432, 168, }, /* 640 */+ { 0, 5, 12, 0, 35332, 18432, 76, }, /* 641 */+ { 0, 5, 12, 0, 3814, 18432, 76, }, /* 642 */+ { 0, 5, 12, 0, 35384, 18432, 76, }, /* 643 */+ { 0, 5, 12, 0, 0, 18432, 192, }, /* 644 */+ { 0, 6, 12, 0, 0, 18432, 168, }, /* 645 */+ { 0, 6, 12, 0, 0, 18432, 194, }, /* 646 */+ { 1, 6, 12, 0, 0, 18432, 168, }, /* 647 */+ { 84, 12, 3, 0, 0, 26636, 102, }, /* 648 */+ { 84, 12, 3, 0, 0, 26687, 96, }, /* 649 */+ { 84, 12, 3, 0, 0, 26648, 96, }, /* 650 */+ { 0, 9, 12, 92, 1, 18432, 74, }, /* 651 */+ { 0, 5, 12, 92, -1, 18432, 76, }, /* 652 */+ { 0, 5, 12, 0, 0, 18432, 70, }, /* 653 */+ { 0, 5, 12, 92, -58, 18432, 70, }, /* 654 */+ { 0, 9, 12, 0, -7615, 18432, 74, }, /* 655 */+ { 1, 5, 12, 0, 8, 18432, 76, }, /* 656 */+ { 1, 9, 12, 0, -8, 18432, 74, }, /* 657 */+ { 1, 5, 12, 0, 74, 18432, 76, }, /* 658 */+ { 1, 5, 12, 0, 86, 18432, 76, }, /* 659 */+ { 1, 5, 12, 0, 100, 18432, 76, }, /* 660 */+ { 1, 5, 12, 0, 128, 18432, 76, }, /* 661 */+ { 1, 5, 12, 0, 112, 18432, 76, }, /* 662 */+ { 1, 5, 12, 0, 126, 18432, 76, }, /* 663 */+ { 1, 5, 12, 0, 8, 18432, 70, }, /* 664 */+ { 1, 8, 12, 0, -8, 18432, 86, }, /* 665 */+ { 1, 5, 12, 0, 0, 18432, 70, }, /* 666 */+ { 1, 5, 12, 0, 9, 18432, 70, }, /* 667 */+ { 1, 9, 12, 0, -74, 18432, 74, }, /* 668 */+ { 1, 8, 12, 0, -9, 18432, 86, }, /* 669 */+ { 1, 5, 12, 21, -7173, 18432, 76, }, /* 670 */+ { 1, 9, 12, 0, -86, 18432, 74, }, /* 671 */+ { 1, 9, 12, 0, -100, 18432, 74, }, /* 672 */+ { 1, 9, 12, 0, -112, 18432, 74, }, /* 673 */+ { 1, 9, 12, 0, -128, 18432, 74, }, /* 674 */+ { 1, 9, 12, 0, -126, 18432, 74, }, /* 675 */+ { 69, 29, 12, 0, 0, 45056, 52, }, /* 676 */+ { 84, 1, 3, 0, 0, 6144, 196, }, /* 677 */+ { 84, 1, 13, 0, 0, 6144, 198, }, /* 678 */+ { 69, 1, 2, 0, 0, 18432, 200, }, /* 679 */+ { 69, 1, 2, 0, 0, 34816, 200, }, /* 680 */+ { 69, 17, 12, 0, 0, 28672, 202, }, /* 681 */+ { 69, 21, 12, 0, 0, 28672, 64, }, /* 682 */+ { 69, 20, 12, 0, 0, 28672, 204, }, /* 683 */+ { 69, 19, 12, 0, 0, 28672, 204, }, /* 684 */+ { 69, 22, 12, 0, 0, 28672, 206, }, /* 685 */+ { 69, 20, 12, 0, 0, 28672, 206, }, /* 686 */+ { 69, 19, 12, 0, 0, 28672, 206, }, /* 687 */+ { 69, 21, 12, 0, 0, 28672, 208, }, /* 688 */+ { 69, 27, 2, 0, 0, 45056, 50, }, /* 689 */+ { 69, 28, 2, 0, 0, 4096, 50, }, /* 690 */+ { 69, 1, 2, 0, 0, 20480, 134, }, /* 691 */+ { 69, 1, 2, 0, 0, 36864, 134, }, /* 692 */+ { 69, 1, 2, 0, 0, 30720, 134, }, /* 693 */+ { 69, 1, 2, 0, 0, 24576, 134, }, /* 694 */+ { 69, 1, 2, 0, 0, 40960, 134, }, /* 695 */+ { 69, 29, 12, 0, 0, 8291, 52, }, /* 696 */+ { 69, 21, 12, 0, 0, 14336, 54, }, /* 697 */+ { 69, 21, 12, 0, 0, 14336, 64, }, /* 698 */+ { 69, 21, 14, 0, 0, 28672, 210, }, /* 699 */+ { 69, 21, 12, 0, 0, 28672, 212, }, /* 700 */+ { 69, 16, 12, 0, 0, 28672, 138, }, /* 701 */+ { 69, 16, 12, 0, 0, 28672, 214, }, /* 702 */+ { 69, 25, 12, 0, 0, 8192, 64, }, /* 703 */+ { 69, 22, 12, 0, 0, 28672, 216, }, /* 704 */+ { 69, 18, 12, 0, 0, 28672, 216, }, /* 705 */+ { 69, 21, 12, 0, 0, 28672, 202, }, /* 706 */+ { 69, 1, 2, 0, 0, 6144, 218, }, /* 707 */+ { 68, 2, 2, 0, 0, 6144, 220, }, /* 708 */+ { 69, 1, 2, 0, 0, 22528, 134, }, /* 709 */+ { 69, 1, 2, 0, 0, 38912, 134, }, /* 710 */+ { 69, 1, 2, 0, 0, 16384, 134, }, /* 711 */+ { 69, 1, 2, 0, 0, 32768, 134, }, /* 712 */+ { 69, 1, 2, 0, 0, 6144, 222, }, /* 713 */+ { 69, 25, 12, 0, 0, 12288, 118, }, /* 714 */+ { 69, 25, 12, 0, 0, 12288, 224, }, /* 715 */+ { 69, 25, 12, 0, 0, 28672, 118, }, /* 716 */+ { 69, 22, 12, 0, 0, 28672, 226, }, /* 717 */+ { 69, 18, 12, 0, 0, 28672, 226, }, /* 718 */+ { 68, 2, 12, 0, 0, 14336, 0, }, /* 719 */+ { 84, 12, 3, 0, 0, 26624, 228, }, /* 720 */+ { 84, 11, 3, 0, 0, 26624, 120, }, /* 721 */+ { 84, 11, 3, 0, 0, 26624, 230, }, /* 722 */+ { 84, 12, 3, 0, 0, 26753, 102, }, /* 723 */+ { 69, 26, 12, 0, 0, 28672, 68, }, /* 724 */+ { 69, 9, 12, 0, 0, 18432, 112, }, /* 725 */+ { 69, 5, 12, 0, 0, 18432, 232, }, /* 726 */+ { 69, 25, 12, 0, 0, 28672, 234, }, /* 727 */+ { 69, 26, 14, 0, 0, 28672, 236, }, /* 728 */+ { 1, 9, 12, 96, -7517, 18432, 74, }, /* 729 */+ { 69, 26, 12, 0, 0, 28672, 118, }, /* 730 */+ { 0, 9, 12, 100, 0, 18432, 74, }, /* 731 */+ { 0, 9, 12, 104, -8262, 18432, 74, }, /* 732 */+ { 69, 26, 12, 0, 0, 14336, 238, }, /* 733 */+ { 0, 9, 12, 0, 28, 18432, 74, }, /* 734 */+ { 69, 7, 12, 0, 0, 18432, 240, }, /* 735 */+ { 69, 5, 14, 0, 0, 18432, 242, }, /* 736 */+ { 69, 5, 12, 0, 0, 18432, 244, }, /* 737 */+ { 0, 5, 12, 0, -28, 18432, 76, }, /* 738 */+ { 0, 14, 12, 0, 16, 18432, 74, }, /* 739 */+ { 0, 14, 12, 0, -16, 18432, 76, }, /* 740 */+ { 0, 14, 12, 0, 0, 18432, 82, }, /* 741 */+ { 69, 25, 14, 0, 0, 28672, 246, }, /* 742 */+ { 69, 26, 14, 0, 0, 28672, 246, }, /* 743 */+ { 69, 26, 12, 0, 0, 28672, 64, }, /* 744 */+ { 69, 25, 12, 0, 0, 28672, 248, }, /* 745 */+ { 69, 25, 12, 0, 0, 12288, 250, }, /* 746 */+ { 69, 22, 12, 0, 0, 28672, 248, }, /* 747 */+ { 69, 18, 12, 0, 0, 28672, 248, }, /* 748 */+ { 69, 26, 14, 0, 0, 28672, 252, }, /* 749 */+ { 69, 22, 12, 0, 0, 28672, 254, }, /* 750 */+ { 69, 18, 12, 0, 0, 28672, 254, }, /* 751 */+ { 69, 26, 12, 0, 0, 18432, 54, }, /* 752 */+ { 69, 26, 14, 0, 0, 28672, 256, }, /* 753 */+ { 68, 2, 12, 0, 0, 18432, 258, }, /* 754 */+ { 69, 26, 12, 0, 26, 18432, 260, }, /* 755 */+ { 69, 26, 14, 0, 26, 18432, 262, }, /* 756 */+ { 69, 26, 12, 0, -26, 18432, 264, }, /* 757 */+ { 69, 25, 14, 0, 0, 28672, 266, }, /* 758 */+ { 69, 26, 14, 0, 0, 28672, 268, }, /* 759 */+ { 69, 26, 14, 0, 0, 28672, 270, }, /* 760 */+ { 69, 25, 14, 0, 0, 28672, 268, }, /* 761 */+ { 69, 26, 14, 0, 0, 18432, 256, }, /* 762 */+ { 69, 26, 14, 0, 0, 28672, 272, }, /* 763 */+ { 88, 26, 12, 0, 0, 18432, 54, }, /* 764 */+ { 69, 26, 12, 0, 0, 28672, 216, }, /* 765 */+ { 35, 9, 12, 0, 48, 18432, 74, }, /* 766 */+ { 35, 5, 12, 0, -48, 18432, 76, }, /* 767 */+ { 0, 9, 12, 0, -10743, 18432, 74, }, /* 768 */+ { 0, 9, 12, 0, -3814, 18432, 74, }, /* 769 */+ { 0, 9, 12, 0, -10727, 18432, 74, }, /* 770 */+ { 0, 5, 12, 0, -10795, 18432, 76, }, /* 771 */+ { 0, 5, 12, 0, -10792, 18432, 76, }, /* 772 */+ { 0, 9, 12, 0, -10780, 18432, 74, }, /* 773 */+ { 0, 9, 12, 0, -10749, 18432, 74, }, /* 774 */+ { 0, 9, 12, 0, -10783, 18432, 74, }, /* 775 */+ { 0, 9, 12, 0, -10782, 18432, 74, }, /* 776 */+ { 0, 9, 12, 0, -10815, 18432, 74, }, /* 777 */+ { 34, 5, 12, 0, 0, 18432, 60, }, /* 778 */+ { 34, 26, 12, 0, 0, 28672, 68, }, /* 779 */+ { 34, 12, 3, 0, 0, 26624, 96, }, /* 780 */+ { 34, 21, 12, 0, 0, 28672, 68, }, /* 781 */+ { 34, 15, 12, 0, 0, 28672, 68, }, /* 782 */+ { 17, 5, 12, 0, -7264, 18432, 76, }, /* 783 */+ { 90, 7, 12, 0, 0, 18432, 82, }, /* 784 */+ { 90, 6, 12, 0, 0, 18432, 142, }, /* 785 */+ { 90, 21, 12, 0, 0, 18432, 68, }, /* 786 */+ { 90, 12, 3, 0, 0, 26624, 184, }, /* 787 */+ { 2, 12, 3, 0, 0, 26624, 130, }, /* 788 */+ { 69, 20, 12, 0, 0, 28672, 216, }, /* 789 */+ { 69, 19, 12, 0, 0, 28672, 216, }, /* 790 */+ { 69, 6, 12, 0, 0, 28672, 274, }, /* 791 */+ { 69, 21, 12, 0, 0, 28672, 276, }, /* 792 */+ { 69, 21, 12, 0, 0, 28726, 54, }, /* 793 */+ { 23, 26, 12, 0, 0, 28672, 278, }, /* 794 */+ { 69, 26, 12, 0, 0, 28672, 280, }, /* 795 */+ { 69, 26, 12, 0, 0, 28672, 282, }, /* 796 */+ { 69, 21, 12, 0, 0, 28825, 276, }, /* 797 */+ { 69, 21, 12, 0, 0, 28825, 212, }, /* 798 */+ { 69, 21, 12, 0, 0, 28819, 54, }, /* 799 */+ { 23, 6, 12, 0, 0, 18432, 136, }, /* 800 */+ { 69, 7, 12, 0, 0, 18447, 284, }, /* 801 */+ { 23, 14, 12, 0, 0, 18432, 284, }, /* 802 */+ { 69, 22, 12, 0, 0, 28825, 216, }, /* 803 */+ { 69, 18, 12, 0, 0, 28825, 216, }, /* 804 */+ { 69, 22, 12, 0, 0, 28825, 62, }, /* 805 */+ { 69, 18, 12, 0, 0, 28825, 62, }, /* 806 */+ { 69, 26, 12, 0, 0, 28819, 54, }, /* 807 */+ { 69, 17, 12, 0, 0, 28819, 202, }, /* 808 */+ { 69, 22, 12, 0, 0, 28819, 206, }, /* 809 */+ { 69, 18, 12, 0, 0, 28819, 206, }, /* 810 */+ { 84, 12, 3, 0, 0, 26669, 96, }, /* 811 */+ { 18, 10, 3, 0, 0, 18432, 286, }, /* 812 */+ { 69, 17, 14, 0, 0, 28819, 288, }, /* 813 */+ { 69, 6, 12, 0, 0, 18525, 136, }, /* 814 */+ { 69, 26, 12, 0, 0, 28819, 68, }, /* 815 */+ { 23, 6, 12, 0, 0, 18432, 142, }, /* 816 */+ { 69, 7, 12, 0, 0, 18564, 82, }, /* 817 */+ { 69, 21, 14, 0, 0, 28804, 236, }, /* 818 */+ { 69, 26, 12, 0, 0, 28687, 68, }, /* 819 */+ { 20, 7, 12, 0, 0, 18432, 82, }, /* 820 */+ { 84, 12, 3, 0, 0, 26717, 96, }, /* 821 */+ { 69, 24, 12, 0, 0, 28765, 290, }, /* 822 */+ { 20, 6, 12, 0, 0, 18432, 136, }, /* 823 */+ { 69, 17, 12, 0, 0, 28765, 126, }, /* 824 */+ { 21, 7, 12, 0, 0, 18432, 82, }, /* 825 */+ { 69, 21, 12, 0, 0, 28825, 68, }, /* 826 */+ { 69, 6, 12, 0, 0, 18525, 94, }, /* 827 */+ { 21, 6, 12, 0, 0, 18432, 136, }, /* 828 */+ { 22, 7, 12, 0, 0, 18432, 82, }, /* 829 */+ { 18, 7, 12, 0, 0, 18432, 82, }, /* 830 */+ { 18, 7, 12, 0, 0, 18432, 170, }, /* 831 */+ { 69, 26, 12, 0, 0, 18447, 68, }, /* 832 */+ { 69, 15, 12, 0, 0, 18447, 68, }, /* 833 */+ { 18, 26, 12, 0, 0, 18432, 68, }, /* 834 */+ { 18, 26, 12, 0, 0, 28672, 68, }, /* 835 */+ { 69, 15, 12, 0, 0, 18432, 68, }, /* 836 */+ { 69, 26, 14, 0, 0, 18447, 236, }, /* 837 */+ { 21, 26, 12, 0, 0, 18432, 68, }, /* 838 */+ { 23, 7, 12, 0, 0, 18432, 292, }, /* 839 */+ { 24, 7, 12, 0, 0, 18432, 82, }, /* 840 */+ { 24, 6, 12, 0, 0, 18432, 136, }, /* 841 */+ { 24, 26, 12, 0, 0, 28672, 68, }, /* 842 */+ { 111, 7, 12, 0, 0, 18432, 82, }, /* 843 */+ { 111, 6, 12, 0, 0, 18432, 142, }, /* 844 */+ { 111, 21, 12, 0, 0, 18432, 106, }, /* 845 */+ { 111, 21, 12, 0, 0, 18432, 124, }, /* 846 */+ { 99, 7, 12, 0, 0, 18432, 82, }, /* 847 */+ { 99, 6, 12, 0, 0, 18432, 136, }, /* 848 */+ { 99, 21, 12, 0, 0, 28672, 106, }, /* 849 */+ { 99, 21, 12, 0, 0, 28672, 124, }, /* 850 */+ { 99, 13, 12, 0, 0, 18432, 138, }, /* 851 */+ { 2, 9, 12, 108, 1, 18432, 74, }, /* 852 */+ { 2, 5, 12, 108, -35267, 18432, 76, }, /* 853 */+ { 2, 7, 12, 0, 0, 18432, 82, }, /* 854 */+ { 2, 21, 12, 0, 0, 28672, 68, }, /* 855 */+ { 2, 12, 3, 0, 0, 26624, 96, }, /* 856 */+ { 2, 6, 12, 0, 0, 28672, 92, }, /* 857 */+ { 2, 6, 12, 0, 0, 18432, 88, }, /* 858 */+ { 112, 7, 12, 0, 0, 18432, 82, }, /* 859 */+ { 112, 14, 12, 0, 0, 18432, 82, }, /* 860 */+ { 112, 12, 3, 0, 0, 26624, 96, }, /* 861 */+ { 112, 21, 12, 0, 0, 18432, 68, }, /* 862 */+ { 112, 21, 12, 0, 0, 18432, 124, }, /* 863 */+ { 112, 21, 12, 0, 0, 18432, 106, }, /* 864 */+ { 69, 24, 12, 0, 0, 28762, 56, }, /* 865 */+ { 0, 9, 12, 0, -35332, 18432, 74, }, /* 866 */+ { 69, 24, 12, 0, 0, 18432, 56, }, /* 867 */+ { 0, 9, 12, 0, -42280, 18432, 74, }, /* 868 */+ { 0, 5, 12, 0, 48, 18432, 76, }, /* 869 */+ { 0, 9, 12, 0, -42308, 18432, 74, }, /* 870 */+ { 0, 9, 12, 0, -42319, 18432, 74, }, /* 871 */+ { 0, 9, 12, 0, -42315, 18432, 74, }, /* 872 */+ { 0, 9, 12, 0, -42305, 18432, 74, }, /* 873 */+ { 0, 9, 12, 0, -42258, 18432, 74, }, /* 874 */+ { 0, 9, 12, 0, -42282, 18432, 74, }, /* 875 */+ { 0, 9, 12, 0, -42261, 18432, 74, }, /* 876 */+ { 0, 9, 12, 0, 928, 18432, 74, }, /* 877 */+ { 0, 9, 12, 0, -48, 18432, 74, }, /* 878 */+ { 0, 9, 12, 0, -42307, 18432, 74, }, /* 879 */+ { 0, 9, 12, 0, -35384, 18432, 74, }, /* 880 */+ { 36, 7, 12, 0, 0, 18432, 82, }, /* 881 */+ { 36, 12, 3, 0, 0, 26624, 130, }, /* 882 */+ { 36, 12, 3, 0, 0, 26624, 184, }, /* 883 */+ { 36, 10, 5, 0, 0, 18432, 144, }, /* 884 */+ { 36, 26, 12, 0, 0, 28672, 68, }, /* 885 */+ { 69, 15, 12, 0, 0, 18612, 68, }, /* 886 */+ { 69, 15, 12, 0, 0, 18609, 68, }, /* 887 */+ { 69, 26, 12, 0, 0, 18600, 68, }, /* 888 */+ { 69, 23, 12, 0, 0, 14504, 68, }, /* 889 */+ { 69, 26, 12, 0, 0, 14504, 68, }, /* 890 */+ { 37, 7, 12, 0, 0, 18432, 82, }, /* 891 */+ { 37, 21, 12, 0, 0, 28672, 68, }, /* 892 */+ { 37, 21, 12, 0, 0, 28672, 124, }, /* 893 */+ { 100, 10, 5, 0, 0, 18432, 144, }, /* 894 */+ { 100, 7, 12, 0, 0, 18432, 82, }, /* 895 */+ { 100, 12, 3, 0, 0, 26624, 146, }, /* 896 */+ { 100, 12, 3, 0, 0, 26624, 130, }, /* 897 */+ { 100, 21, 12, 0, 0, 18432, 124, }, /* 898 */+ { 100, 13, 12, 0, 0, 18432, 138, }, /* 899 */+ { 6, 12, 3, 0, 0, 26666, 96, }, /* 900 */+ { 6, 7, 12, 0, 0, 18507, 82, }, /* 901 */+ { 39, 13, 12, 0, 0, 18432, 138, }, /* 902 */+ { 39, 7, 12, 0, 0, 18432, 82, }, /* 903 */+ { 39, 12, 3, 0, 0, 26624, 130, }, /* 904 */+ { 39, 12, 3, 0, 0, 26624, 96, }, /* 905 */+ { 69, 21, 12, 0, 0, 18567, 190, }, /* 906 */+ { 39, 21, 12, 0, 0, 18432, 124, }, /* 907 */+ { 101, 7, 12, 0, 0, 18432, 82, }, /* 908 */+ { 101, 12, 3, 0, 0, 26624, 130, }, /* 909 */+ { 101, 10, 5, 0, 0, 18432, 144, }, /* 910 */+ { 101, 10, 5, 0, 0, 18432, 174, }, /* 911 */+ { 101, 21, 12, 0, 0, 18432, 68, }, /* 912 */+ { 40, 12, 3, 0, 0, 26624, 130, }, /* 913 */+ { 40, 10, 5, 0, 0, 18432, 144, }, /* 914 */+ { 40, 7, 12, 0, 0, 18432, 82, }, /* 915 */+ { 40, 12, 3, 0, 0, 26624, 96, }, /* 916 */+ { 40, 10, 5, 0, 0, 18432, 174, }, /* 917 */+ { 40, 21, 12, 0, 0, 18432, 68, }, /* 918 */+ { 40, 21, 12, 0, 0, 18432, 106, }, /* 919 */+ { 40, 21, 12, 0, 0, 18432, 124, }, /* 920 */+ { 69, 6, 12, 0, 0, 18480, 136, }, /* 921 */+ { 40, 13, 12, 0, 0, 18432, 138, }, /* 922 */+ { 16, 6, 12, 0, 0, 18432, 136, }, /* 923 */+ { 105, 7, 12, 0, 0, 18432, 82, }, /* 924 */+ { 105, 12, 3, 0, 0, 26624, 130, }, /* 925 */+ { 105, 10, 5, 0, 0, 18432, 144, }, /* 926 */+ { 105, 13, 12, 0, 0, 18432, 138, }, /* 927 */+ { 105, 21, 12, 0, 0, 18432, 68, }, /* 928 */+ { 105, 21, 12, 0, 0, 18432, 124, }, /* 929 */+ { 107, 7, 12, 0, 0, 18432, 82, }, /* 930 */+ { 107, 12, 3, 0, 0, 26624, 130, }, /* 931 */+ { 107, 7, 12, 0, 0, 18432, 156, }, /* 932 */+ { 107, 12, 3, 0, 0, 26624, 96, }, /* 933 */+ { 107, 7, 12, 0, 0, 18432, 294, }, /* 934 */+ { 107, 6, 12, 0, 0, 18432, 136, }, /* 935 */+ { 107, 21, 12, 0, 0, 18432, 68, }, /* 936 */+ { 107, 21, 12, 0, 0, 18432, 106, }, /* 937 */+ { 113, 7, 12, 0, 0, 18432, 82, }, /* 938 */+ { 113, 10, 5, 0, 0, 18432, 144, }, /* 939 */+ { 113, 12, 3, 0, 0, 26624, 130, }, /* 940 */+ { 113, 21, 12, 0, 0, 18432, 124, }, /* 941 */+ { 113, 6, 12, 0, 0, 18432, 136, }, /* 942 */+ { 113, 12, 3, 0, 0, 26624, 146, }, /* 943 */+ { 0, 5, 12, 0, -928, 18432, 76, }, /* 944 */+ { 76, 5, 12, 0, -38864, 18432, 70, }, /* 945 */+ { 113, 10, 5, 0, 0, 18432, 160, }, /* 946 */+ { 113, 13, 12, 0, 0, 18432, 138, }, /* 947 */+ { 18, 7, 9, 0, 0, 18432, 82, }, /* 948 */+ { 18, 7, 10, 0, 0, 18432, 82, }, /* 949 */+ { 68, 4, 12, 0, 0, 18432, 0, }, /* 950 */+ { 68, 3, 12, 0, 0, 18432, 0, }, /* 951 */+ { 23, 7, 12, 0, 0, 18432, 284, }, /* 952 */+ { 71, 25, 12, 0, 0, 12288, 118, }, /* 953 */+ { 3, 7, 12, 0, 0, 0, 296, }, /* 954 */+ { 69, 18, 12, 0, 0, 28705, 54, }, /* 955 */+ { 69, 22, 12, 0, 0, 28705, 54, }, /* 956 */+ { 68, 2, 12, 0, 0, 6144, 298, }, /* 957 */+ { 3, 7, 12, 0, 0, 39, 82, }, /* 958 */+ { 3, 26, 12, 0, 0, 28711, 68, }, /* 959 */+ { 84, 12, 3, 0, 0, 26624, 180, }, /* 960 */+ { 84, 12, 3, 0, 0, 26624, 300, }, /* 961 */+ { 69, 21, 12, 0, 0, 28672, 68, }, /* 962 */+ { 69, 21, 12, 0, 0, 28672, 122, }, /* 963 */+ { 69, 22, 12, 0, 0, 28672, 68, }, /* 964 */+ { 69, 18, 12, 0, 0, 28672, 68, }, /* 965 */+ { 69, 17, 12, 0, 0, 28672, 126, }, /* 966 */+ { 69, 22, 12, 0, 0, 28672, 302, }, /* 967 */+ { 69, 18, 12, 0, 0, 28672, 302, }, /* 968 */+ { 69, 21, 12, 0, 0, 8192, 106, }, /* 969 */+ { 69, 21, 12, 0, 0, 8192, 304, }, /* 970 */+ { 69, 21, 12, 0, 0, 8192, 306, }, /* 971 */+ { 69, 21, 12, 0, 0, 28672, 124, }, /* 972 */+ { 69, 22, 12, 0, 0, 28672, 158, }, /* 973 */+ { 69, 18, 12, 0, 0, 28672, 158, }, /* 974 */+ { 69, 21, 12, 0, 0, 14336, 68, }, /* 975 */+ { 69, 21, 12, 0, 0, 28672, 118, }, /* 976 */+ { 69, 17, 12, 0, 0, 12288, 224, }, /* 977 */+ { 69, 25, 12, 0, 0, 28672, 226, }, /* 978 */+ { 69, 21, 12, 0, 0, 28672, 302, }, /* 979 */+ { 69, 21, 12, 0, 0, 28672, 308, }, /* 980 */+ { 69, 17, 12, 0, 0, 12288, 126, }, /* 981 */+ { 69, 21, 12, 0, 0, 8192, 68, }, /* 982 */+ { 69, 13, 12, 0, 0, 10240, 310, }, /* 983 */+ { 0, 9, 12, 0, 32, 18432, 312, }, /* 984 */+ { 69, 24, 12, 0, 0, 28672, 314, }, /* 985 */+ { 0, 5, 12, 0, -32, 18432, 316, }, /* 986 */+ { 69, 21, 12, 0, 0, 28825, 124, }, /* 987 */+ { 69, 22, 12, 0, 0, 28825, 318, }, /* 988 */+ { 69, 18, 12, 0, 0, 28825, 318, }, /* 989 */+ { 69, 21, 12, 0, 0, 28825, 106, }, /* 990 */+ { 69, 6, 3, 0, 0, 18525, 320, }, /* 991 */+ { 69, 1, 2, 0, 0, 28672, 322, }, /* 992 */+ { 31, 7, 12, 0, 0, 18432, 82, }, /* 993 */+ { 69, 21, 12, 0, 0, 18552, 68, }, /* 994 */+ { 69, 21, 12, 0, 0, 28792, 68, }, /* 995 */+ { 69, 21, 12, 0, 0, 18483, 68, }, /* 996 */+ { 69, 15, 12, 0, 0, 18555, 68, }, /* 997 */+ { 69, 26, 12, 0, 0, 18483, 68, }, /* 998 */+ { 1, 14, 12, 0, 0, 28672, 82, }, /* 999 */+ { 1, 15, 12, 0, 0, 28672, 68, }, /* 1000 */+ { 1, 26, 12, 0, 0, 28672, 68, }, /* 1001 */+ { 1, 26, 12, 0, 0, 18432, 68, }, /* 1002 */+ { 102, 7, 12, 0, 0, 18432, 82, }, /* 1003 */+ { 103, 7, 12, 0, 0, 18432, 82, }, /* 1004 */+ { 84, 12, 3, 0, 0, 26651, 96, }, /* 1005 */+ { 69, 15, 12, 0, 0, 10267, 68, }, /* 1006 */+ { 81, 7, 12, 0, 0, 18432, 82, }, /* 1007 */+ { 81, 15, 12, 0, 0, 18432, 68, }, /* 1008 */+ { 82, 7, 12, 0, 0, 18432, 82, }, /* 1009 */+ { 82, 14, 12, 0, 0, 18432, 82, }, /* 1010 */+ { 53, 7, 12, 0, 0, 18432, 82, }, /* 1011 */+ { 53, 12, 3, 0, 0, 26624, 130, }, /* 1012 */+ { 85, 7, 12, 0, 0, 18432, 82, }, /* 1013 */+ { 85, 21, 12, 0, 0, 18432, 106, }, /* 1014 */+ { 91, 7, 12, 0, 0, 18432, 82, }, /* 1015 */+ { 91, 21, 12, 0, 0, 18432, 106, }, /* 1016 */+ { 91, 14, 12, 0, 0, 18432, 82, }, /* 1017 */+ { 83, 9, 12, 0, 40, 18432, 74, }, /* 1018 */+ { 83, 5, 12, 0, -40, 18432, 76, }, /* 1019 */+ { 86, 7, 12, 0, 0, 18432, 82, }, /* 1020 */+ { 87, 7, 12, 0, 0, 18432, 82, }, /* 1021 */+ { 87, 13, 12, 0, 0, 18432, 138, }, /* 1022 */+ { 145, 9, 12, 0, 40, 18432, 74, }, /* 1023 */+ { 145, 5, 12, 0, -40, 18432, 76, }, /* 1024 */+ { 127, 7, 12, 0, 0, 18432, 82, }, /* 1025 */+ { 125, 7, 12, 0, 0, 18432, 82, }, /* 1026 */+ { 125, 21, 12, 0, 0, 18432, 68, }, /* 1027 */+ { 161, 9, 12, 0, 39, 18432, 74, }, /* 1028 */+ { 161, 5, 12, 0, -39, 18432, 76, }, /* 1029 */+ { 49, 7, 12, 0, 0, 18432, 82, }, /* 1030 */+ { 0, 6, 12, 0, 0, 18432, 94, }, /* 1031 */+ { 32, 7, 12, 0, 0, 34816, 82, }, /* 1032 */+ { 114, 7, 12, 0, 0, 34816, 82, }, /* 1033 */+ { 114, 21, 12, 0, 0, 34816, 106, }, /* 1034 */+ { 114, 15, 12, 0, 0, 34816, 68, }, /* 1035 */+ { 133, 7, 12, 0, 0, 34816, 82, }, /* 1036 */+ { 133, 26, 12, 0, 0, 34816, 68, }, /* 1037 */+ { 133, 15, 12, 0, 0, 34816, 68, }, /* 1038 */+ { 132, 7, 12, 0, 0, 34816, 82, }, /* 1039 */+ { 132, 15, 12, 0, 0, 34816, 68, }, /* 1040 */+ { 139, 7, 12, 0, 0, 34816, 82, }, /* 1041 */+ { 139, 15, 12, 0, 0, 34816, 68, }, /* 1042 */+ { 95, 7, 12, 0, 0, 34816, 82, }, /* 1043 */+ { 95, 15, 12, 0, 0, 34816, 68, }, /* 1044 */+ { 95, 21, 12, 0, 0, 28672, 106, }, /* 1045 */+ { 104, 7, 12, 0, 0, 34816, 82, }, /* 1046 */+ { 104, 21, 12, 0, 0, 34816, 68, }, /* 1047 */+ { 122, 7, 12, 0, 0, 34816, 82, }, /* 1048 */+ { 121, 7, 12, 0, 0, 34816, 82, }, /* 1049 */+ { 121, 15, 12, 0, 0, 34816, 68, }, /* 1050 */+ { 92, 7, 12, 0, 0, 34816, 82, }, /* 1051 */+ { 92, 12, 3, 0, 0, 26624, 130, }, /* 1052 */+ { 92, 12, 3, 0, 0, 26624, 102, }, /* 1053 */+ { 92, 12, 3, 0, 0, 26624, 184, }, /* 1054 */+ { 92, 15, 12, 0, 0, 34816, 68, }, /* 1055 */+ { 92, 21, 12, 0, 0, 34816, 68, }, /* 1056 */+ { 92, 21, 12, 0, 0, 34816, 124, }, /* 1057 */+ { 115, 7, 12, 0, 0, 34816, 82, }, /* 1058 */+ { 115, 15, 12, 0, 0, 34816, 68, }, /* 1059 */+ { 115, 21, 12, 0, 0, 34816, 68, }, /* 1060 */+ { 131, 7, 12, 0, 0, 34816, 82, }, /* 1061 */+ { 131, 15, 12, 0, 0, 34816, 68, }, /* 1062 */+ { 51, 7, 12, 0, 0, 34816, 82, }, /* 1063 */+ { 51, 26, 12, 0, 0, 34816, 68, }, /* 1064 */+ { 51, 12, 3, 0, 0, 26624, 96, }, /* 1065 */+ { 51, 15, 12, 0, 0, 34816, 68, }, /* 1066 */+ { 51, 21, 12, 0, 0, 34816, 106, }, /* 1067 */+ { 51, 21, 12, 0, 0, 34918, 106, }, /* 1068 */+ { 51, 21, 12, 0, 0, 34816, 68, }, /* 1069 */+ { 108, 7, 12, 0, 0, 34816, 82, }, /* 1070 */+ { 108, 21, 12, 0, 0, 28672, 68, }, /* 1071 */+ { 108, 21, 12, 0, 0, 28672, 106, }, /* 1072 */+ { 116, 7, 12, 0, 0, 34816, 82, }, /* 1073 */+ { 116, 15, 12, 0, 0, 34816, 68, }, /* 1074 */+ { 117, 7, 12, 0, 0, 34816, 82, }, /* 1075 */+ { 117, 15, 12, 0, 0, 34816, 68, }, /* 1076 */+ { 54, 7, 12, 0, 0, 34816, 82, }, /* 1077 */+ { 54, 21, 12, 0, 0, 34816, 106, }, /* 1078 */+ { 54, 15, 12, 0, 0, 34816, 68, }, /* 1079 */+ { 118, 7, 12, 0, 0, 34816, 82, }, /* 1080 */+ { 140, 9, 12, 0, 64, 34816, 74, }, /* 1081 */+ { 140, 5, 12, 0, -64, 34816, 76, }, /* 1082 */+ { 140, 15, 12, 0, 0, 34816, 68, }, /* 1083 */+ { 62, 7, 12, 0, 0, 0, 82, }, /* 1084 */+ { 62, 7, 12, 0, 0, 0, 294, }, /* 1085 */+ { 62, 12, 3, 0, 0, 26624, 128, }, /* 1086 */+ { 62, 13, 12, 0, 0, 2048, 138, }, /* 1087 */+ { 3, 15, 12, 0, 0, 2048, 68, }, /* 1088 */+ { 65, 7, 12, 0, 0, 34816, 82, }, /* 1089 */+ { 65, 12, 3, 0, 0, 26624, 130, }, /* 1090 */+ { 65, 17, 12, 0, 0, 34816, 126, }, /* 1091 */+ { 152, 7, 12, 0, 0, 34816, 82, }, /* 1092 */+ { 152, 15, 12, 0, 0, 34816, 68, }, /* 1093 */+ { 63, 7, 12, 0, 0, 0, 82, }, /* 1094 */+ { 63, 12, 3, 0, 0, 26624, 96, }, /* 1095 */+ { 63, 15, 12, 0, 0, 0, 68, }, /* 1096 */+ { 63, 21, 12, 0, 0, 0, 124, }, /* 1097 */+ { 67, 7, 12, 0, 0, 34816, 82, }, /* 1098 */+ { 67, 12, 3, 0, 0, 26624, 96, }, /* 1099 */+ { 67, 21, 12, 0, 0, 34816, 124, }, /* 1100 */+ { 156, 7, 12, 0, 0, 34816, 82, }, /* 1101 */+ { 156, 15, 12, 0, 0, 34816, 68, }, /* 1102 */+ { 153, 7, 12, 0, 0, 34816, 82, }, /* 1103 */+ { 120, 10, 5, 0, 0, 18432, 144, }, /* 1104 */+ { 120, 12, 3, 0, 0, 26624, 130, }, /* 1105 */+ { 120, 7, 12, 0, 0, 18432, 82, }, /* 1106 */+ { 120, 12, 3, 0, 0, 26624, 146, }, /* 1107 */+ { 120, 21, 12, 0, 0, 18432, 124, }, /* 1108 */+ { 120, 21, 12, 0, 0, 18432, 106, }, /* 1109 */+ { 120, 15, 12, 0, 0, 28672, 68, }, /* 1110 */+ { 120, 13, 12, 0, 0, 18432, 138, }, /* 1111 */+ { 120, 12, 3, 0, 0, 26624, 184, }, /* 1112 */+ { 41, 12, 3, 0, 0, 26624, 130, }, /* 1113 */+ { 41, 10, 5, 0, 0, 18432, 144, }, /* 1114 */+ { 41, 7, 12, 0, 0, 18432, 82, }, /* 1115 */+ { 41, 12, 3, 0, 0, 26624, 146, }, /* 1116 */+ { 41, 12, 3, 0, 0, 26624, 96, }, /* 1117 */+ { 41, 21, 12, 0, 0, 18432, 68, }, /* 1118 */+ { 41, 1, 4, 0, 0, 18432, 132, }, /* 1119 */+ { 41, 21, 12, 0, 0, 18432, 124, }, /* 1120 */+ { 124, 7, 12, 0, 0, 18432, 82, }, /* 1121 */+ { 124, 13, 12, 0, 0, 18432, 138, }, /* 1122 */+ { 43, 12, 3, 0, 0, 26624, 130, }, /* 1123 */+ { 43, 7, 12, 0, 0, 18432, 82, }, /* 1124 */+ { 43, 10, 5, 0, 0, 18432, 144, }, /* 1125 */+ { 43, 12, 3, 0, 0, 26624, 146, }, /* 1126 */+ { 43, 13, 12, 0, 0, 18432, 138, }, /* 1127 */+ { 43, 21, 12, 0, 0, 18432, 68, }, /* 1128 */+ { 43, 21, 12, 0, 0, 18432, 124, }, /* 1129 */+ { 50, 7, 12, 0, 0, 18432, 82, }, /* 1130 */+ { 50, 12, 3, 0, 0, 26624, 96, }, /* 1131 */+ { 50, 21, 12, 0, 0, 18432, 68, }, /* 1132 */+ { 44, 12, 3, 0, 0, 26624, 130, }, /* 1133 */+ { 44, 10, 5, 0, 0, 18432, 144, }, /* 1134 */+ { 44, 7, 12, 0, 0, 18432, 82, }, /* 1135 */+ { 44, 10, 5, 0, 0, 18432, 174, }, /* 1136 */+ { 44, 7, 4, 0, 0, 18432, 82, }, /* 1137 */+ { 44, 21, 12, 0, 0, 18432, 124, }, /* 1138 */+ { 44, 21, 12, 0, 0, 18432, 68, }, /* 1139 */+ { 44, 12, 3, 0, 0, 26624, 102, }, /* 1140 */+ { 44, 12, 3, 0, 0, 26624, 96, }, /* 1141 */+ { 44, 13, 12, 0, 0, 18432, 138, }, /* 1142 */+ { 15, 15, 12, 0, 0, 18432, 68, }, /* 1143 */+ { 48, 7, 12, 0, 0, 18432, 82, }, /* 1144 */+ { 48, 10, 5, 0, 0, 18432, 144, }, /* 1145 */+ { 48, 12, 3, 0, 0, 26624, 130, }, /* 1146 */+ { 48, 10, 5, 0, 0, 18432, 174, }, /* 1147 */+ { 48, 12, 3, 0, 0, 26624, 96, }, /* 1148 */+ { 48, 21, 12, 0, 0, 18432, 124, }, /* 1149 */+ { 48, 21, 12, 0, 0, 18432, 106, }, /* 1150 */+ { 48, 21, 12, 0, 0, 18432, 68, }, /* 1151 */+ { 57, 7, 12, 0, 0, 18432, 82, }, /* 1152 */+ { 57, 21, 12, 0, 0, 18432, 124, }, /* 1153 */+ { 55, 7, 12, 0, 0, 18432, 82, }, /* 1154 */+ { 55, 12, 3, 0, 0, 26624, 130, }, /* 1155 */+ { 55, 10, 5, 0, 0, 18432, 144, }, /* 1156 */+ { 55, 12, 3, 0, 0, 26624, 96, }, /* 1157 */+ { 55, 12, 3, 0, 0, 26624, 146, }, /* 1158 */+ { 55, 13, 12, 0, 0, 18432, 138, }, /* 1159 */+ { 47, 12, 3, 0, 0, 26624, 130, }, /* 1160 */+ { 47, 12, 3, 0, 0, 26705, 130, }, /* 1161 */+ { 47, 10, 5, 0, 0, 18432, 144, }, /* 1162 */+ { 47, 10, 5, 0, 0, 18513, 144, }, /* 1163 */+ { 47, 7, 12, 0, 0, 18432, 82, }, /* 1164 */+ { 84, 12, 3, 0, 0, 26705, 102, }, /* 1165 */+ { 47, 12, 3, 0, 0, 26705, 96, }, /* 1166 */+ { 47, 10, 3, 0, 0, 18432, 148, }, /* 1167 */+ { 47, 10, 5, 0, 0, 18432, 174, }, /* 1168 */+ { 47, 7, 12, 0, 0, 18432, 324, }, /* 1169 */+ { 47, 12, 3, 0, 0, 26624, 96, }, /* 1170 */+ { 144, 7, 12, 0, 0, 18432, 82, }, /* 1171 */+ { 144, 10, 5, 0, 0, 18432, 144, }, /* 1172 */+ { 144, 12, 3, 0, 0, 26624, 130, }, /* 1173 */+ { 144, 12, 3, 0, 0, 26624, 146, }, /* 1174 */+ { 144, 12, 3, 0, 0, 26624, 96, }, /* 1175 */+ { 144, 21, 12, 0, 0, 18432, 124, }, /* 1176 */+ { 144, 21, 12, 0, 0, 18432, 106, }, /* 1177 */+ { 144, 21, 12, 0, 0, 18432, 68, }, /* 1178 */+ { 144, 13, 12, 0, 0, 18432, 138, }, /* 1179 */+ { 144, 12, 3, 0, 0, 26624, 102, }, /* 1180 */+ { 56, 7, 12, 0, 0, 18432, 82, }, /* 1181 */+ { 56, 10, 3, 0, 0, 18432, 148, }, /* 1182 */+ { 56, 10, 5, 0, 0, 18432, 144, }, /* 1183 */+ { 56, 12, 3, 0, 0, 26624, 130, }, /* 1184 */+ { 56, 12, 3, 0, 0, 26624, 146, }, /* 1185 */+ { 56, 12, 3, 0, 0, 26624, 96, }, /* 1186 */+ { 56, 21, 12, 0, 0, 18432, 68, }, /* 1187 */+ { 56, 13, 12, 0, 0, 18432, 138, }, /* 1188 */+ { 135, 7, 12, 0, 0, 18432, 82, }, /* 1189 */+ { 135, 10, 3, 0, 0, 18432, 148, }, /* 1190 */+ { 135, 10, 5, 0, 0, 18432, 144, }, /* 1191 */+ { 135, 12, 3, 0, 0, 26624, 130, }, /* 1192 */+ { 135, 12, 3, 0, 0, 26624, 146, }, /* 1193 */+ { 135, 12, 3, 0, 0, 26624, 96, }, /* 1194 */+ { 135, 21, 12, 0, 0, 18432, 68, }, /* 1195 */+ { 135, 21, 12, 0, 0, 18432, 124, }, /* 1196 */+ { 135, 21, 12, 0, 0, 18432, 106, }, /* 1197 */+ { 135, 21, 12, 0, 0, 18432, 178, }, /* 1198 */+ { 52, 7, 12, 0, 0, 18432, 82, }, /* 1199 */+ { 52, 10, 5, 0, 0, 18432, 144, }, /* 1200 */+ { 52, 12, 3, 0, 0, 26624, 130, }, /* 1201 */+ { 52, 12, 3, 0, 0, 26624, 146, }, /* 1202 */+ { 52, 21, 12, 0, 0, 18432, 124, }, /* 1203 */+ { 52, 21, 12, 0, 0, 18432, 68, }, /* 1204 */+ { 52, 13, 12, 0, 0, 18432, 138, }, /* 1205 */+ { 45, 7, 12, 0, 0, 18432, 82, }, /* 1206 */+ { 45, 12, 3, 0, 0, 26624, 130, }, /* 1207 */+ { 45, 10, 5, 0, 0, 18432, 144, }, /* 1208 */+ { 45, 10, 5, 0, 0, 18432, 174, }, /* 1209 */+ { 45, 12, 3, 0, 0, 26624, 96, }, /* 1210 */+ { 45, 21, 12, 0, 0, 18432, 68, }, /* 1211 */+ { 45, 13, 12, 0, 0, 18432, 138, }, /* 1212 */+ { 137, 7, 12, 0, 0, 18432, 82, }, /* 1213 */+ { 137, 12, 3, 0, 0, 26624, 130, }, /* 1214 */+ { 137, 10, 12, 0, 0, 18432, 144, }, /* 1215 */+ { 137, 10, 5, 0, 0, 18432, 144, }, /* 1216 */+ { 137, 12, 3, 0, 0, 26624, 146, }, /* 1217 */+ { 137, 13, 12, 0, 0, 18432, 138, }, /* 1218 */+ { 137, 15, 12, 0, 0, 18432, 68, }, /* 1219 */+ { 137, 21, 12, 0, 0, 18432, 124, }, /* 1220 */+ { 137, 26, 12, 0, 0, 18432, 68, }, /* 1221 */+ { 60, 7, 12, 0, 0, 18432, 82, }, /* 1222 */+ { 60, 10, 5, 0, 0, 18432, 144, }, /* 1223 */+ { 60, 12, 3, 0, 0, 26624, 130, }, /* 1224 */+ { 60, 12, 3, 0, 0, 26624, 146, }, /* 1225 */+ { 60, 12, 3, 0, 0, 26624, 96, }, /* 1226 */+ { 60, 21, 12, 0, 0, 18432, 68, }, /* 1227 */+ { 136, 9, 12, 0, 32, 18432, 74, }, /* 1228 */+ { 136, 5, 12, 0, -32, 18432, 76, }, /* 1229 */+ { 136, 13, 12, 0, 0, 18432, 138, }, /* 1230 */+ { 136, 15, 12, 0, 0, 18432, 68, }, /* 1231 */+ { 136, 7, 12, 0, 0, 18432, 82, }, /* 1232 */+ { 157, 7, 12, 0, 0, 18432, 82, }, /* 1233 */+ { 157, 10, 3, 0, 0, 18432, 148, }, /* 1234 */+ { 157, 10, 5, 0, 0, 18432, 144, }, /* 1235 */+ { 157, 12, 3, 0, 0, 26624, 130, }, /* 1236 */+ { 157, 10, 5, 0, 0, 18432, 174, }, /* 1237 */+ { 157, 12, 3, 0, 0, 26624, 146, }, /* 1238 */+ { 157, 7, 4, 0, 0, 18432, 82, }, /* 1239 */+ { 157, 12, 3, 0, 0, 26624, 96, }, /* 1240 */+ { 157, 21, 12, 0, 0, 18432, 124, }, /* 1241 */+ { 157, 21, 12, 0, 0, 18432, 68, }, /* 1242 */+ { 157, 13, 12, 0, 0, 18432, 138, }, /* 1243 */+ { 64, 7, 12, 0, 0, 18432, 82, }, /* 1244 */+ { 64, 10, 5, 0, 0, 18432, 144, }, /* 1245 */+ { 64, 12, 3, 0, 0, 26624, 130, }, /* 1246 */+ { 64, 12, 3, 0, 0, 26624, 146, }, /* 1247 */+ { 64, 21, 12, 0, 0, 18432, 68, }, /* 1248 */+ { 149, 7, 12, 0, 0, 18432, 82, }, /* 1249 */+ { 149, 12, 3, 0, 0, 26624, 130, }, /* 1250 */+ { 149, 12, 3, 0, 0, 18432, 130, }, /* 1251 */+ { 149, 12, 3, 0, 0, 26624, 102, }, /* 1252 */+ { 149, 12, 3, 0, 0, 26624, 146, }, /* 1253 */+ { 149, 10, 5, 0, 0, 18432, 144, }, /* 1254 */+ { 149, 7, 4, 0, 0, 18432, 82, }, /* 1255 */+ { 149, 21, 12, 0, 0, 18432, 68, }, /* 1256 */+ { 149, 21, 12, 0, 0, 18432, 124, }, /* 1257 */+ { 148, 7, 12, 0, 0, 18432, 82, }, /* 1258 */+ { 148, 12, 3, 0, 0, 26624, 130, }, /* 1259 */+ { 148, 10, 5, 0, 0, 18432, 144, }, /* 1260 */+ { 148, 7, 4, 0, 0, 18432, 82, }, /* 1261 */+ { 148, 12, 3, 0, 0, 26624, 326, }, /* 1262 */+ { 148, 12, 3, 0, 0, 26624, 146, }, /* 1263 */+ { 148, 21, 12, 0, 0, 18432, 68, }, /* 1264 */+ { 148, 21, 12, 0, 0, 18432, 124, }, /* 1265 */+ { 148, 21, 12, 0, 0, 18432, 106, }, /* 1266 */+ { 134, 7, 12, 0, 0, 18432, 82, }, /* 1267 */+ { 142, 7, 12, 0, 0, 18432, 82, }, /* 1268 */+ { 142, 10, 5, 0, 0, 18432, 144, }, /* 1269 */+ { 142, 12, 3, 0, 0, 26624, 130, }, /* 1270 */+ { 142, 12, 3, 0, 0, 18432, 146, }, /* 1271 */+ { 142, 21, 12, 0, 0, 18432, 124, }, /* 1272 */+ { 142, 21, 12, 0, 0, 18432, 106, }, /* 1273 */+ { 142, 21, 12, 0, 0, 18432, 68, }, /* 1274 */+ { 142, 13, 12, 0, 0, 18432, 138, }, /* 1275 */+ { 142, 15, 12, 0, 0, 18432, 68, }, /* 1276 */+ { 143, 21, 12, 0, 0, 18432, 68, }, /* 1277 */+ { 143, 21, 12, 0, 0, 18432, 106, }, /* 1278 */+ { 143, 7, 12, 0, 0, 18432, 82, }, /* 1279 */+ { 143, 12, 3, 0, 0, 26624, 130, }, /* 1280 */+ { 143, 10, 5, 0, 0, 18432, 144, }, /* 1281 */+ { 59, 7, 12, 0, 0, 18432, 82, }, /* 1282 */+ { 59, 12, 3, 0, 0, 26624, 130, }, /* 1283 */+ { 59, 12, 3, 0, 0, 26624, 96, }, /* 1284 */+ { 59, 12, 3, 0, 0, 26624, 146, }, /* 1285 */+ { 59, 7, 4, 0, 0, 18432, 82, }, /* 1286 */+ { 59, 13, 12, 0, 0, 18432, 138, }, /* 1287 */+ { 61, 7, 12, 0, 0, 18432, 82, }, /* 1288 */+ { 61, 10, 5, 0, 0, 18432, 144, }, /* 1289 */+ { 61, 12, 3, 0, 0, 26624, 130, }, /* 1290 */+ { 61, 12, 3, 0, 0, 26624, 146, }, /* 1291 */+ { 61, 13, 12, 0, 0, 18432, 138, }, /* 1292 */+ { 150, 7, 12, 0, 0, 18432, 82, }, /* 1293 */+ { 150, 12, 3, 0, 0, 26624, 130, }, /* 1294 */+ { 150, 10, 5, 0, 0, 18432, 144, }, /* 1295 */+ { 150, 21, 12, 0, 0, 18432, 124, }, /* 1296 */+ { 162, 12, 3, 0, 0, 26624, 130, }, /* 1297 */+ { 162, 7, 4, 0, 0, 18432, 82, }, /* 1298 */+ { 162, 10, 5, 0, 0, 18432, 144, }, /* 1299 */+ { 162, 7, 12, 0, 0, 18432, 82, }, /* 1300 */+ { 162, 10, 5, 0, 0, 18432, 176, }, /* 1301 */+ { 162, 12, 3, 0, 0, 26624, 184, }, /* 1302 */+ { 162, 21, 12, 0, 0, 18432, 124, }, /* 1303 */+ { 162, 21, 12, 0, 0, 18432, 68, }, /* 1304 */+ { 162, 13, 12, 0, 0, 18432, 138, }, /* 1305 */+ { 11, 15, 12, 0, 0, 18432, 68, }, /* 1306 */+ { 11, 21, 12, 0, 0, 18432, 68, }, /* 1307 */+ { 94, 7, 12, 0, 0, 18432, 82, }, /* 1308 */+ { 94, 14, 12, 0, 0, 18432, 82, }, /* 1309 */+ { 94, 21, 12, 0, 0, 18432, 106, }, /* 1310 */+ { 66, 7, 12, 0, 0, 18432, 82, }, /* 1311 */+ { 66, 21, 12, 0, 0, 18432, 68, }, /* 1312 */+ { 109, 7, 12, 0, 0, 18432, 82, }, /* 1313 */+ { 109, 1, 2, 0, 0, 18432, 322, }, /* 1314 */+ { 109, 12, 3, 0, 0, 26624, 102, }, /* 1315 */+ { 109, 12, 3, 0, 0, 26624, 96, }, /* 1316 */+ { 138, 7, 12, 0, 0, 18432, 82, }, /* 1317 */+ { 130, 7, 12, 0, 0, 18432, 82, }, /* 1318 */+ { 130, 13, 12, 0, 0, 18432, 138, }, /* 1319 */+ { 130, 21, 12, 0, 0, 18432, 124, }, /* 1320 */+ { 159, 7, 12, 0, 0, 18432, 82, }, /* 1321 */+ { 159, 13, 12, 0, 0, 18432, 138, }, /* 1322 */+ { 126, 7, 12, 0, 0, 18432, 82, }, /* 1323 */+ { 126, 12, 3, 0, 0, 26624, 96, }, /* 1324 */+ { 126, 21, 12, 0, 0, 18432, 124, }, /* 1325 */+ { 128, 7, 12, 0, 0, 18432, 82, }, /* 1326 */+ { 128, 12, 3, 0, 0, 26624, 96, }, /* 1327 */+ { 128, 21, 12, 0, 0, 18432, 124, }, /* 1328 */+ { 128, 21, 12, 0, 0, 18432, 106, }, /* 1329 */+ { 128, 21, 12, 0, 0, 18432, 68, }, /* 1330 */+ { 128, 26, 12, 0, 0, 18432, 68, }, /* 1331 */+ { 128, 6, 12, 0, 0, 18432, 142, }, /* 1332 */+ { 128, 6, 12, 0, 0, 18432, 136, }, /* 1333 */+ { 128, 13, 12, 0, 0, 18432, 138, }, /* 1334 */+ { 128, 15, 12, 0, 0, 18432, 68, }, /* 1335 */+ { 151, 9, 12, 0, 32, 18432, 74, }, /* 1336 */+ { 151, 5, 12, 0, -32, 18432, 76, }, /* 1337 */+ { 151, 15, 12, 0, 0, 18432, 68, }, /* 1338 */+ { 151, 21, 12, 0, 0, 18432, 106, }, /* 1339 */+ { 151, 21, 12, 0, 0, 18432, 124, }, /* 1340 */+ { 151, 21, 12, 0, 0, 18432, 68, }, /* 1341 */+ { 123, 7, 12, 0, 0, 18432, 82, }, /* 1342 */+ { 123, 12, 3, 0, 0, 26624, 130, }, /* 1343 */+ { 123, 10, 5, 0, 0, 18432, 144, }, /* 1344 */+ { 123, 12, 3, 0, 0, 26624, 128, }, /* 1345 */+ { 123, 6, 12, 0, 0, 18432, 92, }, /* 1346 */+ { 146, 6, 12, 0, 0, 18432, 136, }, /* 1347 */+ { 147, 6, 12, 0, 0, 18432, 136, }, /* 1348 */+ { 23, 21, 12, 0, 0, 28672, 68, }, /* 1349 */+ { 158, 12, 3, 0, 0, 26624, 328, }, /* 1350 */+ { 23, 10, 5, 0, 0, 18432, 164, }, /* 1351 */+ { 146, 7, 12, 0, 0, 18432, 284, }, /* 1352 */+ { 158, 7, 12, 0, 0, 18432, 284, }, /* 1353 */+ { 21, 6, 12, 0, 0, 18432, 92, }, /* 1354 */+ { 147, 7, 12, 0, 0, 18432, 284, }, /* 1355 */+ { 46, 7, 12, 0, 0, 18432, 82, }, /* 1356 */+ { 46, 26, 12, 0, 0, 18432, 68, }, /* 1357 */+ { 46, 12, 3, 0, 0, 26624, 102, }, /* 1358 */+ { 46, 12, 3, 0, 0, 26624, 130, }, /* 1359 */+ { 46, 21, 12, 0, 0, 18432, 124, }, /* 1360 */+ { 69, 1, 2, 0, 0, 6153, 66, }, /* 1361 */+ { 69, 10, 3, 0, 0, 18432, 330, }, /* 1362 */+ { 69, 10, 5, 0, 0, 18432, 138, }, /* 1363 */+ { 69, 10, 5, 0, 0, 18432, 160, }, /* 1364 */+ { 69, 10, 3, 0, 0, 18432, 286, }, /* 1365 */+ { 1, 12, 3, 0, 0, 26624, 102, }, /* 1366 */+ { 69, 25, 12, 0, 0, 18432, 118, }, /* 1367 */+ { 69, 13, 12, 0, 0, 10240, 214, }, /* 1368 */+ { 141, 26, 12, 0, 0, 18432, 68, }, /* 1369 */+ { 141, 12, 3, 0, 0, 26624, 102, }, /* 1370 */+ { 141, 21, 12, 0, 0, 18432, 106, }, /* 1371 */+ { 141, 21, 12, 0, 0, 18432, 124, }, /* 1372 */+ { 141, 21, 12, 0, 0, 18432, 68, }, /* 1373 */+ { 35, 12, 3, 0, 0, 26624, 130, }, /* 1374 */+ { 2, 6, 12, 0, 0, 18432, 90, }, /* 1375 */+ { 154, 7, 12, 0, 0, 18432, 82, }, /* 1376 */+ { 154, 12, 3, 0, 0, 26624, 96, }, /* 1377 */+ { 154, 6, 12, 0, 0, 18432, 142, }, /* 1378 */+ { 154, 6, 12, 0, 0, 18432, 136, }, /* 1379 */+ { 154, 13, 12, 0, 0, 18432, 138, }, /* 1380 */+ { 154, 26, 12, 0, 0, 18432, 68, }, /* 1381 */+ { 160, 7, 12, 0, 0, 18432, 82, }, /* 1382 */+ { 160, 12, 3, 0, 0, 26624, 96, }, /* 1383 */+ { 155, 7, 12, 0, 0, 18432, 82, }, /* 1384 */+ { 155, 12, 3, 0, 0, 26624, 96, }, /* 1385 */+ { 155, 13, 12, 0, 0, 18432, 138, }, /* 1386 */+ { 155, 23, 12, 0, 0, 14336, 68, }, /* 1387 */+ { 163, 7, 12, 0, 0, 18432, 82, }, /* 1388 */+ { 163, 6, 12, 0, 0, 18432, 142, }, /* 1389 */+ { 163, 12, 3, 0, 0, 26624, 102, }, /* 1390 */+ { 163, 13, 12, 0, 0, 18432, 138, }, /* 1391 */+ { 129, 7, 12, 0, 0, 34816, 82, }, /* 1392 */+ { 129, 15, 12, 0, 0, 34816, 68, }, /* 1393 */+ { 129, 12, 3, 0, 0, 26624, 96, }, /* 1394 */+ { 58, 9, 12, 0, 34, 34816, 74, }, /* 1395 */+ { 58, 5, 12, 0, -34, 34816, 76, }, /* 1396 */+ { 58, 12, 3, 0, 0, 26624, 150, }, /* 1397 */+ { 58, 12, 3, 0, 0, 26624, 130, }, /* 1398 */+ { 58, 12, 3, 0, 0, 26624, 96, }, /* 1399 */+ { 58, 6, 12, 0, 0, 34816, 142, }, /* 1400 */+ { 58, 13, 12, 0, 0, 34816, 138, }, /* 1401 */+ { 58, 21, 12, 0, 0, 34816, 68, }, /* 1402 */+ { 69, 15, 12, 0, 0, 0, 68, }, /* 1403 */+ { 69, 26, 12, 0, 0, 0, 68, }, /* 1404 */+ { 69, 23, 12, 0, 0, 0, 68, }, /* 1405 */+ { 3, 7, 12, 0, 0, 0, 240, }, /* 1406 */+ { 69, 26, 14, 0, 0, 28672, 332, }, /* 1407 */+ { 69, 26, 14, 0, 0, 28672, 334, }, /* 1408 */+ { 68, 2, 14, 0, 0, 18432, 336, }, /* 1409 */+ { 69, 26, 12, 0, 0, 18432, 338, }, /* 1410 */+ { 69, 26, 14, 0, 0, 18432, 340, }, /* 1411 */+ { 69, 26, 14, 0, 0, 18432, 334, }, /* 1412 */+ { 69, 26, 11, 0, 0, 18432, 342, }, /* 1413 */+ { 20, 26, 12, 0, 0, 18432, 68, }, /* 1414 */+ { 69, 26, 14, 0, 0, 18432, 236, }, /* 1415 */+ { 69, 26, 14, 0, 0, 18447, 334, }, /* 1416 */+ { 69, 26, 14, 0, 0, 28672, 344, }, /* 1417 */+ { 69, 26, 14, 0, 0, 28672, 346, }, /* 1418 */+ { 69, 24, 3, 0, 0, 28672, 348, }, /* 1419 */+ { 69, 26, 14, 0, 0, 28672, 350, }, /* 1420 */+ { 69, 13, 12, 0, 0, 10240, 138, }, /* 1421 */+ { 69, 1, 3, 0, 0, 6144, 352, }, /* 1422 */+};++const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* U+0000 */+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 42, 43, 44, 45, /* U+1000 */+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, /* U+1800 */+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, /* U+2000 */+ 78, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, /* U+2800 */+ 93, 94, 95, 96, 97, 98, 99,100,101,101,101,101,101,101,101,101, /* U+3000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+3800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+4000 */+101,101,101,101,101,101,101,101,101,101,101,102,101,101,101,101, /* U+4800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+5000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+5800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+6000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+6800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+7000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+7800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+8000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+8800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+9000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+9800 */+103,104,104,104,104,104,104,104,104,105,106,106,107,108,109,110, /* U+A000 */+111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,119, /* U+A800 */+120,121,122,123,124,125,119,120,121,122,123,124,125,119,120,121, /* U+B000 */+122,123,124,125,119,120,121,122,123,124,125,119,120,121,122,123, /* U+B800 */+124,125,119,120,121,122,123,124,125,119,120,121,122,123,124,125, /* U+C000 */+119,120,121,122,123,124,125,119,120,121,122,123,124,125,119,120, /* U+C800 */+121,122,123,124,125,119,120,121,122,123,124,125,119,120,121,126, /* U+D000 */+127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, /* U+D800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+E000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+E800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F000 */+128,128,129,129,130,131,132,133,134,135,136,137,138,139,140,141, /* U+F800 */+142,143,144,145,146,147,148,149,150,151,152,153,154,154,155,156, /* U+10000 */+157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172, /* U+10800 */+173,174,175,176,177,178,179,146,180,181,146,182,183,184,185,146, /* U+11000 */+186,187,188,189,190,191,192,146,193,194,195,196,146,197,198,199, /* U+11800 */+200,200,200,200,200,200,200,201,202,200,203,146,146,146,146,146, /* U+12000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,204, /* U+12800 */+205,205,205,205,205,205,205,205,206,146,146,146,146,146,146,146, /* U+13000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+13800 */+146,146,146,146,146,146,146,146,207,207,207,207,208,146,146,146, /* U+14000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+14800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+15000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+15800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+16000 */+209,209,209,209,210,211,212,213,146,146,146,146,214,215,216,217, /* U+16800 */+218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, /* U+17000 */+218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, /* U+17800 */+218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,219, /* U+18000 */+218,218,218,218,218,218,220,220,220,221,222,146,146,146,146,146, /* U+18800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+19000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+19800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+1A000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,223, /* U+1A800 */+224,225,226,227,227,228,146,146,146,146,146,146,146,146,146,146, /* U+1B000 */+146,146,146,146,146,146,146,146,229,230,146,146,146,146,146,146, /* U+1B800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+1C000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,231,232, /* U+1C800 */+233,234,235,236,237,238,239,146,240,241,242,243,244,245,246,247, /* U+1D000 */+248,248,248,248,249,250,146,146,146,146,146,146,146,146,251,146, /* U+1D800 */+252,253,254,146,146,255,146,146,146,256,146,146,146,146,146,257, /* U+1E000 */+258,259,260,168,168,168,168,168,261,262,263,168,264,265,168,168, /* U+1E800 */+266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281, /* U+1F000 */+282,283,284,285,286,287,288,289,271,271,271,271,271,271,271,290, /* U+1F800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+20000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+20800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+21000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+21800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+22000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+22800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+23000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+23800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+24000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+24800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+25000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+25800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+26000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+26800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+27000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+27800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+28000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+28800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+29000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+29800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,291,101,101, /* U+2A000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2A800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,292,101, /* U+2B000 */+293,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2B800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2C000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,294,101,101, /* U+2C800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2D000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2D800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2E000 */+101,101,101,101,101,101,101,295,146,146,146,146,146,146,146,146, /* U+2E800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+2F000 */+129,129,129,129,296,146,146,146,146,146,146,146,146,146,146,297, /* U+2F800 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+30000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+30800 */+101,101,101,101,101,101,298,101,101,101,101,101,101,101,101,101, /* U+31000 */+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+31800 */+101,101,101,101,101,101,101,299,146,146,146,146,146,146,146,146, /* U+32000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+32800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+33000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+33800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+34000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+34800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+35000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+35800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+36000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+36800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+37000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+37800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+38000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+38800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+39000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+39800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3A000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3A800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3B000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3B800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3C000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3C800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3D000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3D800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3E000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3E800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3F000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+3F800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+40000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+40800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+41000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+41800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+42000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+42800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+43000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+43800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+44000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+44800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+45000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+45800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+46000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+46800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+47000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+47800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+48000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+48800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+49000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+49800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4A000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4A800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4B000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4B800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4C000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4C800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4D000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4D800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4E000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4E800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4F000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+4F800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+50000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+50800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+51000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+51800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+52000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+52800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+53000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+53800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+54000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+54800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+55000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+55800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+56000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+56800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+57000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+57800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+58000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+58800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+59000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+59800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5A000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5A800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5B000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5B800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5C000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5C800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5D000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5D800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5E000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5E800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5F000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+5F800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+60000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+60800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+61000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+61800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+62000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+62800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+63000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+63800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+64000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+64800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+65000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+65800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+66000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+66800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+67000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+67800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+68000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+68800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+69000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+69800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6A000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6A800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6B000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6B800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6C000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6C800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6D000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6D800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6E000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6E800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6F000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+6F800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+70000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+70800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+71000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+71800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+72000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+72800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+73000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+73800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+74000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+74800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+75000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+75800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+76000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+76800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+77000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+77800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+78000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+78800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+79000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+79800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7A000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7A800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7B000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7B800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7C000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7C800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7D000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7D800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7E000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7E800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7F000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+7F800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+80000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+80800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+81000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+81800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+82000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+82800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+83000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+83800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+84000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+84800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+85000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+85800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+86000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+86800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+87000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+87800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+88000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+88800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+89000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+89800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8A000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8A800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8B000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8B800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8C000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8C800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8D000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8D800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8E000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8E800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8F000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+8F800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+90000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+90800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+91000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+91800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+92000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+92800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+93000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+93800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+94000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+94800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+95000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+95800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+96000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+96800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+97000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+97800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+98000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+98800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+99000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+99800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9A000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9A800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9B000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9B800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9C000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9C800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9D000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9D800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9E000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9E800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9F000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+9F800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A0000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A0800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A1000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A1800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A2000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A2800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A3000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A3800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A4000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A4800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A5000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A5800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A6000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A6800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A7000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A7800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A8000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A8800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A9000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A9800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AA000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AA800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AB000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AB800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AC000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AC800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AD000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AD800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AE000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AE800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AF000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+AF800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B0000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B0800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B1000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B1800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B2000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B2800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B3000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B3800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B4000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B4800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B5000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B5800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B6000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B6800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B7000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B7800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B8000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B8800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B9000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B9800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BA000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BA800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BB000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BB800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BC000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BC800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BD000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BD800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BE000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BE800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BF000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+BF800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C0000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C0800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C1000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C1800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C2000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C2800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C3000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C3800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C4000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C4800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C5000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C5800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C6000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C6800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C7000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C7800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C8000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C8800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C9000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C9800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CA000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CA800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CB000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CB800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CC000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CC800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CD000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CD800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CE000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CE800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CF000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+CF800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D0000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D0800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D1000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D1800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D2000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D2800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D3000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D3800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D4000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D4800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D5000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D5800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D6000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D6800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D7000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D7800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D8000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D8800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D9000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D9800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DA000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DA800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DB000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DB800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DC000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DC800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DD000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DD800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DE000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DE800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DF000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+DF800 */+300,301,302,303,301,301,301,301,301,301,301,301,301,301,301,301, /* U+E0000 */+301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301, /* U+E0800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E1000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E1800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E2000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E2800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E3000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E3800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E4000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E4800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E5000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E5800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E6000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E6800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E7000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E7800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E8000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E8800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E9000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E9800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EA000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EA800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EB000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EB800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EC000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EC800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+ED000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+ED800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EE000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EE800 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EF000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+EF800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F0000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F0800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F1000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F1800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F2000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F2800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F3000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F3800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F4000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F4800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F5000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F5800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F6000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F6800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F7000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F7800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F8000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F8800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F9000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F9800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FA000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FA800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FB000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FB800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FC000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FC800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FD000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FD800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FE000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FE800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FF000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,304, /* U+FF800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+100000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+100800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+101000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+101800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+102000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+102800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+103000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+103800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+104000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+104800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+105000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+105800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+106000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+106800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+107000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+107800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+108000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+108800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+109000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+109800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10A000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10A800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10B000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10B800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10C000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10C800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10D000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10D800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10E000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10E800 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10F000 */+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,304, /* U+10F800 */+};++const uint16_t PRIV(ucd_stage2)[] = { /* 78080 bytes, block = 128 */++/* block 0 */+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 3, 4, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 6,+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 25, 26, 27, 26, 8,+ 13, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 30, 29, 29, 29, 29,+ 29, 29, 29, 31, 29, 29, 29, 29, 29, 29, 29, 15, 13, 16, 32, 33,+ 34, 35, 35, 35, 35, 35, 35, 36, 36, 37, 37, 38, 36, 36, 36, 36,+ 36, 36, 36, 39, 36, 36, 36, 36, 36, 36, 36, 15, 27, 16, 27, 0,++/* block 1 */+ 40, 40, 40, 40, 40, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,+ 42, 43, 44, 44, 44, 44, 45, 43, 46, 47, 48, 49, 50, 51, 47, 46,+ 52, 53, 54, 54, 46, 55, 43, 56, 46, 54, 48, 57, 58, 58, 58, 43,+ 59, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,+ 59, 59, 59, 59, 59, 59, 59, 50, 59, 59, 59, 59, 59, 59, 59, 61,+ 62, 62, 62, 62, 62, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,+ 62, 62, 62, 62, 62, 62, 62, 50, 62, 62, 62, 62, 62, 62, 62, 64,++/* block 2 */+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67,+ 68, 69, 65, 66, 65, 66, 65, 66, 70, 65, 66, 65, 66, 65, 66, 65,+ 66, 65, 66, 65, 66, 65, 66, 65, 66, 71, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 72, 65, 66, 65, 66, 65, 66, 73,++/* block 3 */+ 74, 75, 65, 66, 65, 66, 76, 65, 66, 77, 77, 65, 66, 70, 78, 79,+ 80, 65, 66, 77, 81, 82, 83, 84, 65, 66, 85, 70, 83, 86, 87, 88,+ 65, 66, 65, 66, 65, 66, 89, 65, 66, 89, 70, 70, 65, 66, 89, 65,+ 66, 90, 90, 65, 66, 65, 66, 91, 65, 66, 70, 92, 65, 66, 70, 93,+ 92, 92, 92, 92, 94, 95, 96, 97, 98, 99,100,101,102, 65, 66, 65,+ 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,103, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 69,104,105,106, 65, 66,107,108, 65, 66, 65, 66, 65, 66, 65, 66,++/* block 4 */+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+109, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 70, 70, 70, 70, 70, 70,110, 65, 66,111,112,113,+113, 65, 66,114,115,116, 65, 66, 65, 67, 65, 66, 65, 66, 65, 66,+117,118,119,120,121, 70,122,122, 70,123, 70,124,125, 70, 70, 70,+122,126, 70,127, 70,128,129, 70,130,131,129,132,133, 70, 70,131,+ 70,134,135, 70, 70,136, 70, 70, 70, 70, 70, 70, 70,137, 70, 70,++/* block 5 */+138, 70,139,138, 70, 70, 70,140,138,141,142,142,143, 70, 70, 70,+ 70, 70,144, 70, 92, 70, 70, 70, 70, 70, 70, 70, 70,145,146, 70,+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,+147,147,148,147,147,147,147,147,147,149,149,150,150,150,150,150,+151,151, 46, 46, 46, 46,149,149,149,149,149,149,149,149,149,149,+152,152, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,+147,147,147,147,147, 46, 46, 46, 46, 46,153,153,149, 46,150, 46,+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,++/* block 6 */+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,+154,154,155,154,154,156,154,154,154,154,154,154,154,154,154,157,+154,154,154,154,154,154,154,154,158,158,158,158,158,154,154,154,+154,154,154,159,159,159,159,159,159,159,159,159,159,159,159,159,+160,161,160,161,149,162,160,161,163,163,164,165,165,165,166,167,++/* block 7 */+163,163,163,163,162, 46,168,169,170,170,170,163,171,163,172,172,+173,174,175,174,174,176,174,174,177,178,179,174,180,174,174,174,+181,182,163,183,174,174,184,174,174,185,174,174,186,187,187,187,+173,188,189,188,188,190,188,188,191,192,193,188,194,188,188,188,+195,196,197,198,188,188,199,188,188,200,188,188,201,202,202,203,+204,205,206,207,207,208,209,210,160,161,160,161,160,161,160,161,+160,161,211,212,211,212,211,212,211,212,211,212,211,212,211,212,+213,214,215,216,217,218,219,160,161,220,160,161,221,222,222,222,++/* block 8 */+223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,+224,224,225,224,226,224,224,224,224,224,224,224,224,224,227,224,+224,228,229,224,224,224,224,224,224,224,230,224,224,224,224,224,+231,231,232,231,233,231,231,231,231,231,231,231,231,231,234,231,+231,235,236,231,231,231,231,231,231,231,237,231,231,231,231,231,+238,238,238,238,238,238,239,238,239,238,238,238,238,238,238,238,+240,241,242,243,240,241,240,241,240,241,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,++/* block 9 */+240,241,244,245,246,247,247,246,248,248,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+249,240,241,240,241,240,241,240,241,240,241,240,241,240,241,250,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,++/* block 10 */+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+163,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,+251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,+251,251,251,251,251,251,251,163,163,252,253,253,253,253,253,254,+255,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,+256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,++/* block 11 */+256,256,256,256,256,256,256,257,255,258,259,163,163,260,260,261,+262,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,+263,263,264,263,263,263,263,263,263,263,263,263,263,263,263,263,+265,265,265,265,265,265,265,265,265,265,265,265,265,265,266,265,+267,265,265,268,265,269,267,269,262,262,262,262,262,262,262,262,+270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,+270,270,270,270,270,270,270,270,270,270,270,262,262,262,262,270,+270,270,270,267,271,262,262,262,262,262,262,262,262,262,262,262,++/* block 12 */+272,272,272,272,272,273,274,274,275,276,276,277,278,279,280,280,+281,281,281,281,281,281,281,281,281,281,281,282,283,284,284,285,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+287,286,286,286,286,286,286,286,286,286,286,288,288,288,288,288,+288,288,288,289,289,289,281,290,291,281,281,281,281,281,281,281,+292,292,292,292,292,292,292,292,292,292,276,293,293,279,286,286,+289,286,286,294,286,286,286,286,286,286,286,286,286,286,286,286,++/* block 13 */+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,295,286,281,281,281,281,281,281,281,273,280,291,+291,281,281,281,281,296,296,281,281,280,291,291,291,281,286,286,+297,297,297,297,297,297,297,297,297,297,286,286,286,298,298,286,++/* block 14 */+299,299,299,300,300,300,300,300,300,300,300,301,300,301,302,303,+304,305,304,304,304,304,304,304,304,304,304,304,304,304,304,304,+304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,+306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,+307,307,307,307,307,307,307,307,307,307,307,302,302,304,304,304,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,++/* block 15 */+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,+308,308,308,308,308,308,309,309,309,309,309,309,309,309,309,309,+309,308,302,302,302,302,302,302,302,302,302,302,302,302,302,302,+310,310,310,310,310,310,310,310,310,310,311,311,311,311,311,311,+311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,+311,311,311,311,311,311,311,311,311,311,311,312,312,312,312,312,+312,312,312,312,313,313,314,315,316,317,318,262,262,319,320,320,++/* block 16 */+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,322,322,323,323,324,322,322,322,322,322,+322,322,322,322,324,322,322,322,324,322,322,322,322,325,262,262,+326,326,326,326,326,326,326,327,326,327,326,326,326,327,327,262,+328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,+328,328,328,328,328,328,328,328,328,329,329,329,262,262,330,262,+304,304,304,304,304,304,304,304,304,304,304,302,302,302,302,302,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,++/* block 17 */+286,286,286,286,286,286,286,286,331,286,286,286,286,286,286,302,+272,272,302,302,302,302,302,302,291,291,291,291,291,291,291,291,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,296,291,291,291,291,291,291,+291,291,291,332,281,281,281,281,281,281,281,281,281,281,281,281,+332,332,273,290,290,290,290,290,290,290,291,291,291,291,291,291,+290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,281,++/* block 18 */+333,333,333,334,335,335,335,335,335,335,335,335,335,335,335,335,+335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,+335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,+335,335,335,335,335,335,335,335,335,335,333,334,336,335,334,334,+334,333,333,333,333,333,333,333,333,334,334,334,334,337,334,334,+335,338,339,154,154,333,333,333,335,335,335,335,335,335,335,335,+335,335,333,333,340,341,342,342,342,342,342,342,342,342,342,342,+343,344,335,335,335,335,335,335,335,335,335,335,335,335,335,335,++/* block 19 */+345,346,347,347,163,345,345,345,345,345,345,345,345,163,163,345,+345,163,163,345,345,345,345,345,345,345,345,345,345,345,345,345,+345,345,345,345,345,345,345,345,345,163,345,345,345,345,345,345,+345,163,345,163,163,163,345,345,345,345,163,163,348,345,349,347,+347,346,346,346,346,163,163,347,347,163,163,347,347,350,345,163,+163,163,163,163,163,163,163,349,163,163,163,163,345,345,163,345,+345,345,346,346,163,163,351,351,351,351,351,351,351,351,351,351,+345,345,352,352,353,353,353,353,353,353,354,352,345,355,356,163,++/* block 20 */+163,357,357,358,163,359,359,359,359,359,359,163,163,163,163,359,+359,163,163,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,163,359,359,359,359,359,359,+359,163,359,359,163,359,359,163,359,359,163,163,360,163,358,358,+358,357,357,163,163,163,163,357,357,163,163,357,357,361,163,163,+163,357,163,163,163,163,163,163,163,359,359,359,359,163,359,163,+163,163,163,163,163,163,362,362,362,362,362,362,362,362,362,362,+357,357,359,359,359,357,363,163,163,163,163,163,163,163,163,163,++/* block 21 */+163,364,364,365,163,366,366,366,366,366,366,366,366,366,163,366,+366,366,163,366,366,366,366,366,366,366,366,366,366,366,366,366,+366,366,366,366,366,366,366,366,366,163,366,366,366,366,366,366,+366,163,366,366,163,366,366,366,366,366,163,163,367,366,365,365,+365,364,364,364,364,364,163,364,364,365,163,365,365,368,163,163,+366,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+366,366,364,364,163,163,369,369,369,369,369,369,369,369,369,369,+370,371,163,163,163,163,163,163,163,366,364,364,364,367,367,367,++/* block 22 */+163,372,373,373,163,374,374,374,374,374,374,374,374,163,163,374,+374,163,163,374,374,374,374,374,374,374,374,374,374,374,374,374,+374,374,374,374,374,374,374,374,374,163,374,374,374,374,374,374,+374,163,374,374,163,374,374,374,374,374,163,163,375,374,376,372,+373,372,372,372,372,163,163,373,373,163,163,373,373,377,163,163,+163,163,163,163,163,378,372,376,163,163,163,163,374,374,163,374,+374,374,372,372,163,163,379,379,379,379,379,379,379,379,379,379,+380,374,381,381,381,381,381,381,163,163,163,163,163,163,163,163,++/* block 23 */+163,163,382,383,163,383,383,383,383,383,383,163,163,163,383,383,+383,163,383,383,383,383,163,163,163,383,383,163,383,163,383,383,+163,163,163,383,383,163,163,163,383,383,383,163,163,163,383,383,+383,383,383,383,383,383,383,383,383,383,163,163,163,163,384,385,+382,385,385,163,163,163,385,385,385,163,385,385,385,386,163,163,+383,163,163,163,163,163,163,384,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,387,387,387,387,387,387,387,387,387,387,+388,388,388,389,390,390,390,390,390,391,390,163,163,163,163,163,++/* block 24 */+392,393,393,393,392,394,394,394,394,394,394,394,394,163,394,394,+394,163,394,394,394,394,394,394,394,394,394,394,394,394,394,394,+394,394,394,394,394,394,394,394,394,163,394,394,394,394,394,394,+394,394,394,394,394,394,394,394,394,394,163,163,395,394,392,392,+392,393,393,393,393,163,392,392,392,163,392,392,392,396,163,163,+163,163,163,163,163,392,392,163,394,394,394,163,163,394,163,163,+394,394,392,392,163,163,397,397,397,397,397,397,397,397,397,397,+163,163,163,163,163,163,163,398,399,399,399,399,399,399,399,400,++/* block 25 */+401,402,403,403,404,401,401,401,401,401,401,401,401,163,401,401,+401,163,401,401,401,401,401,401,401,401,401,401,401,401,401,401,+401,401,401,401,401,401,401,401,401,163,401,401,401,401,401,401,+401,401,401,401,163,401,401,401,401,401,163,163,405,401,403,406,+403,403,407,403,403,163,406,403,403,163,403,403,402,408,163,163,+163,163,163,163,163,407,407,163,163,163,163,163,163,401,401,163,+401,401,402,402,163,163,409,409,409,409,409,409,409,409,409,409,+163,401,401,403,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 26 */+410,410,411,411,412,412,412,412,412,412,412,412,412,163,412,412,+412,163,412,412,412,412,412,412,412,412,412,412,412,412,412,412,+412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,+412,412,412,412,412,412,412,412,412,412,412,413,413,412,414,411,+411,410,410,410,410,163,411,411,411,163,411,411,411,413,415,416,+163,163,163,163,412,412,412,414,417,417,417,417,417,417,417,412,+412,412,410,410,163,163,418,418,418,418,418,418,418,418,418,418,+417,417,417,417,417,417,417,417,417,416,412,412,412,412,412,412,++/* block 27 */+163,419,420,420,163,421,421,421,421,421,421,421,421,421,421,421,+421,421,421,421,421,421,421,163,163,163,421,421,421,421,421,421,+421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,+421,421,163,421,421,421,421,421,421,421,421,421,163,421,163,163,+421,421,421,421,421,421,421,163,163,163,422,163,163,163,163,423,+420,420,419,419,419,163,419,163,420,420,420,420,420,420,420,423,+163,163,163,163,163,163,424,424,424,424,424,424,424,424,424,424,+163,163,420,420,425,163,163,163,163,163,163,163,163,163,163,163,++/* block 28 */+163,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,+426,427,426,428,427,427,427,427,427,427,429,163,163,163,163,430,+431,431,431,431,431,426,432,433,433,433,433,433,433,427,433,434,+435,435,435,435,435,435,435,435,435,435,436,436,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 29 */+163,437,437,163,437,163,437,437,437,437,437,163,437,437,437,437,+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,+437,437,437,437,163,437,163,437,437,437,437,437,437,437,437,437,+437,438,437,439,438,438,438,438,438,438,440,438,438,437,163,163,+441,441,441,441,441,163,442,163,443,443,443,443,443,438,444,163,+445,445,445,445,445,445,445,445,445,445,163,163,437,437,437,437,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 30 */+446,447,447,447,448,448,448,448,449,448,448,448,448,449,449,449,+449,449,449,447,448,447,447,447,450,450,447,447,447,447,447,447,+451,451,451,451,451,451,451,451,451,451,452,452,452,452,452,452,+452,452,452,452,447,450,447,450,447,450,453,454,453,454,455,455,+446,446,446,446,446,446,446,446,163,446,446,446,446,446,446,446,+446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,+446,446,446,446,446,446,446,446,446,446,446,446,446,163,163,163,+163,456,456,456,456,456,456,457,456,457,456,456,456,456,456,458,++/* block 31 */+456,456,459,459,460,448,450,450,446,446,446,446,446,456,456,456,+456,456,456,456,456,456,456,456,163,456,456,456,456,456,456,456,+456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,+456,456,456,456,456,456,456,456,456,456,456,456,456,163,447,447,+447,447,447,447,447,447,450,447,447,447,447,447,447,163,447,447,+448,448,448,448,448,461,461,461,461,448,448,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 32 */+462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,+462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,+462,462,462,462,462,462,462,462,462,462,462,463,463,464,464,464,+464,465,464,464,464,464,464,466,463,467,467,465,465,464,464,462,+468,468,468,468,468,468,468,468,468,468,469,469,470,470,470,470,+462,462,462,462,462,462,465,465,464,464,462,462,462,462,464,464,+464,462,463,471,471,462,462,463,463,471,471,471,471,471,462,462,+462,464,464,464,464,462,462,462,462,462,462,462,462,462,462,462,++/* block 33 */+462,462,464,463,465,464,464,471,471,471,471,471,471,472,462,471,+473,473,473,473,473,473,473,473,473,473,471,471,463,464,474,474,+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,+475,475,475,475,475,475,163,475,163,163,163,163,163,475,163,163,+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,+476,476,476,476,476,476,476,476,476,476,476,477,478,476,476,476,++/* block 34 */+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,480,+481,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,++/* block 35 */+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,+482,482,482,482,482,482,482,482,483,483,483,483,483,483,483,483,+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,++/* block 36 */+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,163,484,484,484,484,163,163,+484,484,484,484,484,484,484,163,484,163,484,484,484,484,163,163,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,++/* block 37 */+484,484,484,484,484,484,484,484,484,163,484,484,484,484,163,163,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,163,484,484,484,484,163,163,484,484,484,484,484,484,484,163,+484,163,484,484,484,484,163,163,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,++/* block 38 */+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,163,484,484,484,484,163,163,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,484,484,484,484,163,163,485,485,485,+486,487,488,487,487,487,487,488,488,489,489,489,489,489,489,489,+489,489,490,490,490,490,490,490,490,490,490,490,490,163,163,163,++/* block 39 */+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+491,491,491,491,491,491,491,491,491,491,163,163,163,163,163,163,+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,+493,493,493,493,493,493,163,163,494,494,494,494,494,494,163,163,++/* block 40 */+495,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,++/* block 41 */+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,++/* block 42 */+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,497,498,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,++/* block 43 */+499,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,+500,500,500,500,500,500,500,500,500,500,500,501,502,163,163,163,+503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,+503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,+503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,+503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,+503,503,503,503,503,503,503,503,503,503,503,504,504,504,505,505,+505,503,503,503,503,503,503,503,503,163,163,163,163,163,163,163,++/* block 44 */+506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,+506,506,507,507,508,509,163,163,163,163,163,163,163,163,163,506,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,511,511,512,513,513,163,163,163,163,163,163,163,163,163,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,515,515,163,163,163,163,163,163,163,163,163,163,163,163,+516,516,516,516,516,516,516,516,516,516,516,516,516,163,516,516,+516,163,517,517,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 45 */+518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,+518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,+518,518,518,519,519,518,518,518,518,518,518,518,518,518,518,518,+518,518,518,518,520,520,521,522,522,522,522,522,522,522,521,521,+521,521,521,521,521,521,522,521,521,523,523,523,523,523,523,523,+523,523,524,523,525,525,525,526,527,527,525,528,518,523,163,163,+529,529,529,529,529,529,529,529,529,529,163,163,163,163,163,163,+530,530,530,530,530,530,530,530,530,530,163,163,163,163,163,163,++/* block 46 */+531,531,532,533,534,532,535,531,534,536,537,538,538,538,539,538,+540,540,540,540,540,540,540,540,540,540,163,163,163,163,163,163,+541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,+541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,+541,541,541,542,541,541,541,541,541,541,541,541,541,541,541,541,+541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,+541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,+541,541,541,541,541,541,541,541,541,163,163,163,163,163,163,163,++/* block 47 */+541,541,541,541,541,543,543,541,541,541,541,541,541,541,541,541,+541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,+541,541,541,541,541,541,541,541,541,544,541,163,163,163,163,163,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+496,496,496,496,496,496,163,163,163,163,163,163,163,163,163,163,++/* block 48 */+545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,+545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,163,+546,546,546,547,547,547,547,546,546,547,547,547,163,163,163,163,+547,547,546,547,547,547,547,547,547,548,548,548,163,163,163,163,+549,163,163,163,550,550,551,551,551,551,551,551,551,551,551,551,+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,+552,552,552,552,552,552,552,552,552,552,552,552,552,552,163,163,+552,552,552,552,552,163,163,163,163,163,163,163,163,163,163,163,++/* block 49 */+553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,+553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,+553,553,553,553,553,553,553,553,553,553,553,553,163,163,163,163,+553,553,553,553,553,554,554,554,553,553,554,553,553,553,553,553,+553,553,553,553,553,553,553,553,553,553,163,163,163,163,163,163,+555,555,555,555,555,555,555,555,555,555,556,163,163,163,557,557,+558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,+558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,++/* block 50 */+559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,+559,559,559,559,559,559,559,560,560,561,561,560,163,163,562,562,+563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,+563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,+563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,+563,563,563,563,563,564,565,564,565,565,565,565,565,565,565,163,+566,567,565,567,567,565,565,565,565,565,565,565,565,564,564,564,+564,564,564,565,565,568,568,568,568,568,568,568,568,163,163,568,++/* block 51 */+569,569,569,569,569,569,569,569,569,569,163,163,163,163,163,163,+569,569,569,569,569,569,569,569,569,569,163,163,163,163,163,163,+570,570,570,570,570,570,570,571,572,572,572,572,570,570,163,163,+154,154,154,154,154,154,154,154,154,154,154,154,154,154,573,574,+574,154,154,154,154,154,154,154,154,154,154,154,574,574,574,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 52 */+575,575,575,575,576,577,577,577,577,577,577,577,577,577,577,577,+577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,+577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,+577,577,577,577,578,579,575,575,575,575,575,576,575,576,576,576,+576,576,575,576,580,577,577,577,577,577,577,577,577,163,163,163,+581,581,581,581,581,581,581,581,581,581,582,582,583,584,582,582,+583,585,585,585,585,585,585,585,585,585,585,578,578,578,578,578,+578,578,578,578,585,585,585,585,585,585,585,585,585,582,582,163,++/* block 53 */+586,586,587,588,588,588,588,588,588,588,588,588,588,588,588,588,+588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,+588,587,586,586,586,586,587,587,586,586,589,590,586,586,588,588,+591,591,591,591,591,591,591,591,591,591,588,588,588,588,588,588,+592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,+592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,+592,592,592,592,592,592,593,594,595,595,594,594,594,595,594,595,+595,595,596,596,163,163,163,163,163,163,163,163,597,597,597,597,++/* block 54 */+598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,+598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,+598,598,598,598,599,599,599,599,599,599,599,599,600,600,600,600,+600,600,600,600,599,599,601,602,163,163,163,603,603,604,604,604,+605,605,605,605,605,605,605,605,605,605,163,163,163,598,598,598,+606,606,606,606,606,606,606,606,606,606,607,607,607,607,607,607,+607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,+607,607,607,607,607,607,607,607,608,608,608,609,608,608,610,610,++/* block 55 */+611,612,613,614,615,616,617,618,619,163,163,163,163,163,163,163,+620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,+620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,+620,620,620,620,620,620,620,620,620,620,620,163,163,620,620,620,+621,621,621,621,621,621,621,621,163,163,163,163,163,163,163,163,+622,623,622,624,623,625,625,626,625,626,627,623,626,626,623,623,+626,628,623,623,623,623,623,623,623,629,630,631,631,625,631,631,+631,631,632,633,634,630,630,635,636,636,637,163,163,163,163,163,++/* block 56 */+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,+ 70, 70, 70, 70, 70, 70,221,221,221,221,221,638,147,147,147,147,+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,+147,147,147,147,147,147,147,147,147,147,147,147,147,639,639,639,+639,639,148,147,147,147,639,639,639,639,639, 70, 70, 70, 70, 70,+ 70, 70, 70, 70, 70, 70, 70, 70,640,641, 70, 70, 70,642, 70, 70,++/* block 57 */+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,643, 70,+ 70, 70, 70, 70, 70, 70,644, 70, 70, 70, 70,645,645,645,645,645,+645,645,645,645,646,645,645,645,646,645,645,645,645,645,645,645,+645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,647,+648,648,158,158,154,154,154,154,154,154,154,154,154,154,154,154,+158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,+158,158,158,158,158,158,158,574,574,574,574,574,574,574,574,574,+574,574,574,574,574,154,154,154,649,154,650,154,154,154,154,154,++/* block 58 */+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+651,652, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,++/* block 59 */+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 69, 69, 69, 69,653,654, 70, 70,655, 70,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,++/* block 60 */+656,656,656,656,656,656,656,656,657,657,657,657,657,657,657,657,+656,656,656,656,656,656,163,163,657,657,657,657,657,657,163,163,+656,656,656,656,656,656,656,656,657,657,657,657,657,657,657,657,+656,656,656,656,656,656,656,656,657,657,657,657,657,657,657,657,+656,656,656,656,656,656,163,163,657,657,657,657,657,657,163,163,+173,656,173,656,173,656,173,656,163,657,163,657,163,657,163,657,+656,656,656,656,656,656,656,656,657,657,657,657,657,657,657,657,+658,658,659,659,659,659,660,660,661,661,662,662,663,663,163,163,++/* block 61 */+664,664,664,664,664,664,664,664,665,665,665,665,665,665,665,665,+664,664,664,664,664,664,664,664,665,665,665,665,665,665,665,665,+664,664,664,664,664,664,664,664,665,665,665,665,665,665,665,665,+656,656,666,667,666,163,173,666,657,657,668,668,669,162,670,162,+162,162,666,667,666,163,173,666,671,671,671,671,669,162,162,162,+656,656,173,173,163,163,173,173,657,657,672,672,163,162,162,162,+656,656,173,173,173,215,173,173,657,657,673,673,220,162,162,162,+163,163,666,667,666,163,173,666,674,674,675,675,669,162,162,163,++/* block 62 */+676,676,676,676,676,676,676,676,676,676,676, 51,677,678,679,680,+681,681,681,681,681,681,682, 43,683,684,685,686,686,687,685,686,+ 43, 43, 43, 43,688, 43, 43,688,689,690,691,692,693,694,695,696,+697,697,698,698,698, 43, 43, 43, 43, 49, 57, 43,699,700, 43,701,+702, 43, 43, 43,703,704,705,700,700,699, 43, 43, 43, 43, 43, 43,+ 43, 43, 50,706,701, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,676,+ 51,707,707,707,707,708,709,710,711,712,713,713,713,713,713,713,+ 54,646,163,163, 54, 54, 54, 54, 54, 54,714,715,716,717,718,645,++/* block 63 */+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,714,715,716,717,718,163,+645,645,645,645,645,645,645,645,645,645,645,645,645,163,163,163,+430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,+430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,+430,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,+720,720,720,720,720,720,720,720,720,720,720,720,720,721,721,721,+721,720,721,722,721,720,720,158,158,158,158,720,720,720,720,720,+723,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 64 */+724,724,725,724,724,724,724,725,724,724,726,725,725,725,726,726,+725,725,725,726,724,725,724,724,727,725,725,725,725,725,724,724,+724,724,728,724,725,724,729,724,725,730,731,732,725,725,733,726,+725,725,734,725,726,735,735,735,735,736,724,724,726,726,725,725,+716,716,716,716,716,725,726,726,737,737,724,716,724,724,738,461,+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,+740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,++/* block 65 */+741,741,741, 65, 66,741,741,741,741, 58,724,724,163,163,163,163,+ 50, 50, 50, 50,742,743,743,743,743,743, 50, 50,744,744,744,744,+ 50,744,744, 50,744,744, 50,744, 45,743,743,744,744,744, 50, 45,+744,744, 45, 45, 45, 45,744,744, 45, 45, 45, 45,744,744,744,744,+744,744,744,744,744,744,744,744,744,744,744,744,744,744, 50, 50,+744,744, 50,744, 50,744,744,744,744,744,744,744, 45,744, 45, 45,+ 45, 45, 45, 45,744,744, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,++/* block 66 */+ 50, 50, 50, 50, 50, 50, 50, 50,745,745,745,745,745,745, 50, 50,+ 50, 50,746, 53, 50,745, 50, 50, 50, 50, 50, 50, 50, 50, 50,745,+745,745,745, 50,745, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,745,745, 50, 50,+ 50, 50, 50,745, 50,745, 50, 50, 50, 50, 50, 50,745, 50, 50, 50,+ 50, 50,745,745,745,745, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50,745,745,745,745,745,745,745,745, 50, 50,745,745,+745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,++/* block 67 */+745,745,745,745,745,745,745,745,745,745,745,745, 50, 50, 50,745,+745,745,745, 50, 50, 50, 50, 50,745, 50, 50, 50, 50, 50, 50, 50,+ 50, 50,745,745, 50, 50,745, 50,745,745, 50,745, 50, 50, 50, 50,+745,745,745,745,745,745,745,745,745, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50,745,745,745,745,745, 50, 50,+745,745, 50, 50, 50, 50,745,745,745,745,745,745,745,745,745,745,+745,745,745,745,745,745,745,745,745,745,745,745,745,745, 50, 50,+745,745,745,745,745, 50,745,745, 50, 50,745,745,745,745,745, 50,++/* block 68 */+ 45, 45, 45, 45, 45, 45, 45, 45,747,748,747,748, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,749,749, 45, 45, 45, 45,+ 50, 50, 45, 45, 45, 45, 45, 45, 47,750,751, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45,752,752,752,752,752,752,752,752,752,752,+752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,+752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,+752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,+752,752,752,752,752,752,752,752,752,752,752, 45, 50, 45, 45, 45,++/* block 69 */+ 45, 45, 45, 45, 45, 45, 45, 45,753, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45,752, 45, 45, 45, 45, 45, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50,744,744, 45,744, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 47,+744, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50, 50,+ 50, 50,744, 45, 45, 45, 45, 45, 45,749,749,749,749, 47, 47, 47,+749, 47, 47,749, 45, 45, 45, 45, 47, 47, 47, 45, 45, 45, 45, 45,++/* block 70 */+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45,754,754,754,754,754,754,754,754,754,+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,754,754,754,754,754,+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,++/* block 71 */+ 58, 58, 58, 58, 58, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54,+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,755,755,755,755,755,755,755,755,755,755,+755,755,756,755,755,755,755,755,755,755,755,755,755,755,755,755,+757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,+757,757,757,757,757,757,757,757,757,757, 58, 58, 58, 58, 58, 58,+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,++/* block 72 */+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,++/* block 73 */+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+744,744, 45, 45, 45, 45, 45, 45, 45, 45, 47, 47, 45, 45,744,744,+744,744,744,744,744,744,743, 50, 45, 45, 45, 45,744,744,744,744,+743, 50, 45, 45, 45, 45,744,744, 45, 45,744,744, 45, 45, 45,744,+744,744,744,744, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45,744, 45,744, 45, 45,744,744,744,744,744,744, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50,742,742,758,758, 50,++/* block 74 */+ 47, 47, 47, 47, 47,759,744,753,753,753,753,753,753,753, 47,753,+753, 47,753, 45,749,749,753,753, 47,753,753,753,753,760,753,753,+ 47,753, 47, 47,753,753, 47,753,753,753, 47,753,753,753, 47, 47,+753,753,753,753,753,753,753,753, 47, 47, 47,753,753,753,753,753,+743,753,743,753,753,753,753,753,749,749,749,749,749,749,749,749,+749,749,749,749,753,753,753,753,753,753,753,753,753,753,753, 47,+743,759,759,743,753, 47, 47,753, 47,753,753,753,753,759,759,761,+753,753,753,753,753,753,753,753,753,753,753, 47,753,753, 47,749,++/* block 75 */+753,753,753,753,753,753, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+753,753, 47,749, 47, 47, 47, 47,753, 47,753, 47, 47,753,753,753,+ 47,749,753,753,753,753,753, 47,753,753,749,749,762,753,753,753,+ 47, 47,753,753,753,753,753,753,753,753,753,753,753,749,749,753,+753,753,753,753,749,749,753,753, 47,753,753,753,753,753,749, 47,+753, 47,753, 47,749,753,753,753,753,753,753,753,753,753,753,753,+753,753,753,753,753,753,753,753,753, 47,749,753,753,753,753,753,+ 47, 47,749,749, 47,749,753, 47, 47,760,749,753,753,749,753,753,++/* block 76 */+753,753, 47,753,753,749, 45, 45, 47, 47,763,763,760,760,753, 47,+753,753, 47, 45, 47, 45, 47, 45, 45, 45, 45, 45, 45, 47, 45, 45,+ 45, 47, 45, 45, 45, 45, 45, 45,749, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 47, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 47, 45, 45, 47, 45, 45, 45, 45,749, 45,749, 45,+ 45, 45, 45,749,749,749, 45,749, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 47, 47,753,753,753,704,705,704,705,704,705,704,705,+704,705,704,705,704,705, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,++/* block 77 */+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,+ 58, 58, 58, 58, 45,749,749,749, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+749, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,749,+ 50, 50, 50,745,745,747,748, 50,745,745, 50,745, 50,745, 50, 50,+ 50, 50, 50, 50, 50,745,745, 50, 50, 50, 50, 50,745,745,745, 50,+ 50, 50,745,745,745,745,747,748,747,748,747,748,747,748,747,748,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,++/* block 78 */+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,++/* block 79 */+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50,742,742, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,++/* block 80 */+ 50, 50, 50,747,748,747,748,747,748,747,748,747,748,747,748,747,+748,747,748,747,748,747,748,747,748, 50, 50,745, 50, 50, 50, 50,+745, 50, 50,745,745,745, 50, 50,745,745,745,745,745,745,745,745,+ 50, 50, 50, 50, 50, 50, 50, 50,745, 50, 50, 50, 50, 50, 50, 50,+745,745, 50, 50,745,745, 50, 50, 50, 50, 50, 50, 50, 50, 50,745,+745,745,745, 50,745,745, 50, 50,747,748,747,748, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50,745,745, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50,745, 50, 50,745,745, 50, 50,747,748, 50, 50,++/* block 81 */+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,745,745,745,745, 50,+ 50, 50, 50, 50,745,745, 50, 50, 50, 50, 50, 50,745,745, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50,745,745, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50,745,745,745,745,745,745,745,++/* block 82 */+745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,+745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,+745,745,745, 50, 50, 50,745,745,745,745,745,745,745,745, 50,745,+745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,+745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,+745,745,745,745,745,745,745, 50, 50, 50, 50, 50, 50, 50,745, 50,+ 50, 50, 50,745,745,745, 50, 50, 50, 50, 50, 50,745,745,745, 50,+ 50, 50, 50, 50, 50, 50, 50,745,745,745,745, 50, 50, 50, 50, 50,++/* block 83 */+ 45, 45, 45, 45, 45, 47, 47, 47, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,749,749, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 45, 45, 50, 50, 50, 50, 50, 50, 45, 45, 45,+749, 45, 45, 45, 45,749, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45,754,754, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,++/* block 84 */+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45,754, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,765, 45,++/* block 85 */+766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,+766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,+766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,+767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,+767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,+767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,+ 65, 66,768,769,770,771,772, 65, 66, 65, 66, 65, 66,773,774,775,+776, 70, 65, 66, 70, 65, 66, 70, 70, 70, 70, 70,646,645,777,777,++/* block 86 */+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,+211,212,211,212,778,779,779,779,779,779,779,211,212,211,212,780,+780,780,211,212,163,163,163,163,163,781,781,781,781,782,781,781,++/* block 87 */+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,+783,783,783,783,783,783,163,783,163,163,163,163,163,783,163,163,+784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,+784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,+784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,+784,784,784,784,784,784,784,784,163,163,163,163,163,163,163,785,+786,163,163,163,163,163,163,163,163,163,163,163,163,163,163,787,++/* block 88 */+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,+484,484,484,484,484,484,484,163,163,163,163,163,163,163,163,163,+484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163,+484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163,+484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163,+484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163,+788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,+788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,++/* block 89 */+ 43, 43,789,790,789,790, 43, 43, 43,789,790, 43,789,790, 43, 43,+ 43, 43, 43, 43, 43, 43, 43,681, 43, 43,681, 43,789,790, 43, 43,+789,790,704,705,704,705,704,705,704,705, 43, 43, 43, 43,700,791,+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,681,681,700, 43, 43, 43,+681,792,685,793, 43, 43, 43, 43, 43, 43, 43, 43,792, 43,792,792,+ 45, 45, 43,700,700,704,705,704,705,704,705,704,705,681,754,754,+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,++/* block 90 */+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,163,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 91 */+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,++/* block 92 */+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,+794,794,794,794,794,794,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+795,795,796,796,795,795,795,795,795,795,795,795,163,163,163,163,++/* block 93 */+676,797,798,799,724,800,801,802,803,804,803,804,805,806,805,806,+803,804, 45,807,803,804,803,804,803,804,803,804,808,809,810,810,+ 45,802,802,802,802,802,802,802,802,802,811,811,811,811,812,812,+813,814,814,814,814,814,724,815,802,802,802,816,817,818,819,819,+163,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,++/* block 94 */+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,163,163,821,821,822,822,823,823,820,+824,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,+825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,+825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,+825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,+825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,+825,825,825,825,825,825,825,825,825,825,825,826,827,828,828,825,++/* block 95 */+163,163,163,163,163,829,829,829,829,829,829,829,829,829,829,829,+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,+163,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,+830,830,830,830,831,830,830,830,830,830,830,830,830,830,830,830,+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,++/* block 96 */+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,163,+832,832,833,833,833,833,832,832,832,832,832,832,832,832,832,832,+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,+819,819,819,819,163,163,163,163,163,163,163,163,163,163,163,163,+825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,++/* block 97 */+834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,+834,834,834,834,834,834,834,834,834,834,834,834,834,835,835,163,+833,833,833,833,833,833,833,833,833,833,832,832,832,832,832,832,+832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,+832,832,832,832,832,832,832,832,836,836,836,836,836,836,836,836,+724, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,+834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,+834,834,834,834,834,834,834,834,834,834,834,834,835,835,835,461,++/* block 98 */+833,833,833,833,833,833,833,833,833,833,832,832,832,832,832,832,+832,832,832,832,832,832,832,837,832,837,832,832,832,832,832,832,+832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,+832, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,+832,832,832,832,832,832,832,832,832,832,832,832,724,724,724,724,+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,832,++/* block 99 */+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,+838,838,838,838,838,838,838,838,832,832,832,832,832,832,832,832,+832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,+832,461,461,461,461,461,461,724,724,724,724,832,832,832,832,832,++/* block 100 */+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,724,724,+832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,+832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,724,++/* block 101 */+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,++/* block 102 */+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,++/* block 103 */+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,841,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,++/* block 104 */+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,++/* block 105 */+840,840,840,840,840,840,840,840,840,840,840,840,840,163,163,163,+842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,+842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,+842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,+842,842,842,842,842,842,842,163,163,163,163,163,163,163,163,163,+843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,+843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,+843,843,843,843,843,843,843,843,844,844,844,844,844,844,845,846,++/* block 106 */+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,++/* block 107 */+847,847,847,847,847,847,847,847,847,847,847,847,848,849,850,850,+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,+851,851,851,851,851,851,851,851,851,851,847,847,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+240,241,240,241,240,241,240,241,240,241,852,853,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,240,241,854,246,+248,248,248,855,788,788,788,788,788,788,788,788,856,856,855,857,++/* block 108 */+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,+240,241,240,241,240,241,240,241,240,241,240,241,858,858,788,788,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,860,860,860,860,860,860,860,860,860,860,+861,861,862,863,864,864,864,863,163,163,163,163,163,163,163,163,++/* block 109 */+865,865,865,865,865,865,865,865, 46, 46, 46, 46, 46, 46, 46, 46,+ 46, 46, 46, 46, 46, 46, 46,149,149,149,149,149,149,149,149,149,+ 46, 46, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 70, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+645, 70, 70, 70, 70, 70, 70, 70, 70, 65, 66, 65, 66,866, 65, 66,++/* block 110 */+ 65, 66, 65, 66, 65, 66, 65, 66,149,867,867, 65, 66,868, 70, 92,+ 65, 66, 65, 66,869, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,870,871,872,873,870, 70,+874,875,876,877, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66,878,879,880, 65, 66, 65, 66,163,163,163,163,163,+ 65, 66,163, 70,163, 70, 65, 66, 65, 66,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,645,645,645, 65, 66, 92,147,147, 70, 92, 92, 92, 92, 92,++/* block 111 */+881,881,882,881,881,881,883,881,881,881,881,882,881,881,881,881,+881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,+881,881,881,884,884,882,882,884,885,885,885,885,883,163,163,163,+886,886,886,887,887,887,888,888,889,890,163,163,163,163,163,163,+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,+891,891,891,891,892,892,893,893,163,163,163,163,163,163,163,163,++/* block 112 */+894,894,895,895,895,895,895,895,895,895,895,895,895,895,895,895,+895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,+895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,+895,895,895,895,894,894,894,894,894,894,894,894,894,894,894,894,+894,894,894,894,896,897,163,163,163,163,163,163,163,163,898,898,+899,899,899,899,899,899,899,899,899,899,163,163,163,163,163,163,+336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,+336,900,335,901,335,335,335,335,343,343,343,335,343,335,335,333,++/* block 113 */+902,902,902,902,902,902,902,902,902,902,903,903,903,903,903,903,+903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,+903,903,903,903,903,903,904,904,904,904,904,905,905,905,906,907,+908,908,908,908,908,908,908,908,908,908,908,908,908,908,908,908,+908,908,908,908,908,908,908,909,909,909,909,909,909,909,909,909,+909,909,910,911,163,163,163,163,163,163,163,163,163,163,163,912,+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,+479,479,479,479,479,479,479,479,479,479,479,479,479,163,163,163,++/* block 114 */+913,913,913,914,915,915,915,915,915,915,915,915,915,915,915,915,+915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,+915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,+915,915,915,916,914,914,913,913,913,913,914,914,913,913,914,914,+917,918,918,918,918,918,918,919,920,920,918,918,918,918,163,921,+922,922,922,922,922,922,922,922,922,922,163,163,163,163,918,918,+462,462,462,462,462,472,923,462,462,462,462,462,462,462,462,462,+473,473,473,473,473,473,473,473,473,473,462,462,462,462,462,163,++/* block 115 */+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,+924,924,924,924,924,924,924,924,924,925,925,925,925,925,925,926,+926,925,925,926,926,925,925,163,163,163,163,163,163,163,163,163,+924,924,924,925,924,924,924,924,924,924,924,924,925,926,163,163,+927,927,927,927,927,927,927,927,927,927,163,163,928,929,929,929,+462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,+923,462,462,462,462,462,462,474,474,474,462,471,472,471,462,462,++/* block 116 */+930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,+930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,+930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,+931,930,931,931,931,932,932,931,931,932,930,932,932,930,931,933,+934,933,934,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,930,930,935,936,937,+938,938,938,938,938,938,938,938,938,938,938,939,940,940,939,939,+941,941,938,942,942,939,943,163,163,163,163,163,163,163,163,163,++/* block 117 */+163,484,484,484,484,484,484,163,163,484,484,484,484,484,484,163,+163,484,484,484,484,484,484,163,163,163,163,163,163,163,163,163,+484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163,+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,+ 70, 70, 70,944, 70, 70, 70, 70, 70, 70, 70,867,147,147,147,147,+ 70, 70, 70, 70, 70,221, 70, 70, 70,147, 46, 46,163,163,163,163,+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,++/* block 118 */+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,939,939,940,939,939,940,939,939,941,946,943,163,163,+947,947,947,947,947,947,947,947,947,947,163,163,163,163,163,163,++/* block 119 */+948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,++/* block 120 */+949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949,++/* block 121 */+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,++/* block 122 */+949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949,++/* block 123 */+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,++/* block 124 */+949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949,++/* block 125 */+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,++/* block 126 */+949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,163,163,163,163,163,163,163,163,163,163,163,163,+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,+482,482,482,482,482,482,482,163,163,163,163,483,483,483,483,483,+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,+483,483,483,483,483,483,483,483,483,483,483,483,163,163,163,163,++/* block 127 */+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,++/* block 128 */+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,++/* block 129 */+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,++/* block 130 */+952,952,952,952,952,952,952,952,952,952,952,952,952,952,839,839,+952,839,952,839,839,952,952,952,952,952,952,952,952,952,952,839,+952,839,952,839,839,952,952,839,839,839,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,163,163,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,++/* block 131 */+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 132 */+653,653,653,653,653,653,653,163,163,163,163,163,163,163,163,163,+163,163,163,257,257,257,257,257,163,163,163,163,163,270,265,270,+270,270,270,270,270,270,270,270,270,953,270,270,270,270,270,270,+270,270,270,270,270,270,270,262,270,270,270,270,270,262,270,262,+270,270,262,270,270,262,270,270,270,270,270,270,270,270,270,270,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,++/* block 133 */+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,331,331,331,331,331,331,331,331,331,331,331,331,331,331,+331,331,331,302,302,302,302,302,302,302,302,302,302,302,302,302,+302,302,302,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,++/* block 134 */+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,954,954,+954,954,954,954,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,++/* block 135 */+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,++/* block 136 */+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,955,956,+280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,++/* block 137 */+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+302,302,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,302,302,302,302,302,302,302,280,+957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,+957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,+286,286,958,286,286,286,286,286,286,286,954,954,277,959,280,280,++/* block 138 */+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,961,+962,962,962,963,962,962,962,964,965,962,163,163,163,163,163,163,+154,154,154,154,154,154,154,154,154,154,154,154,154,154,856,856,+962,966,966,701,701,964,965,964,965,964,965,964,965,964,965,964,+965,967,968,967,968,799,799,964,965,962,962,962,962,701,701,701,+969,166,970,163,166,971,972,972,966,973,974,973,974,973,974,975,+962,976,714,977,978,978,716,163,976,430,975,962,163,163,163,163,+954,286,954,286,954,302,954,286,954,286,954,286,954,286,954,286,++/* block 139 */+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,302,302, 51,++/* block 140 */+163,972,979,975,430,975,962,980,973,974,962,714,969,981,970,982,+983,983,983,983,983,983,983,983,983,983,971,166,978,716,978,972,+962,984,984,984,984,984,984, 59, 59, 59, 59, 59, 59, 59, 59, 59,+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,973,976,974,985,701,+ 46,986,986,986,986,986,986, 62, 62, 62, 62, 62, 62, 62, 62, 62,+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,973,716,974,716,973,+974,987,988,989,990,826,825,825,825,825,825,825,825,825,825,825,+827,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,++/* block 141 */+825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,+825,825,825,825,825,825,825,825,825,825,825,825,825,825,991,991,+831,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,163,+163,163,830,830,830,830,830,830,163,163,830,830,830,830,830,830,+163,163,830,830,830,830,830,830,163,163,830,830,830,163,163,163,+430,430,716, 46,724,430,430,163,724,716,716,716,716,724,724,163,+708,708,708,708,708,708,708,708,708,992,992,992,724,724,957,957,++/* block 142 */+993,993,993,993,993,993,993,993,993,993,993,993,163,993,993,993,+993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,+993,993,993,993,993,993,993,163,993,993,993,993,993,993,993,993,+993,993,993,993,993,993,993,993,993,993,993,163,993,993,163,993,+993,993,993,993,993,993,993,993,993,993,993,993,993,993,163,163,+993,993,993,993,993,993,993,993,993,993,993,993,993,993,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 143 */+993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,+993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,+993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,+993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,+993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,+993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,+993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,+993,993,993,993,993,993,993,993,993,993,993,163,163,163,163,163,++/* block 144 */+994,995,996,163,163,163,163,997,997,997,997,997,997,997,997,997,+997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,+997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,+997,997,997,997,163,163,163,998,998,998,998,998,998,998,998,998,+999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,+999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,+999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,+999,999,999,999,999,1000,1000,1000,1000,1001,1001,1001,1001,1001,1001,1001,++/* block 145 */+1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1000,1000,1001,1002,1002,163,+724,724,724,724,724,724,724,724,724,724,724,724,724,163,163,163,+1001,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,158,163,163,++/* block 146 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 147 */+1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,+1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,163,163,163,+1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,+1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,+1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,+1004,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1005,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,+1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,163,163,163,163,++/* block 148 */+1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,+1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,+1008,1008,1008,1008,163,163,163,163,163,163,163,163,163,1007,1007,1007,+1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,+1009,1010,1009,1009,1009,1009,1009,1009,1009,1009,1010,163,163,163,163,163,+1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,+1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,+1011,1011,1011,1011,1011,1011,1012,1012,1012,1012,1012,163,163,163,163,163,++/* block 149 */+1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,+1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,163,1014,+1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,+1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,+1015,1015,1015,1015,163,163,163,163,1015,1015,1015,1015,1015,1015,1015,1015,+1016,1017,1017,1017,1017,1017,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 150 */+1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,+1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,+1018,1018,1018,1018,1018,1018,1018,1018,1019,1019,1019,1019,1019,1019,1019,1019,+1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,+1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,+1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,+1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,+1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,++/* block 151 */+1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,+1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,163,163,+1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,163,163,163,163,163,163,+1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,+1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,+1023,1023,1023,1023,163,163,163,163,1024,1024,1024,1024,1024,1024,1024,1024,+1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,+1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,163,163,163,163,++/* block 152 */+1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,+1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,+1025,1025,1025,1025,1025,1025,1025,1025,163,163,163,163,163,163,163,163,+1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,+1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,+1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,+1026,1026,1026,1026,163,163,163,163,163,163,163,163,163,163,163,1027,+1028,1028,1028,1028,1028,1028,1028,1028,1028,1028,1028,163,1028,1028,1028,1028,++/* block 153 */+1028,1028,1028,1028,1028,1028,1028,1028,1028,1028,1028,163,1028,1028,1028,1028,+1028,1028,1028,163,1028,1028,163,1029,1029,1029,1029,1029,1029,1029,1029,1029,+1029,1029,163,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,+1029,1029,163,1029,1029,1029,1029,1029,1029,1029,163,1029,1029,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 154 */+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,++/* block 155 */+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,1030,163,163,163,163,163,163,163,163,163,+1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,+1030,1030,1030,1030,1030,1030,163,163,163,163,163,163,163,163,163,163,+1030,1030,1030,1030,1030,1030,1030,1030,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 156 */+147,1031,1031,147,147,147,163,147,147,147,147,147,147,147,147,147,+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,+147,163,147,147,147,147,147,147,147,147,147,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 157 */+1032,1032,1032,1032,1032,1032,262,262,1032,262,1032,1032,1032,1032,1032,1032,+1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,+1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,+1032,1032,1032,1032,1032,1032,262,1032,1032,262,262,262,1032,262,262,1032,+1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,+1033,1033,1033,1033,1033,1033,262,1034,1035,1035,1035,1035,1035,1035,1035,1035,+1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,+1036,1036,1036,1036,1036,1036,1036,1037,1037,1038,1038,1038,1038,1038,1038,1038,++/* block 158 */+1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,+1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,262,+262,262,262,262,262,262,262,1040,1040,1040,1040,1040,1040,1040,1040,1040,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,+1041,1041,1041,262,1041,1041,262,262,262,262,262,1042,1042,1042,1042,1042,++/* block 159 */+1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,+1043,1043,1043,1043,1043,1043,1044,1044,1044,1044,1044,1044,262,262,262,1045,+1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,+1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,262,262,262,262,262,1047,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,++/* block 160 */+1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,+1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,+1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,+1049,1049,1049,1049,1049,1049,1049,1049,262,262,262,262,1050,1050,1049,1049,+1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,+262,262,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,+1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,+1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,++/* block 161 */+1051,1052,1052,1052,262,1052,1052,262,262,262,262,262,1052,1052,1052,1052,+1051,1051,1051,1051,262,1051,1051,1051,262,1051,1051,1051,1051,1051,1051,1051,+1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,+1051,1051,1051,1051,1051,1051,262,262,1053,1053,1053,262,262,262,262,1054,+1055,1055,1055,1055,1055,1055,1055,1055,1055,262,262,262,262,262,262,262,+1056,1056,1056,1056,1056,1056,1057,1057,1056,262,262,262,262,262,262,262,+1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,+1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1059,1059,1060,++/* block 162 */+1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,+1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1062,1062,1062,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+1063,1063,1063,1063,1063,1063,1063,1063,1064,1063,1063,1063,1063,1063,1063,1063,+1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,+1063,1063,1063,1063,1063,1065,1065,262,262,262,262,1066,1066,1066,1066,1066,+1067,1067,1068,1067,1067,1067,1069,262,262,262,262,262,262,262,262,262,++/* block 163 */+1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,+1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,+1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,+1070,1070,1070,1070,1070,1070,262,262,262,1071,1072,1072,1072,1072,1072,1072,+1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,+1073,1073,1073,1073,1073,1073,262,262,1074,1074,1074,1074,1074,1074,1074,1074,+1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,+1075,1075,1075,262,262,262,262,262,1076,1076,1076,1076,1076,1076,1076,1076,++/* block 164 */+1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,+1077,1077,262,262,262,262,262,262,262,1078,1078,1078,1078,262,262,262,+262,262,262,262,262,262,262,262,262,1079,1079,1079,1079,1079,1079,1079,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,++/* block 165 */+1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,+1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,+1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,+1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,+1080,1080,1080,1080,1080,1080,1080,1080,1080,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,++/* block 166 */+1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,+1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,+1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,+1081,1081,1081,262,262,262,262,262,262,262,262,262,262,262,262,262,+1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,+1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,+1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,+1082,1082,1082,262,262,262,262,262,262,262,1083,1083,1083,1083,1083,1083,++/* block 167 */+1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,+1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,+1084,1084,1085,1085,1086,1086,1086,1086,302,302,302,302,302,302,302,302,+1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,302,302,302,302,302,302,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,++/* block 168 */+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,++/* block 169 */+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,+1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,262,++/* block 170 */+1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,+1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,+1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,262,1090,1090,1091,262,262,+1089,1089,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,+302,302,302,302,302,302,302,302,302,302,302,302,302,291,291,291,++/* block 171 */+1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,+1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1093,1093,1093,+1093,1093,1093,1093,1093,1093,1093,1092,262,262,262,262,262,262,262,262,+1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,+1094,1094,1094,1094,1094,1094,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,+1095,1096,1096,1096,1096,1097,1097,1097,1097,1097,302,302,302,302,302,302,+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,+1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,++/* block 172 */+1098,1098,1099,1099,1099,1099,1100,1100,1100,1100,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,+1101,1101,1101,1101,1101,1102,1102,1102,1102,1102,1102,1102,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,+1103,1103,1103,1103,1103,1103,1103,262,262,262,262,262,262,262,262,262,++/* block 173 */+1104,1105,1104,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,+1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,+1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,+1106,1106,1106,1106,1106,1106,1106,1106,1105,1105,1105,1105,1105,1105,1105,1105,+1105,1105,1105,1105,1105,1105,1107,1108,1108,1109,1109,1109,1109,1109,163,163,+163,163,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,+1110,1110,1110,1110,1110,1110,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,+1107,1106,1106,1105,1105,1106,163,163,163,163,163,163,163,163,163,1112,++/* block 174 */+1113,1113,1114,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,+1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,+1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,+1114,1114,1114,1113,1113,1113,1113,1114,1114,1116,1117,1118,1118,1119,1120,1120,+1120,1120,1113,163,163,163,163,163,163,163,163,163,163,1119,163,163,+1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,+1121,1121,1121,1121,1121,1121,1121,1121,1121,163,163,163,163,163,163,163,+1122,1122,1122,1122,1122,1122,1122,1122,1122,1122,163,163,163,163,163,163,++/* block 175 */+1123,1123,1123,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,+1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,+1124,1124,1124,1124,1124,1124,1124,1123,1123,1123,1123,1123,1125,1123,1123,1123,+1123,1123,1123,1126,1126,163,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,+1128,1129,1129,1129,1124,1125,1125,1124,163,163,163,163,163,163,163,163,+1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,+1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,+1130,1130,1130,1131,1132,1132,1130,163,163,163,163,163,163,163,163,163,++/* block 176 */+1133,1133,1134,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,+1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,+1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,+1135,1135,1135,1134,1134,1134,1133,1133,1133,1133,1133,1133,1133,1133,1133,1134,+1136,1135,1137,1137,1135,1138,1138,1139,1139,1140,1141,1141,1141,1138,1134,1133,+1142,1142,1142,1142,1142,1142,1142,1142,1142,1142,1135,1139,1135,1139,1138,1138,+163,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,+1143,1143,1143,1143,1143,163,163,163,163,163,163,163,163,163,163,163,++/* block 177 */+1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,+1144,1144,163,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,+1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1145,1145,1145,1146,+1146,1146,1145,1145,1146,1147,1148,1146,1149,1149,1150,1149,1149,1151,1146,1144,+1144,1146,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 178 */+1152,1152,1152,1152,1152,1152,1152,163,1152,163,1152,1152,1152,1152,163,1152,+1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,163,1152,+1152,1152,1152,1152,1152,1152,1152,1152,1152,1153,163,163,163,163,163,163,+1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,+1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,+1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1155,+1156,1156,1156,1155,1155,1155,1155,1155,1155,1157,1158,163,163,163,163,163,+1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,163,163,163,163,163,163,++/* block 179 */+1160,1161,1162,1163,163,1164,1164,1164,1164,1164,1164,1164,1164,163,163,1164,+1164,163,163,1164,1164,1164,1164,1164,1164,1164,1164,1164,1164,1164,1164,1164,+1164,1164,1164,1164,1164,1164,1164,1164,1164,163,1164,1164,1164,1164,1164,1164,+1164,163,1164,1164,163,1164,1164,1164,1164,1164,163,1165,1166,1164,1167,1162,+1160,1162,1162,1162,1162,163,163,1162,1162,163,163,1162,1162,1168,163,163,+1164,163,163,163,163,163,163,1167,163,163,163,163,163,1169,1164,1164,+1164,1164,1162,1162,163,163,1170,1170,1170,1170,1170,1170,1170,163,163,163,+1170,1170,1170,1170,1170,163,163,163,163,163,163,163,163,163,163,163,++/* block 180 */+1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,+1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,+1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,+1171,1171,1171,1171,1171,1172,1172,1172,1173,1173,1173,1173,1173,1173,1173,1173,+1172,1172,1174,1173,1173,1172,1175,1171,1171,1171,1171,1176,1176,1177,1178,1178,+1179,1179,1179,1179,1179,1179,1179,1179,1179,1179,1177,1177,163,1178,1180,1171,+1171,1171,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 181 */+1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,+1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,+1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,+1182,1183,1183,1184,1184,1184,1184,1184,1184,1183,1184,1183,1183,1182,1183,1184,+1184,1183,1185,1186,1181,1181,1187,1181,163,163,163,163,163,163,163,163,+1188,1188,1188,1188,1188,1188,1188,1188,1188,1188,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 182 */+1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,+1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,+1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1190,+1191,1191,1192,1192,1192,1192,163,163,1191,1191,1191,1191,1192,1192,1191,1193,+1194,1195,1196,1196,1197,1197,1198,1198,1198,1196,1196,1196,1196,1196,1196,1196,+1196,1196,1196,1196,1196,1196,1196,1196,1189,1189,1189,1189,1192,1192,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 183 */+1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,+1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,+1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,+1200,1200,1200,1201,1201,1201,1201,1201,1201,1201,1201,1200,1200,1201,1200,1202,+1201,1203,1203,1204,1199,163,163,163,163,163,163,163,163,163,163,163,+1205,1205,1205,1205,1205,1205,1205,1205,1205,1205,163,163,163,163,163,163,+531,531,531,531,531,531,531,531,531,531,531,531,531,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 184 */+1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,+1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,+1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1207,1208,1207,1208,1208,+1207,1207,1207,1207,1207,1207,1209,1210,1206,1211,163,163,163,163,163,163,+1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 185 */+1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,+1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,163,163,1214,1214,1214,+1215,1215,1214,1214,1214,1214,1216,1214,1214,1214,1214,1217,163,163,163,163,+1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1219,1219,1220,1220,1220,1221,+1213,1213,1213,1213,1213,1213,1213,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 186 */+1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,+1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,+1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1223,1223,1223,1224,+1224,1224,1224,1224,1224,1224,1224,1224,1223,1225,1226,1227,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 187 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,+1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,+1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,+1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,+1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1231,1231,1231,1231,1231,1231,+1231,1231,1231,163,163,163,163,163,163,163,163,163,163,163,163,1232,++/* block 188 */+1233,1233,1233,1233,1233,1233,1233,163,163,1233,163,163,1233,1233,1233,1233,+1233,1233,1233,1233,163,1233,1233,163,1233,1233,1233,1233,1233,1233,1233,1233,+1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,+1234,1235,1235,1235,1235,1235,163,1235,1235,163,163,1236,1236,1237,1238,1239,+1235,1239,1235,1240,1241,1242,1241,163,163,163,163,163,163,163,163,163,+1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 189 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1244,1244,1244,1244,1244,1244,1244,1244,163,163,1244,1244,1244,1244,1244,1244,+1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,+1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,+1244,1245,1245,1245,1246,1246,1246,1246,163,163,1246,1246,1245,1245,1245,1245,+1247,1244,1248,1244,1245,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 190 */+1249,1250,1250,1250,1250,1250,1250,1251,1251,1250,1250,1249,1249,1249,1249,1249,+1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,+1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,+1249,1249,1249,1252,1253,1250,1250,1250,1250,1254,1255,1250,1250,1250,1250,1256,+1256,1256,1257,1257,1256,1256,1256,1253,163,163,163,163,163,163,163,163,+1258,1259,1259,1259,1259,1259,1259,1260,1260,1259,1259,1259,1258,1258,1258,1258,+1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,+1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,++/* block 191 */+1258,1258,1258,1258,1261,1261,1261,1261,1261,1261,1259,1259,1259,1259,1259,1259,+1259,1259,1259,1259,1259,1259,1259,1260,1262,1263,1264,1265,1265,1258,1264,1264,+1264,1266,1266,163,163,163,163,163,163,163,163,163,163,163,163,163,+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,+1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,+1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,+1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,+1267,1267,1267,1267,1267,1267,1267,1267,1267,163,163,163,163,163,163,163,++/* block 192 */+343,343,343,343,343,343,343,343,343,343,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 193 */+1268,1268,1268,1268,1268,1268,1268,1268,1268,163,1268,1268,1268,1268,1268,1268,+1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,+1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1269,+1270,1270,1270,1270,1270,1270,1270,163,1270,1270,1270,1270,1270,1270,1269,1271,+1268,1272,1272,1273,1274,1274,163,163,163,163,163,163,163,163,163,163,+1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1276,1276,1276,1276,1276,1276,+1276,1276,1276,1276,1276,1276,1276,1276,1276,1276,1276,1276,1276,163,163,163,+1277,1278,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,++/* block 194 */+1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,+163,163,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,+1280,1280,1280,1280,1280,1280,1280,1280,163,1281,1280,1280,1280,1280,1280,1280,+1280,1281,1280,1280,1281,1280,1280,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 195 */+1282,1282,1282,1282,1282,1282,1282,163,1282,1282,163,1282,1282,1282,1282,1282,+1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,+1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,+1282,1283,1283,1283,1283,1283,1283,163,163,163,1283,163,1283,1283,163,1283,+1283,1283,1284,1283,1285,1285,1286,1283,163,163,163,163,163,163,163,163,+1287,1287,1287,1287,1287,1287,1287,1287,1287,1287,163,163,163,163,163,163,+1288,1288,1288,1288,1288,1288,163,1288,1288,163,1288,1288,1288,1288,1288,1288,+1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,++/* block 196 */+1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1289,1289,1289,1289,1289,163,+1290,1290,163,1289,1289,1290,1289,1291,1288,163,163,163,163,163,163,163,+1292,1292,1292,1292,1292,1292,1292,1292,1292,1292,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 197 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,+1293,1293,1293,1294,1294,1295,1295,1296,1296,163,163,163,163,163,163,163,++/* block 198 */+1297,1297,1298,1299,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,+1300,163,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,+1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,+1300,1300,1300,1300,1299,1299,1297,1297,1297,1297,1297,163,163,163,1299,1299,+1297,1301,1302,1303,1303,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,+1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 199 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+843,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,+388,388,1306,388,1306,390,390,390,390,390,390,390,390,391,391,391,+391,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,+390,390,163,163,163,163,163,163,163,163,163,163,163,163,163,1307,++/* block 200 */+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,++/* block 201 */+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 202 */+1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,+1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,+1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,+1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,+1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,+1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,+1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,163,+1310,1310,1310,1310,1310,163,163,163,163,163,163,163,163,163,163,163,++/* block 203 */+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,+1308,1308,1308,1308,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 204 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,+1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,+1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,+1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,+1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,+1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,+1311,1312,1312,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 205 */+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,++/* block 206 */+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,+1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,+1315,1313,1313,1313,1313,1313,1313,1316,1316,1316,1316,1316,1316,1316,1316,1316,+1316,1316,1316,1316,1316,1316,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 207 */+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,++/* block 208 */+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,+1317,1317,1317,1317,1317,1317,1317,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 209 */+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,++/* block 210 */+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,+859,859,859,859,859,859,859,859,859,163,163,163,163,163,163,163,+1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,+1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,163,+1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,163,163,163,163,1320,1320,+1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,++/* block 211 */+1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,+1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,+1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,+1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,163,+1322,1322,1322,1322,1322,1322,1322,1322,1322,1322,163,163,163,163,163,163,+1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,+1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,163,163,+1324,1324,1324,1324,1324,1325,163,163,163,163,163,163,163,163,163,163,++/* block 212 */+1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,+1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,+1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,+1327,1327,1327,1327,1327,1327,1327,1328,1328,1329,1330,1330,1331,1331,1331,1331,+1332,1332,1333,1333,1328,1331,163,163,163,163,163,163,163,163,163,163,+1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,163,1335,1335,1335,1335,1335,+1335,1335,163,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,+1326,1326,1326,1326,1326,1326,1326,1326,163,163,163,163,163,1326,1326,1326,++/* block 213 */+1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 214 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,+1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,+1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,+1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,++/* block 215 */+1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,+1338,1338,1338,1338,1338,1338,1338,1339,1340,1341,1341,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 216 */+1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,+1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,+1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,+1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,+1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,163,163,163,163,1343,+1342,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,++/* block 217 */+1344,1344,1344,1344,1344,1344,1344,1344,163,163,163,163,163,163,163,1345,+1345,1345,1345,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1347,1348,1349,800,1350,163,163,163,163,163,163,163,163,163,163,163,+1351,1351,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 218 */+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,++/* block 219 */+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,+1352,1352,1352,1352,1352,1352,1352,1352,163,163,163,163,163,163,163,163,++/* block 220 */+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,++/* block 221 */+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,+1353,1353,1353,1353,1353,1353,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 222 */+1352,1352,1352,1352,1352,1352,1352,1352,1352,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 223 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1354,1354,1354,1354,163,1354,1354,1354,1354,1354,1354,1354,163,1354,1354,163,++/* block 224 */+825,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,++/* block 225 */+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,++/* block 226 */+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,+825,825,825,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,820,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+820,820,820,163,163,825,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,825,825,825,825,163,163,163,163,163,163,163,163,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,++/* block 227 */+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,++/* block 228 */+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,+1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,163,163,163,163,++/* block 229 */+1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,+1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,+1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,+1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,+1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,+1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,+1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,163,163,163,163,163,+1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,163,163,163,++/* block 230 */+1356,1356,1356,1356,1356,1356,1356,1356,1356,163,163,163,163,163,163,163,+1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,163,163,1357,1358,1359,1360,+1361,1361,1361,1361,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 231 */+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,+154,154,154,154,154,154,154,154,154,154,154,154,154,154,163,163,+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,+154,154,154,154,154,154,154,163,163,163,163,163,163,163,163,163,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,++/* block 232 */+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 233 */+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,++/* block 234 */+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,163,163,163,163,163,163,163,163,163,163,++/* block 235 */+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,163,163,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,1362,1363,154,154,154,461,461,461,1364,1365,1365,+1365,1365,1365, 51, 51, 51, 51, 51, 51, 51, 51,154,154,154,154,154,++/* block 236 */+154,154,154,461,461,154,154,154,154,154,154,154,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,154,154,154,154,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,724,724,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 237 */+1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,+1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,+1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,+1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,+1001,1001,1366,1366,1366,1001,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 238 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,+836,836,836,836,163,163,163,163,163,163,163,163,163,163,163,163,+836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,+836,836,836,836,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 239 */+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,163,163,163,163,163,163,163,163,163,+833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,+833,833,836,836,836,836,836,836,836,163,163,163,163,163,163,163,++/* block 240 */+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,726,726,726,726,726,726,+726,726,737,737,726,726,726,726,726,726,726,726,726,726,726,726,+726,726,726,726,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,726,726,+726,726,726,726,726,163,737,737,726,726,726,726,726,726,726,726,+726,726,726,726,726,726,726,726,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,++/* block 241 */+725,725,726,726,726,726,726,726,726,726,737,737,726,726,726,726,+726,726,726,726,726,726,726,726,726,726,726,726,725,163,725,725,+163,163,725,163,163,725,725,163,163,725,725,725,725,163,725,725,+725,725,725,725,725,725,726,726,726,726,163,726,163,726,737,737,+726,726,726,726,163,726,726,726,726,726,726,726,726,726,726,726,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,726,726,726,726,726,726,+726,726,737,737,726,726,726,726,726,726,726,726,726,726,726,726,++/* block 242 */+726,726,726,726,725,725,163,725,725,725,725,163,163,725,725,725,+725,725,725,725,725,163,725,725,725,725,725,725,725,163,726,726,+726,726,726,726,726,726,737,737,726,726,726,726,726,726,726,726,+726,726,726,726,726,726,726,726,725,725,163,725,725,725,725,163,+725,725,725,725,725,163,725,163,163,163,725,725,725,725,725,725,+725,163,726,726,726,726,726,726,726,726,737,737,726,726,726,726,+726,726,726,726,726,726,726,726,726,726,726,726,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,++/* block 243 */+725,725,725,725,725,725,726,726,726,726,726,726,726,726,737,737,+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,726,726,726,726,726,726,+726,726,737,737,726,726,726,726,726,726,726,726,726,726,726,726,+726,726,726,726,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,726,726,+726,726,726,726,726,726,737,737,726,726,726,726,726,726,726,726,++/* block 244 */+726,726,726,726,726,726,726,726,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,726,726,726,726,726,726,726,726,737,737,726,726,726,726,+726,726,726,726,726,726,726,726,726,726,726,726,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,726,726,726,726,726,726,726,726,737,737,+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,++/* block 245 */+725,725,725,725,725,725,725,725,725,725,726,726,726,726,726,726,+726,726,737,737,726,726,726,726,726,726,726,726,726,726,726,726,+726,726,726,726,726,726,163,163,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,+725,1367,726,726,726,726,726,726,726,726,726,726,726,726,726,726,+726,726,726,726,726,726,726,726,726,726,726,716,726,726,726,726,+726,726,725,725,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,1367,726,726,726,726,++/* block 246 */+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,+726,726,726,726,726,716,726,726,726,726,726,726,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,1367,726,726,726,726,726,726,726,726,726,726,+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,716,+726,726,726,726,726,726,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,1367,+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,++/* block 247 */+726,726,726,726,726,726,726,726,726,716,726,726,726,726,726,726,+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,+725,725,725,725,725,725,725,725,725,1367,726,726,726,726,726,726,+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,+726,726,726,716,726,726,726,726,726,726,725,726,163,163,1368,1368,+1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,+1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,+1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,++/* block 248 */+1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,+1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,+1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,+1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,+1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,+1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,+1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,+1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,++/* block 249 */+1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,+1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,+1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,+1370,1370,1370,1370,1370,1370,1370,1369,1369,1369,1369,1370,1370,1370,1370,1370,+1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,+1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,+1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1369,1369,1369,+1369,1369,1369,1369,1369,1370,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,++/* block 250 */+1369,1369,1369,1369,1370,1369,1369,1371,1372,1371,1371,1373,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,1370,1370,1370,1370,1370,+163,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 251 */+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 92, 70, 70, 70, 70, 70,+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,644, 70, 70, 70, 70,163,+163,163,163,163,163, 70, 70, 70, 70, 70, 70,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 252 */+1374,1374,1374,1374,1374,1374,1374,163,1374,1374,1374,1374,1374,1374,1374,1374,+1374,1374,1374,1374,1374,1374,1374,1374,1374,163,163,1374,1374,1374,1374,1374,+1374,1374,163,1374,1374,163,1374,1374,1374,1374,1374,163,163,163,163,163,+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,+858,858,858,858,858,858,858,858,858,858,858,858,1375,1375,858,858,+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,+858,858,858,858,858,858,858,858,1375,858,858,858,858,858,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 253 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,788,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 254 */+1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,+1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,+1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,163,163,163,+1377,1377,1377,1377,1377,1377,1377,1378,1378,1378,1378,1378,1379,1379,163,163,+1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,163,163,163,163,1376,1381,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 255 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,+1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1383,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,+1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,+1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1385,1385,1385,1385,+1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,163,163,163,163,163,1387,++/* block 256 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,+1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1389,1390,1390,1390,1390,+1391,1391,1391,1391,1391,1391,1391,1391,1391,1391,163,163,163,163,163,163,++/* block 257 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+484,484,484,484,484,484,484,163,484,484,484,484,163,484,484,163,+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,163,++/* block 258 */+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,++/* block 259 */+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,262,262,1393,1393,1393,1393,1393,1393,1393,1393,1393,+1394,1394,1394,1394,1394,1394,1394,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,++/* block 260 */+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,+1395,1395,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,+1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,+1396,1396,1396,1396,1397,1397,1397,1398,1399,1399,1399,1400,262,262,262,262,+1401,1401,1401,1401,1401,1401,1401,1401,1401,1401,262,262,262,262,1402,1402,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,++/* block 261 */+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+302,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,++/* block 262 */+1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,+1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,+1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1404,1403,1403,1403,+1405,1403,1403,1403,1403,302,302,302,302,302,302,302,302,302,302,302,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,++/* block 263 */+302,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,+1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,+1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1404,1403,+1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,302,302,+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,++/* block 264 */+1406,1406,1406,1406,302,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,+1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,+302,1406,1406,302,1406,302,302,1406,302,1406,1406,1406,1406,1406,1406,1406,+1406,1406,1406,302,1406,1406,1406,1406,302,1406,302,1406,302,302,302,302,+302,302,1406,302,302,302,302,1406,302,1406,302,1406,302,1406,1406,1406,+302,1406,1406,302,1406,302,302,1406,302,1406,302,1406,302,1406,302,1406,+302,1406,1406,302,1406,302,302,1406,1406,1406,1406,302,1406,1406,1406,1406,+1406,1406,1406,302,1406,1406,1406,1406,302,1406,1406,1406,1406,302,1406,302,++/* block 265 */+1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,302,1406,1406,1406,1406,1406,+1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,302,302,302,302,+302,1406,1406,1406,302,1406,1406,1406,1406,1406,302,1406,1406,1406,1406,1406,+1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,302,302,302,302,+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,+274,274,302,302,302,302,302,302,302,302,302,302,302,302,302,302,++/* block 266 */+1407,1407,1407,1407,1408,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1409,1409,1409,1409,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,++/* block 267 */+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1409,+1409,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1409,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1408,+1409,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,++/* block 268 */+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 58, 58,1407,1407,1407,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,1407,+1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,+1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,461,461,461,461,461,461,+1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,+1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,724,724,1407,1407,1407,1407,+1411,1411,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1411,1411,++/* block 269 */+1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,461,461,461,461,1412,461,+461,1412,1412,1412,1412,1412,1412,1412,1412,1412,1412,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,1407,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,+1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,++/* block 270 */+1414,1412,1415,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+461,461,461,461,461,461,461,461,461,461,1412,461,461,461,461,461,+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,1412,+461,461,1412,1412,1412,1412,1412,1415,1412,1412,1412,461,1409,1409,1409,1409,+461,461,461,461,461,461,461,461,461,1409,1409,1409,1409,1409,1409,1409,+1416,1416,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1407,1407,1407,1407,1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,++/* block 271 */+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,++/* block 272 */+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,728,1407,1407,728,728,728,728,728,728,728,728,728,1408,1408,1408,+1408,1408,1408,1408,1408,1408,728,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,728,1408,1408,++/* block 273 */+1408,1408,1408,1408,1408,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1407,1407,728,728,1407,728,728,728,1407,1407,728,728,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1417,1417,1417,1408,1408,1417,1408,1408,1417,1418,1418,728,728,1408,+1408,1408,1408,1408,728,728,728,728,728,728,728,728,728,728,728,728,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1407,1407,728,1408,728,1407,728,1408,1408,1408,1419,1419,1419,1419,1419,++/* block 274 */+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,728,+1408,728,1417,1417,1408,1408,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,+1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,+1417,1417,1417,1417,1417,1417,1417,1417,1417,1408,1408,1408,1417,1408,1408,1408,++/* block 275 */+1408,1417,1417,1417,1408,1417,1417,1417,1408,1408,1408,1408,1408,1408,1408,1417,+1408,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1417,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,728,1407,1408,++/* block 276 */+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,724,724,+724,724,724,724,724,724,1407,1407,1407,728,728,1408,1408,1408,1408,1407,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1407,1407,1407,1407,1407,1407,1407,728,+728,1407,1407,728,1418,1418,728,728,728,728,1417,1407,1407,1407,1407,1407,++/* block 277 */+1407,1407,1407,1407,1407,1407,1407,728,1407,1407,728,728,728,728,1407,1407,+1418,1407,1407,1407,1407,1417,1417,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1408,728,1407,1407,728,1407,1407,1407,1407,1407,1407,1407,+1407,728,728,1407,1407,1407,1407,1407,1407,1407,1407,1407,728,1407,1407,1407,+1407,1407,728,728,728,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,728,728,728,1407,1407,1407,1407,1407,1407,1407,1407,728,728,728,1407,+1407,728,1407,728,1407,1407,1407,1407,728,1407,1407,1407,1407,1407,1407,728,+1407,1407,1407,728,1407,1407,1407,1407,1407,1407,728,1408,1408,1408,1408,1408,++/* block 278 */+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1417,1417,1417,1408,1408,1408,1417,1417,1417,1417,1417,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,++/* block 279 */+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1417,1417,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1417,1408,1408,1408,1408,1408,1407,1407,1407,1407,1407,728,1417,728,728,728,+1408,1408,1408,1407,1407,1408,1408,1408,1409,1409,1409,1409,1408,1408,1408,1408,+728,728,728,728,728,728,1407,1407,1407,728,1407,1408,1408,1409,1409,1409,+728,1407,1407,728,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,++/* block 280 */+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,1407,1407,1407,1409,1409,1409,1409,1407,1407,1407,1407,1407,++/* block 281 */+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,1407,1407,1407,1407,1407,1409,1409,1409,1409,1409,1409,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,1409,+1408,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,++/* block 282 */+724,724,724,724,724,724,724,724,724,724,724,724,1409,1409,1409,1409,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,1409,1409,1409,1409,1409,1409,1409,1409,+724,724,724,724,724,724,724,724,724,724,1409,1409,1409,1409,1409,1409,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,++/* block 283 */+724,724,724,724,724,724,724,724,1409,1409,1409,1409,1409,1409,1409,1409,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,1409,1409,+1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,++/* block 284 */+724,724,724,724,724,724,724,724,724,724,724,724,1417,1408,1408,1417,+1408,1408,1408,1408,1408,1408,1408,1408,1417,1417,1417,1417,1417,1417,1417,1417,+1408,1408,1408,1408,1408,1408,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1408,724,1417,1417,1417,1408,+1408,1408,1408,1408,1408,1408,724,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1417,1408,1408,1408,1408,1408,1408,1408,1408,++/* block 285 */+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1420,1420,1420,1420,1408,1417,1417,1408,1417,1417,1408,1417,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1417,1417,1417,+1408,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,++/* block 286 */+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,+1407,1407,1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1409,1409,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,++/* block 287 */+1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,1409,1409,1409,1409,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1408,+1408,1408,1408,1417,1417,1417,1409,1409,1409,1409,1409,1409,1409,1409,1408,1408,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,1409,+1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,1409,1409,1409,1409,+1417,1417,1417,1417,1417,1417,1417,1417,1417,1409,1409,1409,1409,1409,1409,1409,++/* block 288 */+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,++/* block 289 */+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,163,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,+724,724,724,724,724,724,724,724,724,724,724,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+1421,1421,1421,1421,1421,1421,1421,1421,1421,1421,163,163,163,163,163,163,++/* block 290 */+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,957,957,++/* block 291 */+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 292 */+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,163,163,163,163,163,163,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,++/* block 293 */+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,163,163,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,++/* block 294 */+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,++/* block 295 */+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 296 */+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 297 */+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,957,957,++/* block 298 */+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,163,163,163,163,163,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,++/* block 299 */+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,++/* block 300 */+708,713,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,+1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,+1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,+1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,+1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,+1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,++/* block 301 */+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,++/* block 302 */+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,++/* block 303 */+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,++/* block 304 */+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,951,951,951,951,951,957,957, }; #if UCD_BLOCK_SIZE != 128
src/c/pcre2/src/pcre2_ucp.h view
@@ -166,29 +166,29 @@ /* These are the bidi class values. */ enum {- ucp_bidiAL, /* Arabic letter */- ucp_bidiAN, /* Arabic number */- ucp_bidiB, /* Paragraph separator */- ucp_bidiBN, /* Boundary neutral */- ucp_bidiCS, /* Common separator */- ucp_bidiEN, /* European number */- ucp_bidiES, /* European separator */- ucp_bidiET, /* European terminator */- ucp_bidiFSI, /* First strong isolate */- ucp_bidiL, /* Left to right */- ucp_bidiLRE, /* Left to right embedding */- ucp_bidiLRI, /* Left to right isolate */- ucp_bidiLRO, /* Left to right override */- ucp_bidiNSM, /* Non-spacing mark */- ucp_bidiON, /* Other neutral */- ucp_bidiPDF, /* Pop directional format */- ucp_bidiPDI, /* Pop directional isolate */- ucp_bidiR, /* Right to left */- ucp_bidiRLE, /* Right to left embedding */- ucp_bidiRLI, /* Right to left isolate */- ucp_bidiRLO, /* Right to left override */- ucp_bidiS, /* Segment separator */- ucp_bidiWS, /* White space */+ ucp_bidiAL, /* Arabic_Letter */+ ucp_bidiAN, /* Arabic_Number */+ ucp_bidiB, /* Paragraph_Separator */+ ucp_bidiBN, /* Boundary_Neutral */+ ucp_bidiCS, /* Common_Separator */+ ucp_bidiEN, /* European_Number */+ ucp_bidiES, /* European_Separator */+ ucp_bidiET, /* European_Terminator */+ ucp_bidiFSI, /* First_Strong_Isolate */+ ucp_bidiL, /* Left_To_Right */+ ucp_bidiLRE, /* Left_To_Right_Embedding */+ ucp_bidiLRI, /* Left_To_Right_Isolate */+ ucp_bidiLRO, /* Left_To_Right_Override */+ ucp_bidiNSM, /* Nonspacing_Mark */+ ucp_bidiON, /* Other_Neutral */+ ucp_bidiPDF, /* Pop_Directional_Format */+ ucp_bidiPDI, /* Pop_Directional_Isolate */+ ucp_bidiR, /* Right_To_Left */+ ucp_bidiRLE, /* Right_To_Left_Embedding */+ ucp_bidiRLI, /* Right_To_Left_Isolate */+ ucp_bidiRLO, /* Right_To_Left_Override */+ ucp_bidiS, /* Segment_Separator */+ ucp_bidiWS, /* White_Space */ }; /* These are grapheme break properties. The Extended Pictographic property@@ -380,6 +380,8 @@ ucp_Tangsa, ucp_Toto, ucp_Vithkuqi,+ ucp_Kawi,+ ucp_Nag_Mundari, /* This must be last */ ucp_Script_Count
src/c/pcre2/src/pcre2_ucptables.c view
@@ -265,6 +265,7 @@ #define STRING_kana0 STR_k STR_a STR_n STR_a "\0" #define STRING_kannada0 STR_k STR_a STR_n STR_n STR_a STR_d STR_a "\0" #define STRING_katakana0 STR_k STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0"+#define STRING_kawi0 STR_k STR_a STR_w STR_i "\0" #define STRING_kayahli0 STR_k STR_a STR_y STR_a STR_h STR_l STR_i "\0" #define STRING_khar0 STR_k STR_h STR_a STR_r "\0" #define STRING_kharoshthi0 STR_k STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0"@@ -347,6 +348,8 @@ #define STRING_mymr0 STR_m STR_y STR_m STR_r "\0" #define STRING_n0 STR_n "\0" #define STRING_nabataean0 STR_n STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0"+#define STRING_nagm0 STR_n STR_a STR_g STR_m "\0"+#define STRING_nagmundari0 STR_n STR_a STR_g STR_m STR_u STR_n STR_d STR_a STR_r STR_i "\0" #define STRING_nand0 STR_n STR_a STR_n STR_d "\0" #define STRING_nandinagari0 STR_n STR_a STR_n STR_d STR_i STR_n STR_a STR_g STR_a STR_r STR_i "\0" #define STRING_narb0 STR_n STR_a STR_r STR_b "\0"@@ -753,6 +756,7 @@ STRING_kana0 STRING_kannada0 STRING_katakana0+ STRING_kawi0 STRING_kayahli0 STRING_khar0 STRING_kharoshthi0@@ -835,6 +839,8 @@ STRING_mymr0 STRING_n0 STRING_nabataean0+ STRING_nagm0+ STRING_nagmundari0 STRING_nand0 STRING_nandinagari0 STRING_narb0@@ -1241,280 +1247,283 @@ { 1665, PT_SCX, ucp_Katakana }, { 1670, PT_SCX, ucp_Kannada }, { 1678, PT_SCX, ucp_Katakana },- { 1687, PT_SCX, ucp_Kayah_Li },- { 1695, PT_SC, ucp_Kharoshthi },+ { 1687, PT_SC, ucp_Kawi },+ { 1692, PT_SCX, ucp_Kayah_Li }, { 1700, PT_SC, ucp_Kharoshthi },- { 1711, PT_SC, ucp_Khitan_Small_Script },- { 1729, PT_SC, ucp_Khmer },- { 1735, PT_SC, ucp_Khmer },- { 1740, PT_SCX, ucp_Khojki },+ { 1705, PT_SC, ucp_Kharoshthi },+ { 1716, PT_SC, ucp_Khitan_Small_Script },+ { 1734, PT_SC, ucp_Khmer },+ { 1740, PT_SC, ucp_Khmer }, { 1745, PT_SCX, ucp_Khojki },- { 1752, PT_SCX, ucp_Khudawadi },- { 1762, PT_SC, ucp_Khitan_Small_Script },- { 1767, PT_SCX, ucp_Kannada },- { 1772, PT_SCX, ucp_Kaithi },- { 1777, PT_GC, ucp_L },- { 1779, PT_LAMP, 0 },- { 1782, PT_SC, ucp_Tai_Tham },- { 1787, PT_SC, ucp_Lao },- { 1791, PT_SC, ucp_Lao },- { 1796, PT_SCX, ucp_Latin },- { 1802, PT_SCX, ucp_Latin },- { 1807, PT_LAMP, 0 },- { 1810, PT_SC, ucp_Lepcha },+ { 1750, PT_SCX, ucp_Khojki },+ { 1757, PT_SCX, ucp_Khudawadi },+ { 1767, PT_SC, ucp_Khitan_Small_Script },+ { 1772, PT_SCX, ucp_Kannada },+ { 1777, PT_SCX, ucp_Kaithi },+ { 1782, PT_GC, ucp_L },+ { 1784, PT_LAMP, 0 },+ { 1787, PT_SC, ucp_Tai_Tham },+ { 1792, PT_SC, ucp_Lao },+ { 1796, PT_SC, ucp_Lao },+ { 1801, PT_SCX, ucp_Latin },+ { 1807, PT_SCX, ucp_Latin },+ { 1812, PT_LAMP, 0 }, { 1815, PT_SC, ucp_Lepcha },- { 1822, PT_SCX, ucp_Limbu },+ { 1820, PT_SC, ucp_Lepcha }, { 1827, PT_SCX, ucp_Limbu },- { 1833, PT_SCX, ucp_Linear_A },- { 1838, PT_SCX, ucp_Linear_B },- { 1843, PT_SCX, ucp_Linear_A },- { 1851, PT_SCX, ucp_Linear_B },- { 1859, PT_SC, ucp_Lisu },- { 1864, PT_PC, ucp_Ll },- { 1867, PT_PC, ucp_Lm },- { 1870, PT_PC, ucp_Lo },- { 1873, PT_BOOL, ucp_Logical_Order_Exception },- { 1877, PT_BOOL, ucp_Logical_Order_Exception },- { 1899, PT_BOOL, ucp_Lowercase },- { 1905, PT_BOOL, ucp_Lowercase },- { 1915, PT_PC, ucp_Lt },- { 1918, PT_PC, ucp_Lu },- { 1921, PT_SC, ucp_Lycian },+ { 1832, PT_SCX, ucp_Limbu },+ { 1838, PT_SCX, ucp_Linear_A },+ { 1843, PT_SCX, ucp_Linear_B },+ { 1848, PT_SCX, ucp_Linear_A },+ { 1856, PT_SCX, ucp_Linear_B },+ { 1864, PT_SC, ucp_Lisu },+ { 1869, PT_PC, ucp_Ll },+ { 1872, PT_PC, ucp_Lm },+ { 1875, PT_PC, ucp_Lo },+ { 1878, PT_BOOL, ucp_Logical_Order_Exception },+ { 1882, PT_BOOL, ucp_Logical_Order_Exception },+ { 1904, PT_BOOL, ucp_Lowercase },+ { 1910, PT_BOOL, ucp_Lowercase },+ { 1920, PT_PC, ucp_Lt },+ { 1923, PT_PC, ucp_Lu }, { 1926, PT_SC, ucp_Lycian },- { 1933, PT_SC, ucp_Lydian },+ { 1931, PT_SC, ucp_Lycian }, { 1938, PT_SC, ucp_Lydian },- { 1945, PT_GC, ucp_M },- { 1947, PT_SCX, ucp_Mahajani },- { 1956, PT_SCX, ucp_Mahajani },- { 1961, PT_SC, ucp_Makasar },+ { 1943, PT_SC, ucp_Lydian },+ { 1950, PT_GC, ucp_M },+ { 1952, PT_SCX, ucp_Mahajani },+ { 1961, PT_SCX, ucp_Mahajani }, { 1966, PT_SC, ucp_Makasar },- { 1974, PT_SCX, ucp_Malayalam },- { 1984, PT_SCX, ucp_Mandaic },+ { 1971, PT_SC, ucp_Makasar },+ { 1979, PT_SCX, ucp_Malayalam }, { 1989, PT_SCX, ucp_Mandaic },- { 1997, PT_SCX, ucp_Manichaean },+ { 1994, PT_SCX, ucp_Mandaic }, { 2002, PT_SCX, ucp_Manichaean },- { 2013, PT_SC, ucp_Marchen },+ { 2007, PT_SCX, ucp_Manichaean }, { 2018, PT_SC, ucp_Marchen },- { 2026, PT_SCX, ucp_Masaram_Gondi },- { 2039, PT_BOOL, ucp_Math },- { 2044, PT_PC, ucp_Mc },- { 2047, PT_PC, ucp_Me },- { 2050, PT_SC, ucp_Medefaidrin },- { 2062, PT_SC, ucp_Medefaidrin },- { 2067, PT_SC, ucp_Meetei_Mayek },- { 2079, PT_SC, ucp_Mende_Kikakui },+ { 2023, PT_SC, ucp_Marchen },+ { 2031, PT_SCX, ucp_Masaram_Gondi },+ { 2044, PT_BOOL, ucp_Math },+ { 2049, PT_PC, ucp_Mc },+ { 2052, PT_PC, ucp_Me },+ { 2055, PT_SC, ucp_Medefaidrin },+ { 2067, PT_SC, ucp_Medefaidrin },+ { 2072, PT_SC, ucp_Meetei_Mayek }, { 2084, PT_SC, ucp_Mende_Kikakui },- { 2097, PT_SC, ucp_Meroitic_Cursive },- { 2102, PT_SC, ucp_Meroitic_Hieroglyphs },- { 2107, PT_SC, ucp_Meroitic_Cursive },- { 2123, PT_SC, ucp_Meroitic_Hieroglyphs },- { 2143, PT_SC, ucp_Miao },- { 2148, PT_SCX, ucp_Malayalam },- { 2153, PT_PC, ucp_Mn },- { 2156, PT_SCX, ucp_Modi },- { 2161, PT_SCX, ucp_Mongolian },+ { 2089, PT_SC, ucp_Mende_Kikakui },+ { 2102, PT_SC, ucp_Meroitic_Cursive },+ { 2107, PT_SC, ucp_Meroitic_Hieroglyphs },+ { 2112, PT_SC, ucp_Meroitic_Cursive },+ { 2128, PT_SC, ucp_Meroitic_Hieroglyphs },+ { 2148, PT_SC, ucp_Miao },+ { 2153, PT_SCX, ucp_Malayalam },+ { 2158, PT_PC, ucp_Mn },+ { 2161, PT_SCX, ucp_Modi }, { 2166, PT_SCX, ucp_Mongolian },- { 2176, PT_SC, ucp_Mro },- { 2180, PT_SC, ucp_Mro },- { 2185, PT_SC, ucp_Meetei_Mayek },- { 2190, PT_SCX, ucp_Multani },+ { 2171, PT_SCX, ucp_Mongolian },+ { 2181, PT_SC, ucp_Mro },+ { 2185, PT_SC, ucp_Mro },+ { 2190, PT_SC, ucp_Meetei_Mayek }, { 2195, PT_SCX, ucp_Multani },- { 2203, PT_SCX, ucp_Myanmar },- { 2211, PT_SCX, ucp_Myanmar },- { 2216, PT_GC, ucp_N },- { 2218, PT_SC, ucp_Nabataean },- { 2228, PT_SCX, ucp_Nandinagari },- { 2233, PT_SCX, ucp_Nandinagari },- { 2245, PT_SC, ucp_Old_North_Arabian },- { 2250, PT_SC, ucp_Nabataean },- { 2255, PT_BOOL, ucp_Noncharacter_Code_Point },- { 2261, PT_PC, ucp_Nd },- { 2264, PT_SC, ucp_Newa },- { 2269, PT_SC, ucp_New_Tai_Lue },- { 2279, PT_SCX, ucp_Nko },- { 2283, PT_SCX, ucp_Nko },- { 2288, PT_PC, ucp_Nl },- { 2291, PT_PC, ucp_No },- { 2294, PT_BOOL, ucp_Noncharacter_Code_Point },- { 2316, PT_SC, ucp_Nushu },- { 2321, PT_SC, ucp_Nushu },- { 2327, PT_SC, ucp_Nyiakeng_Puachue_Hmong },- { 2348, PT_SC, ucp_Ogham },- { 2353, PT_SC, ucp_Ogham },- { 2359, PT_SC, ucp_Ol_Chiki },- { 2367, PT_SC, ucp_Ol_Chiki },- { 2372, PT_SC, ucp_Old_Hungarian },- { 2385, PT_SC, ucp_Old_Italic },- { 2395, PT_SC, ucp_Old_North_Arabian },- { 2411, PT_SCX, ucp_Old_Permic },- { 2421, PT_SC, ucp_Old_Persian },- { 2432, PT_SC, ucp_Old_Sogdian },- { 2443, PT_SC, ucp_Old_South_Arabian },- { 2459, PT_SC, ucp_Old_Turkic },- { 2469, PT_SCX, ucp_Old_Uyghur },- { 2479, PT_SCX, ucp_Oriya },- { 2485, PT_SC, ucp_Old_Turkic },- { 2490, PT_SCX, ucp_Oriya },- { 2495, PT_SC, ucp_Osage },- { 2501, PT_SC, ucp_Osage },- { 2506, PT_SC, ucp_Osmanya },- { 2511, PT_SC, ucp_Osmanya },- { 2519, PT_SCX, ucp_Old_Uyghur },- { 2524, PT_GC, ucp_P },- { 2526, PT_SC, ucp_Pahawh_Hmong },- { 2538, PT_SC, ucp_Palmyrene },- { 2543, PT_SC, ucp_Palmyrene },- { 2553, PT_BOOL, ucp_Pattern_Syntax },- { 2560, PT_BOOL, ucp_Pattern_Syntax },- { 2574, PT_BOOL, ucp_Pattern_White_Space },- { 2592, PT_BOOL, ucp_Pattern_White_Space },- { 2598, PT_SC, ucp_Pau_Cin_Hau },- { 2603, PT_SC, ucp_Pau_Cin_Hau },- { 2613, PT_PC, ucp_Pc },- { 2616, PT_BOOL, ucp_Prepended_Concatenation_Mark },- { 2620, PT_PC, ucp_Pd },- { 2623, PT_PC, ucp_Pe },- { 2626, PT_SCX, ucp_Old_Permic },- { 2631, PT_PC, ucp_Pf },- { 2634, PT_SCX, ucp_Phags_Pa },- { 2639, PT_SCX, ucp_Phags_Pa },- { 2647, PT_SC, ucp_Inscriptional_Pahlavi },- { 2652, PT_SCX, ucp_Psalter_Pahlavi },- { 2657, PT_SC, ucp_Phoenician },- { 2662, PT_SC, ucp_Phoenician },- { 2673, PT_PC, ucp_Pi },- { 2676, PT_SC, ucp_Miao },- { 2681, PT_PC, ucp_Po },- { 2684, PT_BOOL, ucp_Prepended_Concatenation_Mark },- { 2711, PT_SC, ucp_Inscriptional_Parthian },- { 2716, PT_PC, ucp_Ps },- { 2719, PT_SCX, ucp_Psalter_Pahlavi },- { 2734, PT_SCX, ucp_Coptic },- { 2739, PT_SC, ucp_Inherited },- { 2744, PT_BOOL, ucp_Quotation_Mark },- { 2750, PT_BOOL, ucp_Quotation_Mark },- { 2764, PT_BOOL, ucp_Radical },- { 2772, PT_BOOL, ucp_Regional_Indicator },- { 2790, PT_SC, ucp_Rejang },- { 2797, PT_BOOL, ucp_Regional_Indicator },- { 2800, PT_SC, ucp_Rejang },- { 2805, PT_SCX, ucp_Hanifi_Rohingya },- { 2810, PT_SC, ucp_Runic },- { 2816, PT_SC, ucp_Runic },- { 2821, PT_GC, ucp_S },- { 2823, PT_SC, ucp_Samaritan },- { 2833, PT_SC, ucp_Samaritan },- { 2838, PT_SC, ucp_Old_South_Arabian },- { 2843, PT_SC, ucp_Saurashtra },- { 2848, PT_SC, ucp_Saurashtra },- { 2859, PT_PC, ucp_Sc },- { 2862, PT_BOOL, ucp_Soft_Dotted },- { 2865, PT_BOOL, ucp_Sentence_Terminal },- { 2882, PT_SC, ucp_SignWriting },- { 2887, PT_SCX, ucp_Sharada },- { 2895, PT_SC, ucp_Shavian },- { 2903, PT_SC, ucp_Shavian },+ { 2200, PT_SCX, ucp_Multani },+ { 2208, PT_SCX, ucp_Myanmar },+ { 2216, PT_SCX, ucp_Myanmar },+ { 2221, PT_GC, ucp_N },+ { 2223, PT_SC, ucp_Nabataean },+ { 2233, PT_SC, ucp_Nag_Mundari },+ { 2238, PT_SC, ucp_Nag_Mundari },+ { 2249, PT_SCX, ucp_Nandinagari },+ { 2254, PT_SCX, ucp_Nandinagari },+ { 2266, PT_SC, ucp_Old_North_Arabian },+ { 2271, PT_SC, ucp_Nabataean },+ { 2276, PT_BOOL, ucp_Noncharacter_Code_Point },+ { 2282, PT_PC, ucp_Nd },+ { 2285, PT_SC, ucp_Newa },+ { 2290, PT_SC, ucp_New_Tai_Lue },+ { 2300, PT_SCX, ucp_Nko },+ { 2304, PT_SCX, ucp_Nko },+ { 2309, PT_PC, ucp_Nl },+ { 2312, PT_PC, ucp_No },+ { 2315, PT_BOOL, ucp_Noncharacter_Code_Point },+ { 2337, PT_SC, ucp_Nushu },+ { 2342, PT_SC, ucp_Nushu },+ { 2348, PT_SC, ucp_Nyiakeng_Puachue_Hmong },+ { 2369, PT_SC, ucp_Ogham },+ { 2374, PT_SC, ucp_Ogham },+ { 2380, PT_SC, ucp_Ol_Chiki },+ { 2388, PT_SC, ucp_Ol_Chiki },+ { 2393, PT_SC, ucp_Old_Hungarian },+ { 2406, PT_SC, ucp_Old_Italic },+ { 2416, PT_SC, ucp_Old_North_Arabian },+ { 2432, PT_SCX, ucp_Old_Permic },+ { 2442, PT_SC, ucp_Old_Persian },+ { 2453, PT_SC, ucp_Old_Sogdian },+ { 2464, PT_SC, ucp_Old_South_Arabian },+ { 2480, PT_SC, ucp_Old_Turkic },+ { 2490, PT_SCX, ucp_Old_Uyghur },+ { 2500, PT_SCX, ucp_Oriya },+ { 2506, PT_SC, ucp_Old_Turkic },+ { 2511, PT_SCX, ucp_Oriya },+ { 2516, PT_SC, ucp_Osage },+ { 2522, PT_SC, ucp_Osage },+ { 2527, PT_SC, ucp_Osmanya },+ { 2532, PT_SC, ucp_Osmanya },+ { 2540, PT_SCX, ucp_Old_Uyghur },+ { 2545, PT_GC, ucp_P },+ { 2547, PT_SC, ucp_Pahawh_Hmong },+ { 2559, PT_SC, ucp_Palmyrene },+ { 2564, PT_SC, ucp_Palmyrene },+ { 2574, PT_BOOL, ucp_Pattern_Syntax },+ { 2581, PT_BOOL, ucp_Pattern_Syntax },+ { 2595, PT_BOOL, ucp_Pattern_White_Space },+ { 2613, PT_BOOL, ucp_Pattern_White_Space },+ { 2619, PT_SC, ucp_Pau_Cin_Hau },+ { 2624, PT_SC, ucp_Pau_Cin_Hau },+ { 2634, PT_PC, ucp_Pc },+ { 2637, PT_BOOL, ucp_Prepended_Concatenation_Mark },+ { 2641, PT_PC, ucp_Pd },+ { 2644, PT_PC, ucp_Pe },+ { 2647, PT_SCX, ucp_Old_Permic },+ { 2652, PT_PC, ucp_Pf },+ { 2655, PT_SCX, ucp_Phags_Pa },+ { 2660, PT_SCX, ucp_Phags_Pa },+ { 2668, PT_SC, ucp_Inscriptional_Pahlavi },+ { 2673, PT_SCX, ucp_Psalter_Pahlavi },+ { 2678, PT_SC, ucp_Phoenician },+ { 2683, PT_SC, ucp_Phoenician },+ { 2694, PT_PC, ucp_Pi },+ { 2697, PT_SC, ucp_Miao },+ { 2702, PT_PC, ucp_Po },+ { 2705, PT_BOOL, ucp_Prepended_Concatenation_Mark },+ { 2732, PT_SC, ucp_Inscriptional_Parthian },+ { 2737, PT_PC, ucp_Ps },+ { 2740, PT_SCX, ucp_Psalter_Pahlavi },+ { 2755, PT_SCX, ucp_Coptic },+ { 2760, PT_SC, ucp_Inherited },+ { 2765, PT_BOOL, ucp_Quotation_Mark },+ { 2771, PT_BOOL, ucp_Quotation_Mark },+ { 2785, PT_BOOL, ucp_Radical },+ { 2793, PT_BOOL, ucp_Regional_Indicator },+ { 2811, PT_SC, ucp_Rejang },+ { 2818, PT_BOOL, ucp_Regional_Indicator },+ { 2821, PT_SC, ucp_Rejang },+ { 2826, PT_SCX, ucp_Hanifi_Rohingya },+ { 2831, PT_SC, ucp_Runic },+ { 2837, PT_SC, ucp_Runic },+ { 2842, PT_GC, ucp_S },+ { 2844, PT_SC, ucp_Samaritan },+ { 2854, PT_SC, ucp_Samaritan },+ { 2859, PT_SC, ucp_Old_South_Arabian },+ { 2864, PT_SC, ucp_Saurashtra },+ { 2869, PT_SC, ucp_Saurashtra },+ { 2880, PT_PC, ucp_Sc },+ { 2883, PT_BOOL, ucp_Soft_Dotted },+ { 2886, PT_BOOL, ucp_Sentence_Terminal },+ { 2903, PT_SC, ucp_SignWriting }, { 2908, PT_SCX, ucp_Sharada },- { 2913, PT_SC, ucp_Siddham },- { 2918, PT_SC, ucp_Siddham },- { 2926, PT_SC, ucp_SignWriting },- { 2938, PT_SCX, ucp_Khudawadi },- { 2943, PT_SCX, ucp_Sinhala },- { 2948, PT_SCX, ucp_Sinhala },- { 2956, PT_PC, ucp_Sk },- { 2959, PT_PC, ucp_Sm },- { 2962, PT_PC, ucp_So },- { 2965, PT_BOOL, ucp_Soft_Dotted },- { 2976, PT_SCX, ucp_Sogdian },- { 2981, PT_SCX, ucp_Sogdian },- { 2989, PT_SC, ucp_Old_Sogdian },- { 2994, PT_SC, ucp_Sora_Sompeng },- { 2999, PT_SC, ucp_Sora_Sompeng },- { 3011, PT_SC, ucp_Soyombo },- { 3016, PT_SC, ucp_Soyombo },- { 3024, PT_BOOL, ucp_White_Space },- { 3030, PT_BOOL, ucp_Sentence_Terminal },- { 3036, PT_SC, ucp_Sundanese },- { 3041, PT_SC, ucp_Sundanese },- { 3051, PT_SCX, ucp_Syloti_Nagri },- { 3056, PT_SCX, ucp_Syloti_Nagri },- { 3068, PT_SCX, ucp_Syriac },- { 3073, PT_SCX, ucp_Syriac },- { 3080, PT_SCX, ucp_Tagalog },- { 3088, PT_SCX, ucp_Tagbanwa },- { 3093, PT_SCX, ucp_Tagbanwa },- { 3102, PT_SCX, ucp_Tai_Le },- { 3108, PT_SC, ucp_Tai_Tham },- { 3116, PT_SC, ucp_Tai_Viet },- { 3124, PT_SCX, ucp_Takri },- { 3129, PT_SCX, ucp_Takri },- { 3135, PT_SCX, ucp_Tai_Le },- { 3140, PT_SC, ucp_New_Tai_Lue },- { 3145, PT_SCX, ucp_Tamil },- { 3151, PT_SCX, ucp_Tamil },- { 3156, PT_SC, ucp_Tangut },- { 3161, PT_SC, ucp_Tangsa },- { 3168, PT_SC, ucp_Tangut },- { 3175, PT_SC, ucp_Tai_Viet },- { 3180, PT_SCX, ucp_Telugu },- { 3185, PT_SCX, ucp_Telugu },- { 3192, PT_BOOL, ucp_Terminal_Punctuation },- { 3197, PT_BOOL, ucp_Terminal_Punctuation },- { 3217, PT_SC, ucp_Tifinagh },- { 3222, PT_SCX, ucp_Tagalog },- { 3227, PT_SCX, ucp_Thaana },- { 3232, PT_SCX, ucp_Thaana },- { 3239, PT_SC, ucp_Thai },- { 3244, PT_SC, ucp_Tibetan },- { 3252, PT_SC, ucp_Tibetan },- { 3257, PT_SC, ucp_Tifinagh },- { 3266, PT_SCX, ucp_Tirhuta },- { 3271, PT_SCX, ucp_Tirhuta },- { 3279, PT_SC, ucp_Tangsa },- { 3284, PT_SC, ucp_Toto },- { 3289, PT_SC, ucp_Ugaritic },- { 3294, PT_SC, ucp_Ugaritic },- { 3303, PT_BOOL, ucp_Unified_Ideograph },- { 3309, PT_BOOL, ucp_Unified_Ideograph },- { 3326, PT_SC, ucp_Unknown },- { 3334, PT_BOOL, ucp_Uppercase },- { 3340, PT_BOOL, ucp_Uppercase },- { 3350, PT_SC, ucp_Vai },- { 3354, PT_SC, ucp_Vai },- { 3359, PT_BOOL, ucp_Variation_Selector },- { 3377, PT_SC, ucp_Vithkuqi },- { 3382, PT_SC, ucp_Vithkuqi },- { 3391, PT_BOOL, ucp_Variation_Selector },- { 3394, PT_SC, ucp_Wancho },- { 3401, PT_SC, ucp_Warang_Citi },- { 3406, PT_SC, ucp_Warang_Citi },- { 3417, PT_SC, ucp_Wancho },- { 3422, PT_BOOL, ucp_White_Space },- { 3433, PT_BOOL, ucp_White_Space },- { 3440, PT_ALNUM, 0 },- { 3444, PT_BOOL, ucp_XID_Continue },- { 3449, PT_BOOL, ucp_XID_Continue },- { 3461, PT_BOOL, ucp_XID_Start },- { 3466, PT_BOOL, ucp_XID_Start },- { 3475, PT_SC, ucp_Old_Persian },- { 3480, PT_PXSPACE, 0 },- { 3484, PT_SPACE, 0 },- { 3488, PT_SC, ucp_Cuneiform },- { 3493, PT_UCNC, 0 },- { 3497, PT_WORD, 0 },- { 3501, PT_SCX, ucp_Yezidi },- { 3506, PT_SCX, ucp_Yezidi },- { 3513, PT_SCX, ucp_Yi },- { 3516, PT_SCX, ucp_Yi },- { 3521, PT_GC, ucp_Z },- { 3523, PT_SC, ucp_Zanabazar_Square },- { 3539, PT_SC, ucp_Zanabazar_Square },- { 3544, PT_SC, ucp_Inherited },- { 3549, PT_PC, ucp_Zl },- { 3552, PT_PC, ucp_Zp },- { 3555, PT_PC, ucp_Zs },- { 3558, PT_SC, ucp_Common },- { 3563, PT_SC, ucp_Unknown }+ { 2916, PT_SC, ucp_Shavian },+ { 2924, PT_SC, ucp_Shavian },+ { 2929, PT_SCX, ucp_Sharada },+ { 2934, PT_SC, ucp_Siddham },+ { 2939, PT_SC, ucp_Siddham },+ { 2947, PT_SC, ucp_SignWriting },+ { 2959, PT_SCX, ucp_Khudawadi },+ { 2964, PT_SCX, ucp_Sinhala },+ { 2969, PT_SCX, ucp_Sinhala },+ { 2977, PT_PC, ucp_Sk },+ { 2980, PT_PC, ucp_Sm },+ { 2983, PT_PC, ucp_So },+ { 2986, PT_BOOL, ucp_Soft_Dotted },+ { 2997, PT_SCX, ucp_Sogdian },+ { 3002, PT_SCX, ucp_Sogdian },+ { 3010, PT_SC, ucp_Old_Sogdian },+ { 3015, PT_SC, ucp_Sora_Sompeng },+ { 3020, PT_SC, ucp_Sora_Sompeng },+ { 3032, PT_SC, ucp_Soyombo },+ { 3037, PT_SC, ucp_Soyombo },+ { 3045, PT_BOOL, ucp_White_Space },+ { 3051, PT_BOOL, ucp_Sentence_Terminal },+ { 3057, PT_SC, ucp_Sundanese },+ { 3062, PT_SC, ucp_Sundanese },+ { 3072, PT_SCX, ucp_Syloti_Nagri },+ { 3077, PT_SCX, ucp_Syloti_Nagri },+ { 3089, PT_SCX, ucp_Syriac },+ { 3094, PT_SCX, ucp_Syriac },+ { 3101, PT_SCX, ucp_Tagalog },+ { 3109, PT_SCX, ucp_Tagbanwa },+ { 3114, PT_SCX, ucp_Tagbanwa },+ { 3123, PT_SCX, ucp_Tai_Le },+ { 3129, PT_SC, ucp_Tai_Tham },+ { 3137, PT_SC, ucp_Tai_Viet },+ { 3145, PT_SCX, ucp_Takri },+ { 3150, PT_SCX, ucp_Takri },+ { 3156, PT_SCX, ucp_Tai_Le },+ { 3161, PT_SC, ucp_New_Tai_Lue },+ { 3166, PT_SCX, ucp_Tamil },+ { 3172, PT_SCX, ucp_Tamil },+ { 3177, PT_SC, ucp_Tangut },+ { 3182, PT_SC, ucp_Tangsa },+ { 3189, PT_SC, ucp_Tangut },+ { 3196, PT_SC, ucp_Tai_Viet },+ { 3201, PT_SCX, ucp_Telugu },+ { 3206, PT_SCX, ucp_Telugu },+ { 3213, PT_BOOL, ucp_Terminal_Punctuation },+ { 3218, PT_BOOL, ucp_Terminal_Punctuation },+ { 3238, PT_SC, ucp_Tifinagh },+ { 3243, PT_SCX, ucp_Tagalog },+ { 3248, PT_SCX, ucp_Thaana },+ { 3253, PT_SCX, ucp_Thaana },+ { 3260, PT_SC, ucp_Thai },+ { 3265, PT_SC, ucp_Tibetan },+ { 3273, PT_SC, ucp_Tibetan },+ { 3278, PT_SC, ucp_Tifinagh },+ { 3287, PT_SCX, ucp_Tirhuta },+ { 3292, PT_SCX, ucp_Tirhuta },+ { 3300, PT_SC, ucp_Tangsa },+ { 3305, PT_SC, ucp_Toto },+ { 3310, PT_SC, ucp_Ugaritic },+ { 3315, PT_SC, ucp_Ugaritic },+ { 3324, PT_BOOL, ucp_Unified_Ideograph },+ { 3330, PT_BOOL, ucp_Unified_Ideograph },+ { 3347, PT_SC, ucp_Unknown },+ { 3355, PT_BOOL, ucp_Uppercase },+ { 3361, PT_BOOL, ucp_Uppercase },+ { 3371, PT_SC, ucp_Vai },+ { 3375, PT_SC, ucp_Vai },+ { 3380, PT_BOOL, ucp_Variation_Selector },+ { 3398, PT_SC, ucp_Vithkuqi },+ { 3403, PT_SC, ucp_Vithkuqi },+ { 3412, PT_BOOL, ucp_Variation_Selector },+ { 3415, PT_SC, ucp_Wancho },+ { 3422, PT_SC, ucp_Warang_Citi },+ { 3427, PT_SC, ucp_Warang_Citi },+ { 3438, PT_SC, ucp_Wancho },+ { 3443, PT_BOOL, ucp_White_Space },+ { 3454, PT_BOOL, ucp_White_Space },+ { 3461, PT_ALNUM, 0 },+ { 3465, PT_BOOL, ucp_XID_Continue },+ { 3470, PT_BOOL, ucp_XID_Continue },+ { 3482, PT_BOOL, ucp_XID_Start },+ { 3487, PT_BOOL, ucp_XID_Start },+ { 3496, PT_SC, ucp_Old_Persian },+ { 3501, PT_PXSPACE, 0 },+ { 3505, PT_SPACE, 0 },+ { 3509, PT_SC, ucp_Cuneiform },+ { 3514, PT_UCNC, 0 },+ { 3518, PT_WORD, 0 },+ { 3522, PT_SCX, ucp_Yezidi },+ { 3527, PT_SCX, ucp_Yezidi },+ { 3534, PT_SCX, ucp_Yi },+ { 3537, PT_SCX, ucp_Yi },+ { 3542, PT_GC, ucp_Z },+ { 3544, PT_SC, ucp_Zanabazar_Square },+ { 3560, PT_SC, ucp_Zanabazar_Square },+ { 3565, PT_SC, ucp_Inherited },+ { 3570, PT_PC, ucp_Zl },+ { 3573, PT_PC, ucp_Zp },+ { 3576, PT_PC, ucp_Zs },+ { 3579, PT_SC, ucp_Common },+ { 3584, PT_SC, ucp_Unknown } }; const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
src/c/pcre2/src/pcre2_valid_utf.c view
@@ -171,7 +171,7 @@ if (((d = *(++p)) & 0xc0) != 0x80) {- *erroroffset = (int)(p - string) - 1;+ *erroroffset = (PCRE2_SIZE)(p - string) - 1; return PCRE2_ERROR_UTF8_ERR6; } @@ -186,7 +186,7 @@ case 1: if ((c & 0x3e) == 0) {- *erroroffset = (int)(p - string) - 1;+ *erroroffset = (PCRE2_SIZE)(p - string) - 1; return PCRE2_ERROR_UTF8_ERR15; } break;@@ -198,17 +198,17 @@ case 2: if ((*(++p) & 0xc0) != 0x80) /* Third byte */ {- *erroroffset = (int)(p - string) - 2;+ *erroroffset = (PCRE2_SIZE)(p - string) - 2; return PCRE2_ERROR_UTF8_ERR7; } if (c == 0xe0 && (d & 0x20) == 0) {- *erroroffset = (int)(p - string) - 2;+ *erroroffset = (PCRE2_SIZE)(p - string) - 2; return PCRE2_ERROR_UTF8_ERR16; } if (c == 0xed && d >= 0xa0) {- *erroroffset = (int)(p - string) - 2;+ *erroroffset = (PCRE2_SIZE)(p - string) - 2; return PCRE2_ERROR_UTF8_ERR14; } break;@@ -220,22 +220,22 @@ case 3: if ((*(++p) & 0xc0) != 0x80) /* Third byte */ {- *erroroffset = (int)(p - string) - 2;+ *erroroffset = (PCRE2_SIZE)(p - string) - 2; return PCRE2_ERROR_UTF8_ERR7; } if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ {- *erroroffset = (int)(p - string) - 3;+ *erroroffset = (PCRE2_SIZE)(p - string) - 3; return PCRE2_ERROR_UTF8_ERR8; } if (c == 0xf0 && (d & 0x30) == 0) {- *erroroffset = (int)(p - string) - 3;+ *erroroffset = (PCRE2_SIZE)(p - string) - 3; return PCRE2_ERROR_UTF8_ERR17; } if (c > 0xf4 || (c == 0xf4 && d > 0x8f)) {- *erroroffset = (int)(p - string) - 3;+ *erroroffset = (PCRE2_SIZE)(p - string) - 3; return PCRE2_ERROR_UTF8_ERR13; } break;@@ -251,22 +251,22 @@ case 4: if ((*(++p) & 0xc0) != 0x80) /* Third byte */ {- *erroroffset = (int)(p - string) - 2;+ *erroroffset = (PCRE2_SIZE)(p - string) - 2; return PCRE2_ERROR_UTF8_ERR7; } if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ {- *erroroffset = (int)(p - string) - 3;+ *erroroffset = (PCRE2_SIZE)(p - string) - 3; return PCRE2_ERROR_UTF8_ERR8; } if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */ {- *erroroffset = (int)(p - string) - 4;+ *erroroffset = (PCRE2_SIZE)(p - string) - 4; return PCRE2_ERROR_UTF8_ERR9; } if (c == 0xf8 && (d & 0x38) == 0) {- *erroroffset = (int)(p - string) - 4;+ *erroroffset = (PCRE2_SIZE)(p - string) - 4; return PCRE2_ERROR_UTF8_ERR18; } break;@@ -277,27 +277,27 @@ case 5: if ((*(++p) & 0xc0) != 0x80) /* Third byte */ {- *erroroffset = (int)(p - string) - 2;+ *erroroffset = (PCRE2_SIZE)(p - string) - 2; return PCRE2_ERROR_UTF8_ERR7; } if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ {- *erroroffset = (int)(p - string) - 3;+ *erroroffset = (PCRE2_SIZE)(p - string) - 3; return PCRE2_ERROR_UTF8_ERR8; } if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */ {- *erroroffset = (int)(p - string) - 4;+ *erroroffset = (PCRE2_SIZE)(p - string) - 4; return PCRE2_ERROR_UTF8_ERR9; } if ((*(++p) & 0xc0) != 0x80) /* Sixth byte */ {- *erroroffset = (int)(p - string) - 5;+ *erroroffset = (PCRE2_SIZE)(p - string) - 5; return PCRE2_ERROR_UTF8_ERR10; } if (c == 0xfc && (d & 0x3c) == 0) {- *erroroffset = (int)(p - string) - 5;+ *erroroffset = (PCRE2_SIZE)(p - string) - 5; return PCRE2_ERROR_UTF8_ERR19; } break;@@ -309,7 +309,7 @@ if (ab > 3) {- *erroroffset = (int)(p - string) - ab;+ *erroroffset = (PCRE2_SIZE)(p - string) - ab; return (ab == 4)? PCRE2_ERROR_UTF8_ERR11 : PCRE2_ERROR_UTF8_ERR12; } }@@ -340,21 +340,21 @@ /* High surrogate. Must be a followed by a low surrogate. */ if (length == 0) {- *erroroffset = p - string;+ *erroroffset = (PCRE2_SIZE)(p - string); return PCRE2_ERROR_UTF16_ERR1; } p++; length--; if ((*p & 0xfc00) != 0xdc00) {- *erroroffset = p - string - 1;+ *erroroffset = (PCRE2_SIZE)(p - string) - 1; return PCRE2_ERROR_UTF16_ERR2; } } else { /* Isolated low surrogate. Always an error. */- *erroroffset = p - string;+ *erroroffset = (PCRE2_SIZE)(p - string); return PCRE2_ERROR_UTF16_ERR3; } }@@ -379,14 +379,14 @@ /* Normal UTF-32 code point. Neither high nor low surrogate. */ if (c > 0x10ffffu) {- *erroroffset = p - string;+ *erroroffset = (PCRE2_SIZE)(p - string); return PCRE2_ERROR_UTF32_ERR2; } } else { /* A surrogate */- *erroroffset = p - string;+ *erroroffset = (PCRE2_SIZE)(p - string); return PCRE2_ERROR_UTF32_ERR1; } }
src/c/pcre2/src/pcre2_xclass.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2022 University of Cambridge+ New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -133,6 +133,7 @@ #ifdef SUPPORT_UNICODE else /* XCL_PROP & XCL_NOTPROP */ {+ int chartype; const ucd_record *prop = GET_UCD(c); BOOL isprop = t == XCL_PROP; BOOL ok;@@ -144,8 +145,9 @@ break; case PT_LAMP:- if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||- prop->chartype == ucp_Lt) == isprop) return !negated;+ chartype = prop->chartype;+ if ((chartype == ucp_Lu || chartype == ucp_Ll ||+ chartype == ucp_Lt) == isprop) return !negated; break; case PT_GC:@@ -168,8 +170,9 @@ break; case PT_ALNUM:- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N) == isprop)+ chartype = prop->chartype;+ if ((PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N) == isprop) return !negated; break; @@ -194,9 +197,10 @@ break; case PT_WORD:- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||- PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)- == isprop)+ chartype = prop->chartype;+ if ((PRIV(ucp_gentype)[chartype] == ucp_L ||+ PRIV(ucp_gentype)[chartype] == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc) == isprop) return !negated; break; @@ -238,9 +242,10 @@ */ case PT_PXGRAPH:- if ((PRIV(ucp_gentype)[prop->chartype] != ucp_Z &&- (PRIV(ucp_gentype)[prop->chartype] != ucp_C ||- (prop->chartype == ucp_Cf &&+ chartype = prop->chartype;+ if ((PRIV(ucp_gentype)[chartype] != ucp_Z &&+ (PRIV(ucp_gentype)[chartype] != ucp_C ||+ (chartype == ucp_Cf && c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069)) )) == isprop) return !negated;@@ -250,10 +255,11 @@ not Zl and not Zp, and U+180E. */ case PT_PXPRINT:- if ((prop->chartype != ucp_Zl &&- prop->chartype != ucp_Zp &&- (PRIV(ucp_gentype)[prop->chartype] != ucp_C ||- (prop->chartype == ucp_Cf &&+ chartype = prop->chartype;+ if ((chartype != ucp_Zl &&+ chartype != ucp_Zp &&+ (PRIV(ucp_gentype)[chartype] != ucp_C ||+ (chartype == ucp_Cf && c != 0x061c && (c < 0x2066 || c > 0x2069)) )) == isprop) return !negated;@@ -264,8 +270,21 @@ compatibility (these are $+<=>^`|~). */ case PT_PXPUNCT:- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_P ||- (c < 128 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop)+ chartype = prop->chartype;+ if ((PRIV(ucp_gentype)[chartype] == ucp_P ||+ (c < 128 && PRIV(ucp_gentype)[chartype] == ucp_S)) == isprop)+ return !negated;+ break;++ /* Perl has two sets of hex digits */++ case PT_PXXDIGIT:+ if (((c >= CHAR_0 && c <= CHAR_9) ||+ (c >= CHAR_A && c <= CHAR_F) ||+ (c >= CHAR_a && c <= CHAR_f) ||+ (c >= 0xff10 && c <= 0xff19) || /* Fullwidth digits */+ (c >= 0xff21 && c <= 0xff26) || /* Fullwidth letters */+ (c >= 0xff41 && c <= 0xff46)) == isprop) return !negated; break;
src/c/pcre2/src/pcre2grep.c view
@@ -13,7 +13,7 @@ The header can be found in the special z/OS distribution, which is available from www.zaconsultants.net or from www.cbttape.org. - Copyright (c) 1997-2020 University of Cambridge+ Copyright (c) 1997-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -205,34 +205,37 @@ * Global variables * *************************************************/ -/* Jeffrey Friedl has some debugging requirements that are not part of the-regular code. */- static const char *colour_string = "1;31"; static const char *colour_option = NULL; static const char *dee_option = NULL; static const char *DEE_option = NULL; static const char *locale = NULL; static const char *newline_arg = NULL;+static const char *group_separator = "--"; static const char *om_separator = NULL; static const char *stdin_name = "(standard input)"; static const char *output_text = NULL; static char *main_buffer = NULL; +static const char *printname_nl = STDOUT_NL; /* Changed to NULL for -Z */+static int printname_colon = ':'; /* Changed to 0 for -Z */+static int printname_hyphen = '-'; /* Changed to 0 for -Z */+ static int after_context = 0; static int before_context = 0; static int binary_files = BIN_BINARY; static int both_context = 0;-static int bufthird = PCRE2GREP_BUFSIZE;-static int max_bufthird = PCRE2GREP_MAX_BUFSIZE;-static int bufsize = 3*PCRE2GREP_BUFSIZE; static int endlinetype; static int count_limit = -1; /* Not long, so that it works with OP_NUMBER */ static unsigned long int counts_printed = 0; static unsigned long int total_count = 0; +static PCRE2_SIZE bufthird = PCRE2GREP_BUFSIZE;+static PCRE2_SIZE max_bufthird = PCRE2GREP_MAX_BUFSIZE;+static PCRE2_SIZE bufsize = 3*PCRE2GREP_BUFSIZE;+ #ifdef WIN32 static int dee_action = dee_SKIP; #else@@ -259,11 +262,14 @@ static pcre2_compile_context *compile_context; static pcre2_match_context *match_context;-static pcre2_match_data *match_data;-static PCRE2_SIZE *offsets;+static pcre2_match_data *match_data, *match_data_pair[2];+static PCRE2_SIZE *offsets, *offsets_pair[2];+static int match_data_toggle; static uint32_t offset_size; static uint32_t capture_max = DEFAULT_CAPTURE_MAX; +static BOOL all_matches = FALSE;+static BOOL case_restrict = FALSE; static BOOL count_only = FALSE; static BOOL do_colour = FALSE; #ifdef WIN32@@ -275,6 +281,7 @@ static BOOL line_buffered = FALSE; static BOOL line_offsets = FALSE; static BOOL multiline = FALSE;+static BOOL no_ucp = FALSE; static BOOL number = FALSE; static BOOL omit_zero_count = FALSE; static BOOL resource_error = FALSE;@@ -282,6 +289,7 @@ static BOOL show_total_count = FALSE; static BOOL silent = FALSE; static BOOL utf = FALSE;+static BOOL posix_digit = FALSE; static uint8_t utf8_buffer[8]; @@ -417,6 +425,9 @@ #define N_MAX_BUFSIZE (-23) #define N_OM_CAPTURE (-24) #define N_ALLABSK (-25)+#define N_POSIX_DIGIT (-26)+#define N_GROUP_SEPARATOR (-27)+#define N_NO_GROUP_SEPARATOR (-28) static option_item optionlist[] = { { OP_NODATA, N_NULL, NULL, "", "terminate options" },@@ -425,19 +436,22 @@ { OP_NODATA, 'a', NULL, "text", "treat binary files as text" }, { OP_NUMBER, 'B', &before_context, "before-context=number", "set number of prior context lines" }, { OP_BINFILES, N_BINARY_FILES, NULL, "binary-files=word", "set treatment of binary files" },- { OP_NUMBER, N_BUFSIZE,&bufthird, "buffer-size=number", "set processing buffer starting size" },- { OP_NUMBER, N_MAX_BUFSIZE,&max_bufthird, "max-buffer-size=number", "set processing buffer maximum size" },+ { OP_SIZE, N_BUFSIZE,&bufthird, "buffer-size=number", "set processing buffer starting size" },+ { OP_SIZE, N_MAX_BUFSIZE,&max_bufthird, "max-buffer-size=number", "set processing buffer maximum size" }, { OP_OP_STRING, N_COLOUR, &colour_option, "color=option", "matched text color option" }, { OP_OP_STRING, N_COLOUR, &colour_option, "colour=option", "matched text colour option" }, { OP_NUMBER, 'C', &both_context, "context=number", "set number of context lines, before & after" }, { OP_NODATA, 'c', NULL, "count", "print only a count of matching lines per FILE" }, { OP_STRING, 'D', &DEE_option, "devices=action","how to handle devices, FIFOs, and sockets" }, { OP_STRING, 'd', &dee_option, "directories=action", "how to handle directories" },+ { OP_NODATA, N_POSIX_DIGIT, NULL, "posix-digit", "\\d always matches [0-9], even in UTF/UCP mode" },+ { OP_NODATA, 'E', NULL, "case-restrict", "restrict case matching (no mix ASCII/non-ASCII)" }, { OP_PATLIST, 'e', &match_patdata, "regex(p)=pattern", "specify pattern (may be used more than once)" }, { OP_NODATA, 'F', NULL, "fixed-strings", "patterns are sets of newline-separated strings" }, { OP_FILELIST, 'f', &pattern_files_data, "file=path", "read patterns from file" }, { OP_FILELIST, N_FILE_LIST, &file_lists_data, "file-list=path","read files to search from file" }, { OP_NODATA, N_FOFFSETS, NULL, "file-offsets", "output file offsets, not text" },+ { OP_STRING, N_GROUP_SEPARATOR, &group_separator, "group-separator=text", "set separator between groups of lines" }, { OP_NODATA, 'H', NULL, "with-filename", "force the prefixing filename on output" }, { OP_NODATA, 'h', NULL, "no-filename", "suppress the prefixing filename on output" }, { OP_NODATA, 'I', NULL, "", "treat binary files as not matching (ignore)" },@@ -461,10 +475,12 @@ #else { OP_NODATA, N_NOJIT, NULL, "no-jit", "ignored: this pcre2grep does not support JIT" }, #endif+ { OP_NODATA, N_NO_GROUP_SEPARATOR, NULL, "no-group-separator", "suppress separators between groups of lines" }, { OP_STRING, 'O', &output_text, "output=text", "show only this text (possibly expanded)" }, { OP_OP_NUMBERS, 'o', &only_matching_data, "only-matching=n", "show only the part of the line that matched" }, { OP_STRING, N_OM_SEPARATOR, &om_separator, "om-separator=text", "set separator for multiple -o output" }, { OP_U32NUMBER, N_OM_CAPTURE, &capture_max, "om-capture=n", "set capture count for --only-matching" },+ { OP_NODATA, 'P', NULL, "no-ucp", "do not enable UCP mode with Unicode" }, { OP_NODATA, 'q', NULL, "quiet", "suppress output, just set return code" }, { OP_NODATA, 'r', NULL, "recursive", "recursively scan sub-directories" }, { OP_PATLIST, N_EXCLUDE,&exclude_patdata, "exclude=pattern","exclude matching files when recursing" },@@ -475,13 +491,14 @@ { OP_FILELIST, N_INCLUDE_FROM,&include_from_data, "include-from=path", "read include list from file" }, { OP_NODATA, 's', NULL, "no-messages", "suppress error messages" }, { OP_NODATA, 't', NULL, "total-count", "print total count of matching lines" },- { OP_NODATA, 'u', NULL, "utf", "use UTF mode" },- { OP_NODATA, 'U', NULL, "utf-allow-invalid", "use UTF mode, allow for invalid code units" },+ { OP_NODATA, 'u', NULL, "utf", "use UTF/Unicode" },+ { OP_NODATA, 'U', NULL, "utf-allow-invalid", "use UTF/Unicode, allow for invalid code units" }, { OP_NODATA, 'V', NULL, "version", "print version information and exit" }, { OP_NODATA, 'v', NULL, "invert-match", "select non-matching lines" }, { OP_NODATA, 'w', NULL, "word-regex(p)", "force patterns to match only as words" }, { OP_NODATA, 'x', NULL, "line-regex(p)", "force patterns to match only whole lines" }, { OP_NODATA, N_ALLABSK, NULL, "allow-lookaround-bsk", "allow \\K in lookarounds" },+ { OP_NODATA, 'Z', NULL, "null", "output 0 byte after file names" }, { OP_NODATA, 0, NULL, NULL, NULL } }; @@ -675,6 +692,9 @@ add_pattern(char *s, PCRE2_SIZE patlen, patstr *after) { patstr *p = (patstr *)malloc(sizeof(patstr));++/* LCOV_EXCL_START - These won't be hit in normal testing. */+ if (p == NULL) { fprintf(stderr, "pcre2grep: malloc failed\n");@@ -687,6 +707,9 @@ free(p); return NULL; }++/* LCOV_EXCL_STOP */+ p->next = NULL; p->string = s; p->length = patlen;@@ -766,7 +789,7 @@ #define iswild(name) (strpbrk(name, "*?") != NULL) /* Convert ANSI BGR format to RGB used by Windows */-#define BGR_RGB(x) ((x & 1 ? 4 : 0) | (x & 2) | (x & 4 ? 1 : 0))+#define BGR_RGB(x) (((x) & 1 ? 4 : 0) | ((x) & 2) | ((x) & 4 ? 1 : 0)) static HANDLE hstdout; static CONSOLE_SCREEN_BUFFER_INFO csbi;@@ -778,7 +801,7 @@ WORD result = csbi.wAttributes; while (*cs) {- if (isdigit(*cs))+ if (isdigit((unsigned char)(*cs))) { int code = atoi(cs); if (code == 1) result |= 0x08;@@ -792,7 +815,7 @@ else if (code >= 90 && code <= 97) result = (result & 0xF0) | BGR_RGB(code - 90) | 0x08; else if (code >= 100 && code <= 107) result = (result & 0x0F) | (BGR_RGB(code - 100) << 4) | 0x80; - while (isdigit(*cs)) cs++;+ while (isdigit((unsigned char)(*cs))) cs++; } if (*cs) cs++; }@@ -1368,11 +1391,16 @@ { omstr *om = (omstr *)malloc(sizeof(omstr)); +/* LCOV_EXCL_START - These lines won't be hit in normal testing. */+ if (om == NULL) { fprintf(stderr, "pcre2grep: malloc failed\n"); pcre2grep_exit(2); }++/* LCOV_EXCL_STOP */+ om->next = NULL; om->groupnum = n; @@ -1408,10 +1436,10 @@ */ static PCRE2_SIZE-read_one_line(char *buffer, int length, FILE *f)+read_one_line(char *buffer, PCRE2_SIZE length, FILE *f) { int c;-int yield = 0;+PCRE2_SIZE yield = 0; while ((c = fgetc(f)) != EOF) { buffer[yield++] = c;@@ -1772,7 +1800,7 @@ { char *pp = end_of_line(lastmatchrestart, endptr, &ellength); if (ellength == 0 && pp == main_buffer + bufsize) break;- if (printname != NULL) fprintf(stdout, "%s-", printname);+ if (printname != NULL) fprintf(stdout, "%s%c", printname, printname_hyphen); if (number) fprintf(stdout, "%lu-", lastmatchnumber++); FWRITE_IGNORE(lastmatchrestart, 1, pp - lastmatchrestart, stdout); lastmatchrestart = pp;@@ -1798,9 +1826,10 @@ * Apply patterns to subject till one matches * *************************************************/ -/* This function is called to run through all patterns, looking for a match. It-is used multiple times for the same subject when colouring is enabled, in order-to find all possible matches.+/* This function is called to run through all the patterns, looking for a+match. When all possible matches are required, for example, for colouring, it+checks all patterns for matching, and returns the earliest match. Otherwise, it+returns the first pattern that has matched. Arguments: matchptr the start of the subject@@ -1809,17 +1838,18 @@ startoffset where to start matching mrc address of where to put the result of pcre2_match() -Returns: TRUE if there was a match- FALSE if there was no match- invert if there was a non-fatal error+Returns: TRUE if there was a match, match_data and offsets are set+ FALSE if there was no match (but no errors)+ invert if there was a non-fatal error */ static BOOL match_patterns(char *matchptr, PCRE2_SIZE length, unsigned int options, PCRE2_SIZE startoffset, int *mrc) {-int i; PCRE2_SIZE slen = length;+int first = -1;+int firstrc = 0; patstr *p = patterns; const char *msg = "this text:\n\n"; @@ -1829,27 +1859,53 @@ msg = "text that starts:\n\n"; } -for (i = 1; p != NULL; p = p->next, i++)+for (int i = 1; p != NULL; p = p->next, i++) {- *mrc = pcre2_match(p->compiled, (PCRE2_SPTR)matchptr, (int)length,+ int rc = pcre2_match(p->compiled, (PCRE2_SPTR)matchptr, length, startoffset, options, match_data, match_context);- if (*mrc >= 0) return TRUE;- if (*mrc == PCRE2_ERROR_NOMATCH) continue;- fprintf(stderr, "pcre2grep: pcre2_match() gave error %d while matching ", *mrc);+ if (rc == PCRE2_ERROR_NOMATCH) continue;++ /* Handle a successful match. When all_matches is false, we are done.+ Otherwise we must save the earliest match. */++ if (rc >= 0)+ {+ if (!all_matches)+ {+ *mrc = rc;+ return TRUE;+ }++ if (first < 0 || offsets[0] < offsets_pair[first][0] ||+ (offsets[0] == offsets_pair[first][0] &&+ offsets[1] > offsets_pair[first][1]))+ {+ first = match_data_toggle;+ firstrc = rc;+ match_data_toggle ^= 1;+ match_data = match_data_pair[match_data_toggle];+ offsets = offsets_pair[match_data_toggle];+ }+ continue;+ }++ /* Deal with PCRE2 error. */++ fprintf(stderr, "pcre2grep: pcre2_match() gave error %d while matching ", rc); if (patterns->next != NULL) fprintf(stderr, "pattern number %d to ", i); fprintf(stderr, "%s", msg); FWRITE_IGNORE(matchptr, 1, slen, stderr); /* In case binary zero included */ fprintf(stderr, "\n\n");- if (*mrc <= PCRE2_ERROR_UTF8_ERR1 &&- *mrc >= PCRE2_ERROR_UTF8_ERR21)+ if (rc <= PCRE2_ERROR_UTF8_ERR1 &&+ rc >= PCRE2_ERROR_UTF8_ERR21) { unsigned char mbuffer[256]; PCRE2_SIZE startchar = pcre2_get_startchar(match_data);- (void)pcre2_get_error_message(*mrc, mbuffer, sizeof(mbuffer));+ (void)pcre2_get_error_message(rc, mbuffer, sizeof(mbuffer)); fprintf(stderr, "%s at offset %" SIZ_FORM "\n\n", mbuffer, startchar); }- if (*mrc == PCRE2_ERROR_MATCHLIMIT || *mrc == PCRE2_ERROR_DEPTHLIMIT ||- *mrc == PCRE2_ERROR_HEAPLIMIT || *mrc == PCRE2_ERROR_JIT_STACKLIMIT)+ if (rc == PCRE2_ERROR_MATCHLIMIT || rc == PCRE2_ERROR_DEPTHLIMIT ||+ rc == PCRE2_ERROR_HEAPLIMIT || rc == PCRE2_ERROR_JIT_STACKLIMIT) resource_error = TRUE; if (error_count++ > 20) {@@ -1859,7 +1915,18 @@ return invert; /* No more matching; don't show the line again */ } -return FALSE; /* No match, no errors */+/* We get here when all patterns have been tried. If all_matches is false,+this means that none of them matched. If all_matches is true, matched_first+will be non-NULL if there was at least one match, and it will point to the+appropriate match_data block. */++if (!all_matches || first < 0) return FALSE;++match_data_toggle = first;+match_data = match_data_pair[first];+offsets = offsets_pair[first];+*mrc = firstrc;+return TRUE; } @@ -1927,7 +1994,7 @@ case '{': brace = TRUE; string++;- if (!isdigit(*string)) /* Syntax error: a decimal number required. */+ if (!isdigit((unsigned char)(*string))) /* Syntax error: a decimal number required. */ { if (!callout) fprintf(stderr, "pcre2grep: Error in output text at offset %d: %s\n",@@ -2160,18 +2227,19 @@ } continue; + /* LCOV_EXCL_START */ default: /* Should not occur */ break;+ /* LCOV_EXCL_STOP */ } } else value = *string; /* Not a $ escape */ - if (utf && value <= 127) fprintf(stdout, "%c", *string); else+ if (!utf || value <= 127) fprintf(stdout, "%c", value); else {- int i; int n = ord2utf8(value);- for (i = 0; i < n; i++) fputc(utf8_buffer[i], stdout);+ for (int i = 0; i < n; i++) fputc(utf8_buffer[i], stdout); } printed = TRUE;@@ -2303,9 +2371,11 @@ else if (utf && value > 127) argslen += ord2utf8(value) - 1; break; + /* LCOV_EXCL_START */ default: /* Should not occur */ case DDE_ERROR: return 0;+ /* LCOV_EXCL_STOP */ } length -= (string - begin);@@ -2324,8 +2394,10 @@ argsvector = (char**)malloc(argsvectorlen * sizeof(char*)); if (argsvector == NULL) {+ /* LCOV_EXCL_START */ free(args); return 0;+ /* LCOV_EXCL_STOP */ } /* Now reprocess the string and set up the arguments. */@@ -2381,11 +2453,13 @@ } break; + /* LCOV_EXCL_START */ default: /* Even though this should not occur, the string having */ case DDE_ERROR: /* been checked above, we need to include the free() */ free(args); /* calls so that source checkers do not complain. */ free(argsvector); return 0;+ /* LCOV_EXCL_STOP */ } length -= (string - begin);@@ -2437,7 +2511,11 @@ exit(1); } else if (pid > 0)+ {+ (void)fflush(stdout); (void)waitpid(pid, &result, 0);+ (void)fflush(stdout);+ } #endif /* End Windows/VMS/other handling */ free(args);@@ -2457,8 +2535,8 @@ * Read a portion of the file into buffer * *************************************************/ -static int-fill_buffer(void *handle, int frtype, char *buffer, int length,+static PCRE2_SIZE+fill_buffer(void *handle, int frtype, char *buffer, PCRE2_SIZE length, BOOL input_line_buffered) { (void)frtype; /* Avoid warning when not used */@@ -2471,7 +2549,7 @@ #ifdef SUPPORT_LIBBZ2 if (frtype == FR_LIBBZ2)- return BZ2_bzread((BZFILE *)handle, buffer, length);+ return (PCRE2_SIZE)BZ2_bzread((BZFILE *)handle, buffer, length); else #endif @@ -2537,10 +2615,8 @@ if (frtype != FR_LIBZ && frtype != FR_LIBBZ2) { in = (FILE *)handle;- if (feof(in))- return 1;- if (is_file_tty(in))- input_line_buffered = TRUE;+ if (feof(in)) return 1;+ if (is_file_tty(in)) input_line_buffered = TRUE; else { if (count_limit >= 0 && filename == stdin_name)@@ -2553,7 +2629,7 @@ input_line_buffered); #ifdef SUPPORT_LIBBZ2-if (frtype == FR_LIBBZ2 && (int)bufflength < 0) return 2; /* Gotcha: bufflength is PCRE2_SIZE */+if (frtype == FR_LIBBZ2 && (int)bufflength < 0) return 3; /* Gotcha: bufflength is PCRE2_SIZE */ #endif endptr = main_buffer + bufflength;@@ -2620,21 +2696,24 @@ if (bufthird < max_bufthird) { char *new_buffer;- int new_bufthird = 2*bufthird;+ PCRE2_SIZE new_bufthird = 2*bufthird; if (new_bufthird > max_bufthird) new_bufthird = max_bufthird; new_buffer = (char *)malloc(3*new_bufthird); if (new_buffer == NULL) {+ /* LCOV_EXCL_START */ fprintf(stderr, "pcre2grep: line %lu%s%s is too long for the internal buffer\n"- "pcre2grep: not enough memory to increase the buffer size to %d\n",+ "pcre2grep: not enough memory to increase the buffer size to %"+ SIZ_FORM "\n", linenumber, (filename == NULL)? "" : " of file ", (filename == NULL)? "" : filename, new_bufthird); return 2;+ /* LCOV_EXCL_STOP */ } /* Copy the data and adjust pointers to the new buffer location. */@@ -2659,7 +2738,7 @@ { fprintf(stderr, "pcre2grep: line %lu%s%s is too long for the internal buffer\n"- "pcre2grep: the maximum buffer size is %d\n"+ "pcre2grep: the maximum buffer size is %" SIZ_FORM "\n" "pcre2grep: use the --max-buffer-size option to change it\n", linenumber, (filename == NULL)? "" : " of file ",@@ -2724,7 +2803,9 @@ else if (filenames == FN_MATCH_ONLY) {- fprintf(stdout, "%s" STDOUT_NL, printname);+ fprintf(stdout, "%s", printname);+ if (printname_nl == NULL) fprintf(stdout, "%c", 0);+ else fprintf(stdout, "%s", printname_nl); return 0; } @@ -2743,7 +2824,8 @@ { PCRE2_SIZE oldstartoffset; - if (printname != NULL) fprintf(stdout, "%s:", printname);+ if (printname != NULL) fprintf(stdout, "%s%c", printname,+ printname_colon); if (number) fprintf(stdout, "%lu:", linenumber); /* Handle --line-offsets */@@ -2763,10 +2845,9 @@ else if (output_text != NULL) {- if (display_output_text((PCRE2_SPTR)output_text, FALSE,- (PCRE2_SPTR)ptr, offsets, mrc) || printname != NULL ||- number)- fprintf(stdout, STDOUT_NL);+ (void)display_output_text((PCRE2_SPTR)output_text, FALSE,+ (PCRE2_SPTR)ptr, offsets, mrc);+ fprintf(stdout, STDOUT_NL); } /* Handle --only-matching, which may occur many times */@@ -2791,14 +2872,13 @@ } } }- if (printed || printname != NULL || number) fprintf(stdout, STDOUT_NL); } /* Prepare to repeat to find the next match in the line. */ - match = FALSE;+ //match = FALSE; if (line_buffered) fflush(stdout); rc = 0; /* Had some success */ @@ -2865,7 +2945,8 @@ while (lastmatchrestart < p) { char *pp = lastmatchrestart;- if (printname != NULL) fprintf(stdout, "%s-", printname);+ if (printname != NULL) fprintf(stdout, "%s%c", printname,+ printname_hyphen); if (number) fprintf(stdout, "%lu-", lastmatchnumber++); pp = end_of_line(pp, endptr, &ellength); FWRITE_IGNORE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);@@ -2878,7 +2959,8 @@ if (hyphenpending) {- fprintf(stdout, "--" STDOUT_NL);+ if (group_separator != NULL)+ fprintf(stdout, "%s%s", group_separator, STDOUT_NL); hyphenpending = FALSE; hyphenprinted = TRUE; }@@ -2899,14 +2981,16 @@ p = previous_line(p, main_buffer); } - if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)- fprintf(stdout, "--" STDOUT_NL);+ if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted &&+ group_separator != NULL)+ fprintf(stdout, "%s%s", group_separator, STDOUT_NL); while (p < ptr) { int ellength; char *pp = p;- if (printname != NULL) fprintf(stdout, "%s-", printname);+ if (printname != NULL) fprintf(stdout, "%s%c", printname,+ printname_hyphen); if (number) fprintf(stdout, "%lu-", linenumber - linecount--); pp = end_of_line(pp, endptr, &ellength); FWRITE_IGNORE(p, 1, pp - p, stdout);@@ -2920,7 +3004,8 @@ if (after_context > 0 || before_context > 0) endhyphenpending = TRUE; - if (printname != NULL) fprintf(stdout, "%s:", printname);+ if (printname != NULL) fprintf(stdout, "%s%c", printname,+ printname_colon); if (number) fprintf(stdout, "%lu:", linenumber); /* In multiline mode, or if colouring, we have to split the line(s) up@@ -3076,7 +3161,7 @@ if (input_line_buffered && bufflength < (PCRE2_SIZE)bufsize) {- int add = read_one_line(ptr, bufsize - (int)(ptr - main_buffer), in);+ PCRE2_SIZE add = read_one_line(ptr, bufsize - (ptr - main_buffer), in); bufflength += add; endptr += add; }@@ -3125,7 +3210,9 @@ if (filenames == FN_NOMATCH_ONLY) {- fprintf(stdout, "%s" STDOUT_NL, printname);+ fprintf(stdout, "%s", printname);+ if (printname_nl == NULL) fprintf(stdout, "%c", 0);+ else fprintf(stdout, "%s", printname_nl); return 0; } @@ -3136,7 +3223,7 @@ if (count > 0 || !omit_zero_count) { if (printname != NULL && filenames != FN_NONE)- fprintf(stdout, "%s:", printname);+ fprintf(stdout, "%s%c", printname, printname_colon); fprintf(stdout, "%lu" STDOUT_NL, count); counts_printed++; }@@ -3268,10 +3355,12 @@ if (dir == NULL) {+ /* LCOV_EXCL_START - this is a "never" event */ if (!silent) fprintf(stderr, "pcre2grep: Failed to open directory %s: %s\n", pathname, strerror(errno)); return 2;+ /* LCOV_EXCL_STOP */ } while ((nextfile = readdirectory(dir)) != NULL)@@ -3280,9 +3369,11 @@ int fnlength = strlen(pathname) + strlen(nextfile) + 2; if (fnlength > FNBUFSIZ) {+ /* LCOV_EXCL_START - this is a "never" event */ fprintf(stderr, "pcre2grep: recursive filename is too long\n"); rc = 2; break;+ /* LCOV_EXCL_STOP */ } sprintf(childpath, "%s%c%s", pathname, FILESEP, nextfile); @@ -3299,7 +3390,9 @@ BOOL isSame; size_t rlen; if (realpath(childpath, resolvedpath) == NULL)+ /* LCOV_EXCL_START - this is a "never" event */ continue; /* This path is invalid - we can skip processing this */+ /* LCOV_EXCL_STOP */ isSame = strcmp(pathname, resolvedpath) == 0; if (isSame) continue; /* We have a recursion */ rlen = strlen(resolvedpath);@@ -3388,10 +3481,12 @@ ingz = gzopen(pathname, "rb"); if (ingz == NULL) {+ /* LCOV_EXCL_START */ if (!silent) fprintf(stderr, "pcre2grep: Failed to open %s: %s\n", pathname, strerror(errno)); return 2;+ /* LCOV_EXCL_STOP */ } handle = (void *)ingz; frtype = FR_LIBZ;@@ -3462,10 +3557,12 @@ BZ2_bzclose(inbz2); goto PLAIN_FILE; }+ /* LCOV_EXCL_START */ else if (!silent) fprintf(stderr, "pcre2grep: Failed to read %s using bzlib: %s\n", pathname, err); rc = 2; /* The normal "something went wrong" code */+ /* LCOV_EXCL_STOP */ } BZ2_bzclose(inbz2); }@@ -3487,6 +3584,8 @@ * Handle a no-data option * *************************************************/ +/* This is called when a known option has been identified. */+ static int handle_option(int letter, int options) {@@ -3498,8 +3597,11 @@ case N_LOFFSETS: line_offsets = number = TRUE; break; case N_NOJIT: use_jit = FALSE; break; case N_ALLABSK: extra_options |= PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK; break;+ case N_NO_GROUP_SEPARATOR: group_separator = NULL; break; case 'a': binary_files = BIN_TEXT; break; case 'c': count_only = TRUE; break;+ case N_POSIX_DIGIT: posix_digit = TRUE; break;+ case 'E': case_restrict = TRUE; break; case 'F': options |= PCRE2_LITERAL; break; case 'H': filenames = FN_FORCE; break; case 'I': binary_files = BIN_NOMATCH; break;@@ -3515,15 +3617,15 @@ if (only_matching == NULL) only_matching = only_matching_last; break; + case 'P': no_ucp = TRUE; break; case 'q': quiet = TRUE; break; case 'r': dee_action = dee_RECURSE; break; case 's': silent = TRUE; break; case 't': show_total_count = TRUE; break;- case 'u': options |= PCRE2_UTF; utf = TRUE; break;- case 'U': options |= PCRE2_UTF|PCRE2_MATCH_INVALID_UTF; utf = TRUE; break;+ case 'u': options |= PCRE2_UTF | PCRE2_UCP; utf = TRUE; break;+ case 'U': options |= PCRE2_UTF | PCRE2_MATCH_INVALID_UTF | PCRE2_UCP;+ utf = TRUE; break; case 'v': invert = TRUE; break;- case 'w': extra_options |= PCRE2_EXTRA_MATCH_WORD; break;- case 'x': extra_options |= PCRE2_EXTRA_MATCH_LINE; break; case 'V': {@@ -3532,11 +3634,17 @@ fprintf(stdout, "pcre2grep version %s" STDOUT_NL, buffer); } pcre2grep_exit(0);- break;+ break; /* LCOV_EXCL_LINE - statement kept to avoid compiler warning */ + case 'w': extra_options |= PCRE2_EXTRA_MATCH_WORD; break;+ case 'x': extra_options |= PCRE2_EXTRA_MATCH_LINE; break;+ case 'Z': printname_colon = printname_hyphen = 0; printname_nl = NULL; break;++ /* LCOV_EXCL_START - this is a "never event" */ default: fprintf(stderr, "pcre2grep: Unknown option -%c\n", letter); pcre2grep_exit(usage(2));+ /* LCOV_EXCL_STOP */ } return options;@@ -3714,8 +3822,10 @@ *patlastptr = add_pattern(buffer, patlen, *patlastptr); if (*patlastptr == NULL) {+ /* LCOV_EXCL_START - won't happen in testing */ if (f != stdin) fclose(f); return FALSE;+ /* LCOV_EXCL_STOP */ } if (*patptr == NULL) *patptr = *patlastptr; @@ -3868,9 +3978,11 @@ fulllen - baselen - 2, opbra + 1), ret < 0 || ret > (int)sizeof(buff2))) {+ /* LCOV_EXCL_START - this is a "never" event */ fprintf(stderr, "pcre2grep: Buffer overflow when parsing %s option\n", op->long_name); pcre2grep_exit(2);+ /* LCOV_EXCL_STOP */ } if (strncmp(arg, buff1, arglen) == 0 ||@@ -3932,7 +4044,7 @@ if (op->type == OP_OP_NUMBER || op->type == OP_OP_NUMBERS) {- if (isdigit((unsigned char)s[1])) break;+ if (isdigit((unsigned char)(s[1]))) break; } else /* Check for an option with data */ {@@ -4024,8 +4136,10 @@ fn = (fnstr *)malloc(sizeof(fnstr)); if (fn == NULL) {+ /* LCOV_EXCL_START */ fprintf(stderr, "pcre2grep: malloc failed\n"); goto EXIT2;+ /* LCOV_EXCL_STOP */ } fn->next = NULL; fn->name = option_data;@@ -4093,7 +4207,6 @@ pcre2grep_exit(usage(2)); } - /* Check that there is a big enough ovector for all -o settings. */ for (om = only_matching; om != NULL; om = om->next)@@ -4113,22 +4226,27 @@ !syntax_check_output_text((PCRE2_SPTR)output_text, FALSE)) goto EXIT2; -/* Set up default compile and match contexts and a match data block. */+/* Set up default compile and match contexts and match data blocks. */ offset_size = capture_max + 1; compile_context = pcre2_compile_context_create(NULL); match_context = pcre2_match_context_create(NULL);-match_data = pcre2_match_data_create(offset_size, NULL);-offsets = pcre2_get_ovector_pointer(match_data);+match_data_pair[0] = pcre2_match_data_create(offset_size, NULL);+match_data_pair[1] = pcre2_match_data_create(offset_size, NULL);+offsets_pair[0] = pcre2_get_ovector_pointer(match_data_pair[0]);+offsets_pair[1] = pcre2_get_ovector_pointer(match_data_pair[1]);+match_data = match_data_pair[0];+offsets = offsets_pair[0];+match_data_toggle = 0; /* If string (script) callouts are supported, set up the callout processing-function. */+function in the match context. */ #ifdef SUPPORT_PCRE2GREP_CALLOUT pcre2_set_callout(match_context, pcre2grep_callout, NULL); #endif -/* Put limits into the match data block. */+/* Put limits into the match context. */ if (heap_limit != PCRE2_UNSET) pcre2_set_heap_limit(match_context, heap_limit); if (match_limit > 0) pcre2_set_match_limit(match_context, match_limit);@@ -4198,6 +4316,11 @@ } } +/* When colouring or otherwise identifying matching substrings, we need to find+all possible matches when there are multiple patterns. */++all_matches = do_colour || only_matching_count != 0;+ /* Sort out a newline setting. */ if (newline_arg != NULL)@@ -4249,12 +4372,20 @@ } } -/* Set the extra options */+/* If no_ucp is set, remove PCRE2_UCP from the compile options. */ -(void)pcre2_set_compile_extra_options(compile_context, extra_options);+if (no_ucp) pcre2_options &= ~PCRE2_UCP; -/* Check the values for Jeffrey Friedl's debugging options. */+/* adjust the extra options. */ +if (case_restrict) extra_options |= PCRE2_EXTRA_CASELESS_RESTRICT;+if (posix_digit)+ extra_options |= (PCRE2_EXTRA_ASCII_BSD | PCRE2_EXTRA_ASCII_DIGIT);++/* Set the extra options in the compile context. */++(void)pcre2_set_compile_extra_options(compile_context, extra_options);+ /* If use_jit is set, check whether JIT is available. If not, do not try to use JIT. */ @@ -4278,8 +4409,10 @@ if (main_buffer == NULL) {+ /* LCOV_EXCL_START */ fprintf(stderr, "pcre2grep: malloc failed\n"); goto EXIT2;+ /* LCOV_EXCL_STOP */ } /* If no patterns were provided by -e, and there are no files provided by -f,@@ -4395,7 +4528,7 @@ { int frc; char *end = buffer + (int)strlen(buffer);- while (end > buffer && isspace(end[-1])) end--;+ while (end > buffer && isspace((unsigned char)(end[-1]))) end--; *end = 0; if (*buffer != 0) {@@ -4421,14 +4554,6 @@ else if (frc == 0 && rc == 1) rc = 0; } -#ifdef SUPPORT_PCRE2GREP_CALLOUT-/* If separating builtin echo callouts by implicit newline, add one more for-the final item. */--if (om_separator != NULL && strcmp(om_separator, STDOUT_NL) == 0)- fprintf(stdout, STDOUT_NL);-#endif- /* Show the total number of matches if requested, but not if only one file's count was printed. */ @@ -4450,7 +4575,8 @@ pcre2_compile_context_free(compile_context); pcre2_match_context_free(match_context);-pcre2_match_data_free(match_data);+pcre2_match_data_free(match_data_pair[0]);+pcre2_match_data_free(match_data_pair[1]); free_pattern_chain(patterns); free_pattern_chain(include_patterns);
src/c/pcre2/src/pcre2posix.c view
@@ -7,7 +7,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2021 University of Cambridge+ New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -40,25 +40,27 @@ /* This module is a wrapper that provides a POSIX API to the underlying PCRE2-functions. The operative functions are called pcre2_regcomp(), etc., with-wrappers that use the plain POSIX names. In addition, pcre2posix.h defines the-POSIX names as macros for the pcre2_xxx functions, so any program that includes-it and uses the POSIX names will call the base functions directly. This makes-it easier for an application to be sure it gets the PCRE2 versions in the-presence of other POSIX regex libraries. */+functions. The functions are called pcre2_regcomp(), pcre2_regexec(), etc.+pcre2posix.h defines the POSIX names as macros for the corresonding pcre2_xxx+functions, so any program that includes it and uses the POSIX names will call+the PCRE2 implementations instead. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#ifdef PCRE2POSIX_SHARED+#undef PCRE2_STATIC+#endif + /* Ensure that the PCRE2POSIX_EXP_xxx macros are set appropriately for compiling these functions. This must come before including pcre2posix.h, where they are set for an application (using these functions) if they have not previously been set. */ -#if defined(_WIN32) && !defined(PCRE2_STATIC)+#if defined(_WIN32) && (defined(PCRE2POSIX_SHARED) || !defined(PCRE2_STATIC)) # define PCRE2POSIX_EXP_DECL extern __declspec(dllexport) # define PCRE2POSIX_EXP_DEFN __declspec(dllexport) #endif@@ -69,6 +71,7 @@ #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf+#define BROKEN_SNPRINTF #endif @@ -92,20 +95,6 @@ #include "pcre2.h" #include "pcre2posix.h" -/* When compiling with the MSVC compiler, it is sometimes necessary to include-a "calling convention" before exported function names. (This is secondhand-information; I know nothing about MSVC myself). For example, something like-- void __cdecl function(....)--might be needed. In order to make this easy, all the exported functions have-PCRE2_CALL_CONVENTION just before their names. It is rarely needed; if not-set, we ensure here that it has no effect. */--#ifndef PCRE2_CALL_CONVENTION-#define PCRE2_CALL_CONVENTION-#endif- /* Table to translate PCRE2 compile time error codes into POSIX error codes. Only a few PCRE2 errors with a value greater than 23 turn into special POSIX codes: most go to REG_BADPAT. The second table lists, in pairs, those that@@ -174,68 +163,14 @@ "match failed" /* NOMATCH */ }; ---#if 0 /* REMOVE THIS CODE */--The code below was created for 10.33 (see ChangeLog 10.33 #4) when the-POSIX functions were given pcre2_... names instead of the traditional POSIX-names. However, it has proved to be more troublesome than useful. There have-been at least two cases where a program links with two others, one of which-uses the POSIX library and the other uses the PCRE2 POSIX functions, thus-causing two instances of the POSIX runctions to exist, leading to trouble. For-10.37 this code is commented out. In due course it can be removed if there are-no issues. The only small worry is the comment below about languages that do-not include pcre2posix.h. If there are any such cases, they will have to use-the PCRE2 names.---/*************************************************-* Wrappers with traditional POSIX names *-*************************************************/--/* Keep defining them to preseve the ABI for applications linked to the pcre2-POSIX library before these names were changed into macros in pcre2posix.h.-This also ensures that the POSIX names are callable from languages that do not-include pcre2posix.h. It is vital to #undef the macro definitions from-pcre2posix.h! */--#undef regerror-PCRE2POSIX_EXP_DECL size_t regerror(int, const regex_t *, char *, size_t);-PCRE2POSIX_EXP_DEFN size_t PCRE2_CALL_CONVENTION-regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)-{-return pcre2_regerror(errcode, preg, errbuf, errbuf_size);-}--#undef regfree-PCRE2POSIX_EXP_DECL void regfree(regex_t *);-PCRE2POSIX_EXP_DEFN void PCRE2_CALL_CONVENTION-regfree(regex_t *preg)+static int message_len(const char *message, int offset) {-pcre2_regfree(preg);-}+char buf[12]; -#undef regcomp-PCRE2POSIX_EXP_DECL int regcomp(regex_t *, const char *, int);-PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION-regcomp(regex_t *preg, const char *pattern, int cflags)-{-return pcre2_regcomp(preg, pattern, cflags);+/* 11 magic number comes from the format below */+return (int)strlen(message) + 11 + snprintf(buf, sizeof(buf), "%d", offset); } -#undef regexec-PCRE2POSIX_EXP_DECL int regexec(const regex_t *, const char *, size_t,- regmatch_t *, int);-PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION-regexec(const regex_t *preg, const char *string, size_t nmatch,- regmatch_t pmatch[], int eflags)-{-return pcre2_regexec(preg, string, nmatch, pmatch, eflags);-}-#endif-- /************************************************* * Translate error code to string * *************************************************/@@ -244,23 +179,64 @@ pcre2_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) {-int used;+int ret; const char *message;+size_t len = 0; /* keeps 0 if snprintf is used */ message = (errcode <= 0 || errcode >= (int)(sizeof(pstring)/sizeof(char *)))? "unknown error code" : pstring[errcode]; if (preg != NULL && (int)preg->re_erroffset != -1) {- used = snprintf(errbuf, errbuf_size, "%s at offset %-6d", message,- (int)preg->re_erroffset);+ /* no need to deal with UB in snprintf */+ if (errbuf_size > INT_MAX) errbuf_size = INT_MAX;++ /* there are 11 charactes between message and offset,+ update message_len() if changed */+ ret = snprintf(errbuf, errbuf_size, "%s at offset %d", message,+ (int)preg->re_erroffset); } else {- used = snprintf(errbuf, errbuf_size, "%s", message);+ len = strlen(message);+ if (errbuf_size != 0)+ {+ strncpy(errbuf, message, errbuf_size);+ if (errbuf_size <= len) errbuf[errbuf_size - 1] = '\0';+ }+ ret = (int)len; } -return used + 1;+do {+ if (ret < 0)+ {+#ifdef BROKEN_SNPRINTF+ /* _snprintf returns -1 on overflow and doesn't zero terminate */+ if (!len)+ {+ if (ret == -1 && errbuf_size != 0) errbuf[errbuf_size - 1] = '\0';++ ret = message_len(message, (int)preg->re_erroffset);+ break;+ }+#endif+ /* snprintf failed, will use a 14 char long message if possible */+ ret = 14;+ if (errbuf_size != 0)+ {+ strncpy(errbuf, "internal error", errbuf_size);+ if ((int)errbuf_size <= ret) errbuf[errbuf_size - 1] = '\0';+ }+ }+ else if (ret == (int)errbuf_size && !len)+ {+ /* pre C99 snprintf returns used, so redo ret to fix that */++ ret = message_len(message, (int)preg->re_erroffset);+ }+} while (0);++return ret + 1; } @@ -342,8 +318,10 @@ if (preg->re_match_data == NULL) {+ /* LCOV_EXCL_START */ pcre2_code_free(preg->re_pcre2_code); return REG_ESPACE;+ /* LCOV_EXCL_STOP */ } return 0;@@ -423,17 +401,24 @@ if (rc <= PCRE2_ERROR_UTF8_ERR1 && rc >= PCRE2_ERROR_UTF8_ERR21) return REG_INVARG; +/* Most of these are events that won't occur during testing, so exclude them+from coverage. */+ switch(rc) {- default: return REG_ASSERT;+ case PCRE2_ERROR_HEAPLIMIT: return REG_ESPACE;+ case PCRE2_ERROR_NOMATCH: return REG_NOMATCH;++ /* LCOV_EXCL_START */ case PCRE2_ERROR_BADMODE: return REG_INVARG; case PCRE2_ERROR_BADMAGIC: return REG_INVARG; case PCRE2_ERROR_BADOPTION: return REG_INVARG; case PCRE2_ERROR_BADUTFOFFSET: return REG_INVARG; case PCRE2_ERROR_MATCHLIMIT: return REG_ESPACE;- case PCRE2_ERROR_NOMATCH: return REG_NOMATCH; case PCRE2_ERROR_NOMEMORY: return REG_ESPACE; case PCRE2_ERROR_NULL: return REG_INVARG;+ default: return REG_ASSERT;+ /* LCOV_EXCL_STOP */ } }
src/c/pcre2/src/pcre2posix.h view
@@ -9,7 +9,7 @@ Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2019 University of Cambridge+ New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -40,6 +40,8 @@ ----------------------------------------------------------------------------- */ +#ifndef PCRE2POSIX_H_IDEMPOTENT_GUARD+#define PCRE2POSIX_H_IDEMPOTENT_GUARD /* Have to include stdlib.h in order to ensure that size_t is defined. */ @@ -116,25 +118,38 @@ regoff_t rm_eo; } regmatch_t; +/* When compiling with the MSVC compiler, it is sometimes necessary to include+a "calling convention" before exported function names. (This is secondhand+information; I know nothing about MSVC myself). For example, something like++ void __cdecl function(....)++might be needed. In order to make this easy, all the exported functions have+PCRE2_CALL_CONVENTION just before their names. It is rarely needed; if not+set, we ensure here that it has no effect. */++#ifndef PCRE2_CALL_CONVENTION+#define PCRE2_CALL_CONVENTION+#endif++#ifndef PCRE2_EXPORT+#define PCRE2_EXPORT+#endif+ /* When an application links to a PCRE2 DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE2, the appropriate export settings are needed, and are set in pcre2posix.c before including this file. */ -#if defined(_WIN32) && !defined(PCRE2_STATIC) && !defined(PCRE2POSIX_EXP_DECL)-# define PCRE2POSIX_EXP_DECL extern __declspec(dllimport)-# define PCRE2POSIX_EXP_DEFN __declspec(dllimport)-#endif- /* By default, we use the standard "extern" declarations. */ #ifndef PCRE2POSIX_EXP_DECL-# ifdef __cplusplus-# define PCRE2POSIX_EXP_DECL extern "C"-# define PCRE2POSIX_EXP_DEFN extern "C"+# if defined(_WIN32) && defined(PCRE2POSIX_SHARED) && !defined(PCRE2_STATIC)+# define PCRE2POSIX_EXP_DECL extern __declspec(dllimport)+# define PCRE2POSIX_EXP_DEFN __declspec(dllimport) # else-# define PCRE2POSIX_EXP_DECL extern-# define PCRE2POSIX_EXP_DEFN extern+# define PCRE2POSIX_EXP_DECL extern PCRE2_EXPORT+# define PCRE2POSIX_EXP_DEFN # endif #endif @@ -144,11 +159,11 @@ the PCRE2 library and not by accident from elsewhere (regex_t differs in size elsewhere). */ -PCRE2POSIX_EXP_DECL int pcre2_regcomp(regex_t *, const char *, int);-PCRE2POSIX_EXP_DECL int pcre2_regexec(const regex_t *, const char *, size_t,+PCRE2POSIX_EXP_DECL int PCRE2_CALL_CONVENTION pcre2_regcomp(regex_t *, const char *, int);+PCRE2POSIX_EXP_DECL int PCRE2_CALL_CONVENTION pcre2_regexec(const regex_t *, const char *, size_t, regmatch_t *, int);-PCRE2POSIX_EXP_DECL size_t pcre2_regerror(int, const regex_t *, char *, size_t);-PCRE2POSIX_EXP_DECL void pcre2_regfree(regex_t *);+PCRE2POSIX_EXP_DECL size_t PCRE2_CALL_CONVENTION pcre2_regerror(int, const regex_t *, char *, size_t);+PCRE2POSIX_EXP_DECL void PCRE2_CALL_CONVENTION pcre2_regfree(regex_t *); #define regcomp pcre2_regcomp #define regexec pcre2_regexec@@ -166,5 +181,7 @@ #ifdef __cplusplus } /* extern "C" */ #endif++#endif /* PCRE2POSIX_H_IDEMPOTENT_GUARD */ /* End of pcre2posix.h */
+ src/c/pcre2/src/pcre2posix_test.c view
@@ -0,0 +1,209 @@+/*************************************************+* PCRE2 POSIX interface test program *+*************************************************/++/*+Written by Philip Hazel, December 2022+Copyright (c) 2022+File last edited: December 2022++This program tests the POSIX wrapper to the PCRE2 regular expression library.+The main PCRE2 test program is pcre2test, which also tests these function+calls. This little program is needed to test the case where the client includes+pcre2posix.h but not pcre2.h, mainly to make sure that it builds successfully.+However, the code is written as a flexible test program to which extra tests+can be added.++Compile with -lpcre2-posix -lpcre2-8++If run with no options, there is no output on success, and the return code is+zero. If any test fails there is output to stderr, and the return code is 1.++For testing purposes, the "-v" option causes verification output to be written+to stdout. */++#include <stdio.h>+#include <string.h>+#include <pcre2posix.h>++#define CAPCOUNT 5 /* Number of captures supported */+#define PRINTF if (v) printf /* Shorthand for testing output */++/* This vector contains compiler flags for each pattern that is tested. */++static int cflags[] = {+ 0, /* Test 0 */+ REG_ICASE, /* Test 1 */+ 0, /* Test 2 */+ REG_NEWLINE, /* Test 3 */+ 0 /* Test 4 */+};++/* This vector contains match flags for each pattern that is tested. */++static int mflags[] = {+ 0, /* Test 0 */+ 0, /* Test 1 */+ 0, /* Test 2 */+ REG_NOTBOL, /* Test 3 */+ 0 /* Test 4 */+};++/* Automate the number of patterns */++#define count (int)(sizeof(cflags)/sizeof(int))++/* The data for each pattern consists of a pattern string, followed by any+number of subject strings, terminated by NULL. Some tests share data, but use+different flags. */++static const char *data0_1[] = { "posix", "lower posix", "upper POSIX", NULL };+static const char *data2_3[] = { "(*LF)^(cat|dog)", "catastrophic\ncataclysm",+ "dogfight", "no animals", NULL };+static const char *data4[] = { "*badpattern", NULL };++/* Index the data strings */++static char **data[] = {+ (char **)(&data0_1),+ (char **)(&data0_1),+ (char **)(&data2_3),+ (char **)(&data2_3),+ (char **)(&data4)+};++/* The expected results for each pattern consist of a compiler return code,+optionally followed, for each subject string, by a match return code and, for a+successful match, up to CAPCOUNT pairs of returned match data. */++static int results0[] = {+ 0, /* Compiler rc */+ 0, 6, 11, /* 1st match */+ REG_NOMATCH /* 2nd match */+};++static int results1[] = {+ 0, /* Compiler rc */+ 0, 6, 11, /* 1st match */+ 0, 6, 11 /* 2nd match */+};++static int results2[] = {+ 0, /* Compiler rc */+ 0, 0, 3, 0, 3, /* 1st match */+ 0, 0, 3, 0, 3, /* 2nd match */+ REG_NOMATCH /* 3rd match */+};++static int results3[] = {+ 0, /* Compiler rc */+ 0, 13, 16, 13, 16, /* 1st match */+ REG_NOMATCH, /* 2nd match */+ REG_NOMATCH /* 3rd match */+};++static int results4[] = {+ REG_BADRPT /* Compiler rc */+};++/* Index the result vectors */++static int *results[] = {+ (int *)(&results0),+ (int *)(&results1),+ (int *)(&results2),+ (int *)(&results3),+ (int *)(&results4)+};++/* And here is the program */++int main(int argc, char **argv)+{+regex_t re;+regmatch_t match[CAPCOUNT];+int v = argc > 1 && strcmp(argv[1], "-v") == 0;++PRINTF("Test of pcre2posix.h without pcre2.h\n");++for (int i = 0; i < count; i++)+ {+ char *pattern = data[i][0];+ char **subjects = data[i] + 1;+ int *rd = results[i];+ int rc = regcomp(&re, pattern, cflags[i]);++ PRINTF("Pattern: %s flags=0x%02x\n", pattern, cflags[i]);++ if (rc != *rd)+ {+ fprintf(stderr, "Unexpected compile error %d (expected %d)\n", rc, *rd);+ fprintf(stderr, "Pattern is: %s\n", pattern);+ return 1;+ }++ if (rc != 0)+ {+ if (v)+ {+ char buffer[256];+ (void)regerror(rc, &re, buffer, sizeof(buffer));+ PRINTF("Compile error %d: %s (expected)\n", rc, buffer);+ }+ continue;+ }++ for (; *subjects != NULL; subjects++)+ {+ rc = regexec(&re, *subjects, CAPCOUNT, match, mflags[i]);++ PRINTF("Subject: %s\n", *subjects);+ PRINTF("Return: %d", rc);++ if (rc != *(++rd))+ {+ PRINTF("\n");+ fprintf(stderr, "Unexpected match error %d (expected %d)\n", rc, *rd);+ fprintf(stderr, "Pattern is: %s\n", pattern);+ fprintf(stderr, "Subject is: %s\n", *subjects);+ return 1;+ }++ if (rc == 0)+ {+ for (int j = 0; j < CAPCOUNT; j++)+ {+ regmatch_t *m = match + j;+ if (m->rm_so < 0) continue;+ if (m->rm_so != *(++rd) || m->rm_eo != *(++rd))+ {+ PRINTF("\n");+ fprintf(stderr, "Mismatched results for successful match\n");+ fprintf(stderr, "Pattern is: %s\n", pattern);+ fprintf(stderr, "Subject is: %s\n", *subjects);+ fprintf(stderr, "Result %d: expected %d %d received %d %d\n",+ j, rd[-1], rd[0], m->rm_so, m->rm_eo);+ return 1;+ }+ PRINTF(" (%d %d %d)", j, m->rm_so, m->rm_eo);+ }+ }++ else if (v)+ {+ char buffer[256];+ (void)regerror(rc, &re, buffer, sizeof(buffer));+ PRINTF(": %s (expected)", buffer);+ }++ PRINTF("\n");+ }++ regfree(&re);+ }++PRINTF("End of test\n");+return 0;+}++/* End of pcre2posix_test.c */
src/c/pcre2/src/pcre2test.c view
@@ -11,7 +11,7 @@ Written by Philip Hazel Original code Copyright (c) 1997-2012 University of Cambridge- Rewritten code Copyright (c) 2016-2022 University of Cambridge+ Rewritten code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -263,16 +263,22 @@ clash with those in the libraries. Also, although pcre2_internal.h does itself include pcre2.h, we explicitly include it beforehand, along with pcre2posix.h, so that the PCRE2_EXP_xxx macros get set appropriately for an application, not-for building the library. */+for building the library. +Setting PCRE2_CODE_UNIT_WIDTH to zero cuts out all the width-specific settings+in pcre2.h and pcre2_internal.h. Defining PCRE2_BUILDING_PCRE2TEST cuts out the+check in pcre2_internal.h that ensures PCRE2_CODE_UNIT_WIDTH is 8, 16, or 32+(which it needs to be when compiling one of the libraries). */+ #define PRIV(name) name #define PCRE2_CODE_UNIT_WIDTH 0+#define PCRE2_BUILDING_PCRE2TEST #include "pcre2.h" #include "pcre2posix.h" #include "pcre2_internal.h" /* We need access to some of the data tables that PCRE2 uses. Defining-PCRE2_PCRETEST makes some minor changes in the files. The previous definition+PCRE2_PCRE2TEST makes some minor changes in the files. The previous definition of PRIV avoids name clashes. */ #define PCRE2_PCRE2TEST@@ -336,6 +342,8 @@ #define PCRE2_SUFFIX(a) a +#include "pcre2_chkdint.c"+ /* We need to be able to check input text for UTF-8 validity, whatever code widths are actually available, because the input to pcre2test is always in 8-bit code units. So we include the UTF validity checking function for 8-bit@@ -479,7 +487,7 @@ #define CTL_DFA 0x00000200u #define CTL_EXPAND 0x00000400u #define CTL_FINDLIMITS 0x00000800u-#define CTL_FRAMESIZE 0x00001000u+#define CTL_FINDLIMITS_NOHEAP 0x00001000u #define CTL_FULLBINCODE 0x00002000u #define CTL_GETALL 0x00004000u #define CTL_GLOBAL 0x00008000u@@ -520,9 +528,12 @@ #define CTL2_CALLOUT_NO_WHERE 0x00000200u #define CTL2_CALLOUT_EXTRA 0x00000400u #define CTL2_ALLVECTOR 0x00000800u-#define CTL2_NULL_SUBJECT 0x00001000u-#define CTL2_NULL_REPLACEMENT 0x00002000u+#define CTL2_NULL_PATTERN 0x00001000u+#define CTL2_NULL_SUBJECT 0x00002000u+#define CTL2_NULL_REPLACEMENT 0x00004000u+#define CTL2_FRAMESIZE 0x00008000u +#define CTL2_HEAPFRAMES_SIZE 0x20000000u /* Informational */ #define CTL2_NL_SET 0x40000000u /* Informational */ #define CTL2_BSR_SET 0x80000000u /* Informational */ @@ -549,7 +560,8 @@ CTL2_SUBSTITUTE_REPLACEMENT_ONLY|\ CTL2_SUBSTITUTE_UNKNOWN_UNSET|\ CTL2_SUBSTITUTE_UNSET_EMPTY|\- CTL2_ALLVECTOR)+ CTL2_ALLVECTOR|\+ CTL2_HEAPFRAMES_SIZE) /* Structures for holding modifier information for patterns and subject strings (data). Fields containing modifiers that can be set either for a pattern or a@@ -625,6 +637,9 @@ PCRE2_SIZE offset; } modstruct; +#define PCRE2_EXTRA_ASCII_ALL (PCRE2_EXTRA_ASCII_BSD|PCRE2_EXTRA_ASCII_BSS| \+ PCRE2_EXTRA_ASCII_BSW|PCRE2_EXTRA_ASCII_POSIX)+ static modstruct modlist[] = { { "aftertext", MOD_PNDP, MOD_CTL, CTL_AFTERTEXT, PO(control) }, { "allaftertext", MOD_PNDP, MOD_CTL, CTL_ALLAFTERTEXT, PO(control) },@@ -639,6 +654,12 @@ { "alt_verbnames", MOD_PAT, MOD_OPT, PCRE2_ALT_VERBNAMES, PO(options) }, { "altglobal", MOD_PND, MOD_CTL, CTL_ALTGLOBAL, PO(control) }, { "anchored", MOD_PD, MOD_OPT, PCRE2_ANCHORED, PD(options) },+ { "ascii_all", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ASCII_ALL, CO(extra_options) },+ { "ascii_bsd", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ASCII_BSD, CO(extra_options) },+ { "ascii_bss", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ASCII_BSS, CO(extra_options) },+ { "ascii_bsw", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ASCII_BSW, CO(extra_options) },+ { "ascii_digit", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ASCII_DIGIT, CO(extra_options) },+ { "ascii_posix", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ASCII_POSIX, CO(extra_options) }, { "auto_callout", MOD_PAT, MOD_OPT, PCRE2_AUTO_CALLOUT, PO(options) }, { "bad_escape_is_literal", MOD_CTC, MOD_OPT, PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL, CO(extra_options) }, { "bincode", MOD_PAT, MOD_CTL, CTL_BINCODE, PO(control) },@@ -652,6 +673,7 @@ { "callout_no_where", MOD_DAT, MOD_CTL, CTL2_CALLOUT_NO_WHERE, DO(control2) }, { "callout_none", MOD_DAT, MOD_CTL, CTL_CALLOUT_NONE, DO(control) }, { "caseless", MOD_PATP, MOD_OPT, PCRE2_CASELESS, PO(options) },+ { "caseless_restrict", MOD_CTC, MOD_OPT, PCRE2_EXTRA_CASELESS_RESTRICT, CO(extra_options) }, { "convert", MOD_PAT, MOD_CON, 0, PO(convert_type) }, { "convert_glob_escape", MOD_PAT, MOD_CHR, 0, PO(convert_glob_escape) }, { "convert_glob_separator", MOD_PAT, MOD_CHR, 0, PO(convert_glob_separator) },@@ -663,6 +685,7 @@ { "dfa", MOD_DAT, MOD_CTL, CTL_DFA, DO(control) }, { "dfa_restart", MOD_DAT, MOD_OPT, PCRE2_DFA_RESTART, DO(options) }, { "dfa_shortest", MOD_DAT, MOD_OPT, PCRE2_DFA_SHORTEST, DO(options) },+ { "disable_recurseloop_check", MOD_DAT, MOD_OPT, PCRE2_DISABLE_RECURSELOOP_CHECK, DO(options) }, { "dollar_endonly", MOD_PAT, MOD_OPT, PCRE2_DOLLAR_ENDONLY, PO(options) }, { "dotall", MOD_PATP, MOD_OPT, PCRE2_DOTALL, PO(options) }, { "dupnames", MOD_PATP, MOD_OPT, PCRE2_DUPNAMES, PO(options) },@@ -673,13 +696,15 @@ { "extended_more", MOD_PATP, MOD_OPT, PCRE2_EXTENDED_MORE, PO(options) }, { "extra_alt_bsux", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ALT_BSUX, CO(extra_options) }, { "find_limits", MOD_DAT, MOD_CTL, CTL_FINDLIMITS, DO(control) },+ { "find_limits_noheap", MOD_DAT, MOD_CTL, CTL_FINDLIMITS_NOHEAP, DO(control) }, { "firstline", MOD_PAT, MOD_OPT, PCRE2_FIRSTLINE, PO(options) },- { "framesize", MOD_PAT, MOD_CTL, CTL_FRAMESIZE, PO(control) },+ { "framesize", MOD_PAT, MOD_CTL, CTL2_FRAMESIZE, PO(control2) }, { "fullbincode", MOD_PAT, MOD_CTL, CTL_FULLBINCODE, PO(control) }, { "get", MOD_DAT, MOD_NN, DO(get_numbers), DO(get_names) }, { "getall", MOD_DAT, MOD_CTL, CTL_GETALL, DO(control) }, { "global", MOD_PNDP, MOD_CTL, CTL_GLOBAL, PO(control) }, { "heap_limit", MOD_CTM, MOD_INT, 0, MO(heap_limit) },+ { "heapframes_size", MOD_PND, MOD_CTL, CTL2_HEAPFRAMES_SIZE, PO(control2) }, { "hex", MOD_PAT, MOD_CTL, CTL_HEXPAT, PO(control) }, { "info", MOD_PAT, MOD_CTL, CTL_INFO, PO(control) }, { "jit", MOD_PAT, MOD_IND, 7, PO(jit) },@@ -694,7 +719,9 @@ { "match_line", MOD_CTC, MOD_OPT, PCRE2_EXTRA_MATCH_LINE, CO(extra_options) }, { "match_unset_backref", MOD_PAT, MOD_OPT, PCRE2_MATCH_UNSET_BACKREF, PO(options) }, { "match_word", MOD_CTC, MOD_OPT, PCRE2_EXTRA_MATCH_WORD, CO(extra_options) },+ { "max_pattern_compiled_length", MOD_CTC, MOD_SIZ, 0, CO(max_pattern_compiled_length) }, { "max_pattern_length", MOD_CTC, MOD_SIZ, 0, CO(max_pattern_length) },+ { "max_varlookbehind", MOD_CTC, MOD_INT, 0, CO(max_varlookbehind) }, { "memory", MOD_PD, MOD_CTL, CTL_MEMORY, PD(control) }, { "multiline", MOD_PATP, MOD_OPT, PCRE2_MULTILINE, PO(options) }, { "never_backslash_c", MOD_PAT, MOD_OPT, PCRE2_NEVER_BACKSLASH_C, PO(options) },@@ -712,6 +739,7 @@ { "notempty_atstart", MOD_DAT, MOD_OPT, PCRE2_NOTEMPTY_ATSTART, DO(options) }, { "noteol", MOD_DAT, MOD_OPT, PCRE2_NOTEOL, DO(options) }, { "null_context", MOD_PD, MOD_CTL, CTL_NULLCONTEXT, PO(control) },+ { "null_pattern", MOD_PAT, MOD_CTL, CTL2_NULL_PATTERN, PO(control2) }, { "null_replacement", MOD_DAT, MOD_CTL, CTL2_NULL_REPLACEMENT, DO(control2) }, { "null_subject", MOD_DAT, MOD_CTL, CTL2_NULL_SUBJECT, DO(control2) }, { "offset", MOD_DAT, MOD_INT, 0, DO(offset) },@@ -781,10 +809,11 @@ #define PUSH_SUPPORTED_COMPILE_CONTROLS ( \ CTL_BINCODE|CTL_CALLOUT_INFO|CTL_FULLBINCODE|CTL_HEXPAT|CTL_INFO| \- CTL_JITVERIFY|CTL_MEMORY|CTL_FRAMESIZE|CTL_PUSH|CTL_PUSHCOPY| \+ CTL_JITVERIFY|CTL_MEMORY|CTL_PUSH|CTL_PUSHCOPY| \ CTL_PUSHTABLESCOPY|CTL_USE_LENGTH) -#define PUSH_SUPPORTED_COMPILE_CONTROLS2 (CTL2_BSR_SET|CTL2_NL_SET)+#define PUSH_SUPPORTED_COMPILE_CONTROLS2 (CTL2_BSR_SET| \+ CTL2_HEAPFRAMES_SIZE|CTL2_FRAMESIZE|CTL2_NL_SET) /* Controls that apply only at compile time with 'push'. */ @@ -813,8 +842,9 @@ first control word. */ static uint32_t exclusive_dat_controls[] = {- CTL_ALLUSEDTEXT | CTL_STARTCHAR,- CTL_FINDLIMITS | CTL_NULLCONTEXT };+ CTL_ALLUSEDTEXT | CTL_STARTCHAR,+ CTL_FINDLIMITS | CTL_NULLCONTEXT,+ CTL_FINDLIMITS_NOHEAP | CTL_NULLCONTEXT }; /* Table of single-character abbreviated modifiers. The index field is initialized to -1, but the first time the modifier is encountered, it is filled@@ -829,14 +859,16 @@ } c1modstruct; static c1modstruct c1modlist[] = {- { "bincode", 'B', -1 },- { "info", 'I', -1 },- { "global", 'g', -1 },- { "caseless", 'i', -1 },- { "multiline", 'm', -1 },- { "no_auto_capture", 'n', -1 },- { "dotall", 's', -1 },- { "extended", 'x', -1 }+ { "bincode", 'B', -1 },+ { "info", 'I', -1 },+ { "ascii_all", 'a', -1 },+ { "global", 'g', -1 },+ { "caseless", 'i', -1 },+ { "multiline", 'm', -1 },+ { "no_auto_capture", 'n', -1 },+ { "caseless_restrict", 'r', -1 },+ { "dotall", 's', -1 },+ { "extended", 'x', -1 } }; #define C1MODLISTCOUNT sizeof(c1modlist)/sizeof(c1modstruct)@@ -927,7 +959,6 @@ static BOOL restrict_for_perl_test = FALSE; static BOOL show_memory = FALSE; -static int code_unit_size; /* Bytes */ static int jitrc; /* Return from JIT compile */ static int test_mode = DEFAULT_TEST_MODE; static int timeit = 0;@@ -937,6 +968,7 @@ clock_t total_jit_compile_time = 0; clock_t total_match_time = 0; +static uint32_t code_unit_size; /* Bytes */ static uint32_t dfa_matched; static uint32_t forbid_utf = 0; static uint32_t maxlookbehind;@@ -1142,11 +1174,11 @@ #define PCRE2_COMPILE(a,b,c,d,e,f,g) \ if (test_mode == PCRE8_MODE) \- G(a,8) = pcre2_compile_8(G(b,8),c,d,e,f,g); \+ G(a,8) = pcre2_compile_8(b,c,d,e,f,g); \ else if (test_mode == PCRE16_MODE) \- G(a,16) = pcre2_compile_16(G(b,16),c,d,e,f,g); \+ G(a,16) = pcre2_compile_16(b,c,d,e,f,g); \ else \- G(a,32) = pcre2_compile_32(G(b,32),c,d,e,f,g)+ G(a,32) = pcre2_compile_32(b,c,d,e,f,g) #define PCRE2_CONVERTED_PATTERN_FREE(a) \ if (test_mode == PCRE8_MODE) pcre2_converted_pattern_free_8((PCRE2_UCHAR8 *)a); \@@ -1169,6 +1201,14 @@ else \ r = pcre2_get_error_message_32(a,G(b,32),G(G(b,32),_size/4)) +#define PCRE2_GET_MATCH_DATA_HEAPFRAMES_SIZE(r,a) \+ if (test_mode == PCRE8_MODE) \+ r = pcre2_get_match_data_heapframes_size_8(G(a,8)); \+ else if (test_mode == PCRE16_MODE) \+ r = pcre2_get_match_data_heapframes_size_16(G(a,16)); \+ else \+ r = pcre2_get_match_data_heapframes_size_32(G(a,32))+ #define PCRE2_GET_OVECTOR_COUNT(a,b) \ if (test_mode == PCRE8_MODE) \ a = pcre2_get_ovector_count_8(G(b,8)); \@@ -1227,11 +1267,16 @@ else \ pcre2_jit_stack_free_32((pcre2_jit_stack_32 *)a); -#define PCRE2_MAKETABLES(a) \- if (test_mode == PCRE8_MODE) a = pcre2_maketables_8(NULL); \- else if (test_mode == PCRE16_MODE) a = pcre2_maketables_16(NULL); \- else a = pcre2_maketables_32(NULL)+#define PCRE2_MAKETABLES(a,c) \+ if (test_mode == PCRE8_MODE) a = pcre2_maketables_8(G(c,8)); \+ else if (test_mode == PCRE16_MODE) a = pcre2_maketables_16(G(c,16)); \+ else a = pcre2_maketables_32(G(c,32)) +#define PCRE2_MAKETABLES_FREE(c,a) \+ if (test_mode == PCRE8_MODE) pcre2_maketables_free_8(G(c,8),a); \+ else if (test_mode == PCRE16_MODE) pcre2_maketables_free_16(G(c,16),a); \+ else pcre2_maketables_free_32(G(c,32),a)+ #define PCRE2_MATCH(a,b,c,d,e,f,g,h) \ if (test_mode == PCRE8_MODE) \ a = pcre2_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h); \@@ -1242,19 +1287,19 @@ #define PCRE2_MATCH_DATA_CREATE(a,b,c) \ if (test_mode == PCRE8_MODE) \- G(a,8) = pcre2_match_data_create_8(b,c); \+ G(a,8) = pcre2_match_data_create_8(b,G(c,8)); \ else if (test_mode == PCRE16_MODE) \- G(a,16) = pcre2_match_data_create_16(b,c); \+ G(a,16) = pcre2_match_data_create_16(b,G(c,16)); \ else \- G(a,32) = pcre2_match_data_create_32(b,c)+ G(a,32) = pcre2_match_data_create_32(b,G(c,32)) #define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \ if (test_mode == PCRE8_MODE) \- G(a,8) = pcre2_match_data_create_from_pattern_8(G(b,8),c); \+ G(a,8) = pcre2_match_data_create_from_pattern_8(G(b,8),G(c,8)); \ else if (test_mode == PCRE16_MODE) \- G(a,16) = pcre2_match_data_create_from_pattern_16(G(b,16),c); \+ G(a,16) = pcre2_match_data_create_from_pattern_16(G(b,16),G(c,16)); \ else \- G(a,32) = pcre2_match_data_create_from_pattern_32(G(b,32),c)+ G(a,32) = pcre2_match_data_create_from_pattern_32(G(b,32),G(c,32)) #define PCRE2_MATCH_DATA_FREE(a) \ if (test_mode == PCRE8_MODE) \@@ -1384,6 +1429,14 @@ else \ pcre2_set_match_limit_32(G(a,32),b) +#define PCRE2_SET_MAX_PATTERN_COMPILED_LENGTH(a,b) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_max_pattern_compiled_length_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_max_pattern_compiled_length_16(G(a,16),b); \+ else \+ pcre2_set_max_pattern_compiled_length_32(G(a,32),b)+ #define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) \ if (test_mode == PCRE8_MODE) \ pcre2_set_max_pattern_length_8(G(a,8),b); \@@ -1392,6 +1445,14 @@ else \ pcre2_set_max_pattern_length_32(G(a,32),b) +#define PCRE2_SET_MAX_VARLOOKBEHIND(a,b) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_max_varlookbehind_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_max_varlookbehind_16(G(a,16),b); \+ else \+ pcre2_set_max_varlookbehind_32(G(a,32),b)+ #define PCRE2_SET_OFFSET_LIMIT(a,b) \ if (test_mode == PCRE8_MODE) \ pcre2_set_offset_limit_8(G(a,8),b); \@@ -1494,11 +1555,11 @@ #define PCRE2_SUBSTRING_LIST_FREE(a) \ if (test_mode == PCRE8_MODE) \- pcre2_substring_list_free_8((PCRE2_SPTR8 *)a); \+ pcre2_substring_list_free_8((PCRE2_UCHAR8 **)a); \ else if (test_mode == PCRE16_MODE) \- pcre2_substring_list_free_16((PCRE2_SPTR16 *)a); \+ pcre2_substring_list_free_16((PCRE2_UCHAR16 **)a); \ else \- pcre2_substring_list_free_32((PCRE2_SPTR32 *)a)+ pcre2_substring_list_free_32((PCRE2_UCHAR32 **)a) #define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \ if (test_mode == PCRE8_MODE) \@@ -1672,9 +1733,9 @@ #define PCRE2_COMPILE(a,b,c,d,e,f,g) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(a,BITONE) = G(pcre2_compile_,BITONE)(G(b,BITONE),c,d,e,f,g); \+ G(a,BITONE) = G(pcre2_compile_,BITONE)(b,c,d,e,f,g); \ else \- G(a,BITTWO) = G(pcre2_compile_,BITTWO)(G(b,BITTWO),c,d,e,f,g)+ G(a,BITTWO) = G(pcre2_compile_,BITTWO)(b,c,d,e,f,g) #define PCRE2_CONVERTED_PATTERN_FREE(a) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \@@ -1696,6 +1757,12 @@ else \ r = G(pcre2_get_error_message_,BITTWO)(a,G(b,BITTWO),G(G(b,BITTWO),_size/BYTETWO)) +#define PCRE2_GET_MATCH_DATA_HEAPFRAMES_SIZE(r,a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ r = G(pcre2_get_match_data_heapframes_size_,BITONE)(G(a,BITONE)); \+ else \+ r = G(pcre2_get_match_data_heapframes_size_,BITTWO)(G(a,BITTWO))+ #define PCRE2_GET_OVECTOR_COUNT(a,b) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \ a = G(pcre2_get_ovector_count_,BITONE)(G(b,BITONE)); \@@ -1746,12 +1813,18 @@ else \ G(pcre2_jit_stack_free_,BITTWO)((G(pcre2_jit_stack_,BITTWO) *)a); -#define PCRE2_MAKETABLES(a) \+#define PCRE2_MAKETABLES(a,c) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_maketables_,BITONE)(NULL); \+ a = G(pcre2_maketables_,BITONE)(G(c,BITONE)); \ else \- a = G(pcre2_maketables_,BITTWO)(NULL)+ a = G(pcre2_maketables_,BITTWO)(G(c,BITTWO)) +#define PCRE2_MAKETABLES_FREE(c,a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_maketables_free_,BITONE)(G(c,BITONE),a); \+ else \+ G(pcre2_maketables_free_,BITTWO)(G(c,BITTWO),a)+ #define PCRE2_MATCH(a,b,c,d,e,f,g,h) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \ a = G(pcre2_match_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \@@ -1762,15 +1835,15 @@ #define PCRE2_MATCH_DATA_CREATE(a,b,c) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(a,BITONE) = G(pcre2_match_data_create_,BITONE)(b,c); \+ G(a,BITONE) = G(pcre2_match_data_create_,BITONE)(b,G(c,BITONE)); \ else \- G(a,BITTWO) = G(pcre2_match_data_create_,BITTWO)(b,c)+ G(a,BITTWO) = G(pcre2_match_data_create_,BITTWO)(b,G(c,BITTWO)) #define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(a,BITONE) = G(pcre2_match_data_create_from_pattern_,BITONE)(G(b,BITONE),c); \+ G(a,BITONE) = G(pcre2_match_data_create_from_pattern_,BITONE)(G(b,BITONE),G(c,BITONE)); \ else \- G(a,BITTWO) = G(pcre2_match_data_create_from_pattern_,BITTWO)(G(b,BITTWO),c)+ G(a,BITTWO) = G(pcre2_match_data_create_from_pattern_,BITTWO)(G(b,BITTWO),G(c,BITTWO)) #define PCRE2_MATCH_DATA_FREE(a) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \@@ -1870,12 +1943,24 @@ else \ G(pcre2_set_match_limit_,BITTWO)(G(a,BITTWO),b) +#define PCRE2_SET_MAX_PATTERN_COMPILED_LENGTH(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_max_pattern_compiled_length_,BITONE)(G(a,BITONE),b); \+ else \+ G(pcre2_set_max_pattern_compiled_length_,BITTWO)(G(a,BITTWO),b)+ #define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \ G(pcre2_set_max_pattern_length_,BITONE)(G(a,BITONE),b); \ else \ G(pcre2_set_max_pattern_length_,BITTWO)(G(a,BITTWO),b) +#define PCRE2_SET_MAX_VARLOOKBEHIND(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_max_varlookbehind_,BITONE)(G(a,BITONE),b); \+ else \+ G(pcre2_set_max_varlookbehind_,BITTWO)(G(a,BITTWO),b)+ #define PCRE2_SET_OFFSET_LIMIT(a,b) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \ G(pcre2_set_offset_limit_,BITONE)(G(a,BITONE),b); \@@ -1965,9 +2050,9 @@ #define PCRE2_SUBSTRING_LIST_FREE(a) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_substring_list_free_,BITONE)((G(PCRE2_SPTR,BITONE) *)a); \+ G(pcre2_substring_list_free_,BITONE)((G(PCRE2_UCHAR,BITONE) **)a); \ else \- G(pcre2_substring_list_free_,BITTWO)((G(PCRE2_SPTR,BITTWO) *)a)+ G(pcre2_substring_list_free_,BITTWO)((G(PCRE2_UCHAR,BITTWO) **)a) #define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \@@ -2048,14 +2133,15 @@ #define PCRE2_CODE_COPY_FROM_VOID(a,b) G(a,8) = pcre2_code_copy_8(b) #define PCRE2_CODE_COPY_TO_VOID(a,b) a = (void *)pcre2_code_copy_8(G(b,8)) #define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) a = (void *)pcre2_code_copy_with_tables_8(G(b,8))-#define PCRE2_COMPILE(a,b,c,d,e,f,g) \- G(a,8) = pcre2_compile_8(G(b,8),c,d,e,f,g)+#define PCRE2_COMPILE(a,b,c,d,e,f,g) G(a,8) = pcre2_compile_8(b,c,d,e,f,g) #define PCRE2_CONVERTED_PATTERN_FREE(a) \ pcre2_converted_pattern_free_8((PCRE2_UCHAR8 *)a) #define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \ a = pcre2_dfa_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h,i,j) #define PCRE2_GET_ERROR_MESSAGE(r,a,b) \ r = pcre2_get_error_message_8(a,G(b,8),G(G(b,8),_size))+#define PCRE2_GET_MATCH_DATA_HEAPFRAMES_SIZE(r,a) \+ r = pcre2_get_match_data_heapframes_size_8(G(a,8)) #define PCRE2_GET_OVECTOR_COUNT(a,b) a = pcre2_get_ovector_count_8(G(b,8)) #define PCRE2_GET_STARTCHAR(a,b) a = pcre2_get_startchar_8(G(b,8)) #define PCRE2_JIT_COMPILE(r,a,b) r = pcre2_jit_compile_8(G(a,8),b)@@ -2067,12 +2153,13 @@ #define PCRE2_JIT_STACK_ASSIGN(a,b,c) \ pcre2_jit_stack_assign_8(G(a,8),(pcre2_jit_callback_8)b,c); #define PCRE2_JIT_STACK_FREE(a) pcre2_jit_stack_free_8((pcre2_jit_stack_8 *)a);-#define PCRE2_MAKETABLES(a) a = pcre2_maketables_8(NULL)+#define PCRE2_MAKETABLES(a,c) a = pcre2_maketables_8(G(c,8))+#define PCRE2_MAKETABLES_FREE(c,a) pcre2_maketables_free_8(G(c,8),a) #define PCRE2_MATCH(a,b,c,d,e,f,g,h) \ a = pcre2_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h)-#define PCRE2_MATCH_DATA_CREATE(a,b,c) G(a,8) = pcre2_match_data_create_8(b,c)+#define PCRE2_MATCH_DATA_CREATE(a,b,c) G(a,8) = pcre2_match_data_create_8(b,G(c,8)) #define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \- G(a,8) = pcre2_match_data_create_from_pattern_8(G(b,8),c)+ G(a,8) = pcre2_match_data_create_from_pattern_8(G(b,8),G(c,8)) #define PCRE2_MATCH_DATA_FREE(a) pcre2_match_data_free_8(G(a,8)) #define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) a = pcre2_pattern_convert_8(G(b,8),c,d,(PCRE2_UCHAR8 **)e,f,G(g,8)) #define PCRE2_PATTERN_INFO(a,b,c,d) a = pcre2_pattern_info_8(G(b,8),c,d)@@ -2094,7 +2181,9 @@ #define PCRE2_SET_GLOB_SEPARATOR(r,a,b) r = pcre2_set_glob_separator_8(G(a,8),b) #define PCRE2_SET_HEAP_LIMIT(a,b) pcre2_set_heap_limit_8(G(a,8),b) #define PCRE2_SET_MATCH_LIMIT(a,b) pcre2_set_match_limit_8(G(a,8),b)+#define PCRE2_SET_MAX_PATTERN_COMPILED_LENGTH(a,b) pcre2_set_max_pattern_compiled_length_8(G(a,8),b) #define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) pcre2_set_max_pattern_length_8(G(a,8),b)+#define PCRE2_SET_MAX_VARLOOKBEHIND(a,b) pcre2_set_max_varlookbehind_8(G(a,8),b) #define PCRE2_SET_OFFSET_LIMIT(a,b) pcre2_set_offset_limit_8(G(a,8),b) #define PCRE2_SET_PARENS_NEST_LIMIT(a,b) pcre2_set_parens_nest_limit_8(G(a,8),b) #define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \@@ -2119,7 +2208,7 @@ #define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \ a = pcre2_substring_list_get_8(G(b,8),(PCRE2_UCHAR8 ***)c,d) #define PCRE2_SUBSTRING_LIST_FREE(a) \- pcre2_substring_list_free_8((PCRE2_SPTR8 *)a)+ pcre2_substring_list_free_8((PCRE2_UCHAR8 **)a) #define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \ a = pcre2_substring_number_from_name_8(G(b,8),G(c,8)); #define PTR(x) (void *)G(x,8)@@ -2155,8 +2244,7 @@ #define PCRE2_CODE_COPY_FROM_VOID(a,b) G(a,16) = pcre2_code_copy_16(b) #define PCRE2_CODE_COPY_TO_VOID(a,b) a = (void *)pcre2_code_copy_16(G(b,16)) #define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) a = (void *)pcre2_code_copy_with_tables_16(G(b,16))-#define PCRE2_COMPILE(a,b,c,d,e,f,g) \- G(a,16) = pcre2_compile_16(G(b,16),c,d,e,f,g)+#define PCRE2_COMPILE(a,b,c,d,e,f,g) G(a,16) = pcre2_compile_16(b,c,d,e,f,g) #define PCRE2_CONVERTED_PATTERN_FREE(a) \ pcre2_converted_pattern_free_16((PCRE2_UCHAR16 *)a) #define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \@@ -2164,6 +2252,8 @@ #define PCRE2_GET_ERROR_MESSAGE(r,a,b) \ r = pcre2_get_error_message_16(a,G(b,16),G(G(b,16),_size/2)) #define PCRE2_GET_OVECTOR_COUNT(a,b) a = pcre2_get_ovector_count_16(G(b,16))+#define PCRE2_GET_MATCH_DATA_HEAPFRAMES_SIZE(r,a) \+ r = pcre2_get_match_data_heapframes_size_16(G(a,16)) #define PCRE2_GET_STARTCHAR(a,b) a = pcre2_get_startchar_16(G(b,16)) #define PCRE2_JIT_COMPILE(r,a,b) r = pcre2_jit_compile_16(G(a,16),b) #define PCRE2_JIT_FREE_UNUSED_MEMORY(a) pcre2_jit_free_unused_memory_16(G(a,16))@@ -2174,12 +2264,13 @@ #define PCRE2_JIT_STACK_ASSIGN(a,b,c) \ pcre2_jit_stack_assign_16(G(a,16),(pcre2_jit_callback_16)b,c); #define PCRE2_JIT_STACK_FREE(a) pcre2_jit_stack_free_16((pcre2_jit_stack_16 *)a);-#define PCRE2_MAKETABLES(a) a = pcre2_maketables_16(NULL)+#define PCRE2_MAKETABLES(a,c) a = pcre2_maketables_16(G(c,16))+#define PCRE2_MAKETABLES_FREE(c,a) pcre2_maketables_free_16(G(c,16),a) #define PCRE2_MATCH(a,b,c,d,e,f,g,h) \ a = pcre2_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h)-#define PCRE2_MATCH_DATA_CREATE(a,b,c) G(a,16) = pcre2_match_data_create_16(b,c)+#define PCRE2_MATCH_DATA_CREATE(a,b,c) G(a,16) = pcre2_match_data_create_16(b,G(c,16)) #define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \- G(a,16) = pcre2_match_data_create_from_pattern_16(G(b,16),c)+ G(a,16) = pcre2_match_data_create_from_pattern_16(G(b,16),G(c,16)) #define PCRE2_MATCH_DATA_FREE(a) pcre2_match_data_free_16(G(a,16)) #define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) a = pcre2_pattern_convert_16(G(b,16),c,d,(PCRE2_UCHAR16 **)e,f,G(g,16)) #define PCRE2_PATTERN_INFO(a,b,c,d) a = pcre2_pattern_info_16(G(b,16),c,d)@@ -2201,7 +2292,7 @@ #define PCRE2_SET_GLOB_SEPARATOR(r,a,b) r = pcre2_set_glob_separator_16(G(a,16),b) #define PCRE2_SET_HEAP_LIMIT(a,b) pcre2_set_heap_limit_16(G(a,16),b) #define PCRE2_SET_MATCH_LIMIT(a,b) pcre2_set_match_limit_16(G(a,16),b)-#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) pcre2_set_max_pattern_length_16(G(a,16),b)+#define PCRE2_SET_MAX_VARLOOKBEHIND(a,b) pcre2_set_max_varlookbehind_16(G(a,16),b) #define PCRE2_SET_OFFSET_LIMIT(a,b) pcre2_set_offset_limit_16(G(a,16),b) #define PCRE2_SET_PARENS_NEST_LIMIT(a,b) pcre2_set_parens_nest_limit_16(G(a,16),b) #define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \@@ -2226,7 +2317,7 @@ #define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \ a = pcre2_substring_list_get_16(G(b,16),(PCRE2_UCHAR16 ***)c,d) #define PCRE2_SUBSTRING_LIST_FREE(a) \- pcre2_substring_list_free_16((PCRE2_SPTR16 *)a)+ pcre2_substring_list_free_16((PCRE2_UCHAR16 **)a) #define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \ a = pcre2_substring_number_from_name_16(G(b,16),G(c,16)); #define PTR(x) (void *)G(x,16)@@ -2262,8 +2353,7 @@ #define PCRE2_CODE_COPY_FROM_VOID(a,b) G(a,32) = pcre2_code_copy_32(b) #define PCRE2_CODE_COPY_TO_VOID(a,b) a = (void *)pcre2_code_copy_32(G(b,32)) #define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) a = (void *)pcre2_code_copy_with_tables_32(G(b,32))-#define PCRE2_COMPILE(a,b,c,d,e,f,g) \- G(a,32) = pcre2_compile_32(G(b,32),c,d,e,f,g)+#define PCRE2_COMPILE(a,b,c,d,e,f,g) G(a,32) = pcre2_compile_32(b,c,d,e,f,g) #define PCRE2_CONVERTED_PATTERN_FREE(a) \ pcre2_converted_pattern_free_32((PCRE2_UCHAR32 *)a) #define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \@@ -2271,6 +2361,8 @@ #define PCRE2_GET_ERROR_MESSAGE(r,a,b) \ r = pcre2_get_error_message_32(a,G(b,32),G(G(b,32),_size/4)) #define PCRE2_GET_OVECTOR_COUNT(a,b) a = pcre2_get_ovector_count_32(G(b,32))+#define PCRE2_GET_MATCH_DATA_HEAPFRAMES_SIZE(r,a) \+ r = pcre2_get_match_data_heapframes_size_32(G(a,32)) #define PCRE2_GET_STARTCHAR(a,b) a = pcre2_get_startchar_32(G(b,32)) #define PCRE2_JIT_COMPILE(r,a,b) r = pcre2_jit_compile_32(G(a,32),b) #define PCRE2_JIT_FREE_UNUSED_MEMORY(a) pcre2_jit_free_unused_memory_32(G(a,32))@@ -2281,12 +2373,13 @@ #define PCRE2_JIT_STACK_ASSIGN(a,b,c) \ pcre2_jit_stack_assign_32(G(a,32),(pcre2_jit_callback_32)b,c); #define PCRE2_JIT_STACK_FREE(a) pcre2_jit_stack_free_32((pcre2_jit_stack_32 *)a);-#define PCRE2_MAKETABLES(a) a = pcre2_maketables_32(NULL)+#define PCRE2_MAKETABLES(a,c) a = pcre2_maketables_32(G(c,32))+#define PCRE2_MAKETABLES_FREE(c,a) pcre2_maketables_free_32(G(c,32),a) #define PCRE2_MATCH(a,b,c,d,e,f,g,h) \ a = pcre2_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h)-#define PCRE2_MATCH_DATA_CREATE(a,b,c) G(a,32) = pcre2_match_data_create_32(b,c)+#define PCRE2_MATCH_DATA_CREATE(a,b,c) G(a,32) = pcre2_match_data_create_32(b,G(c,32)) #define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \- G(a,32) = pcre2_match_data_create_from_pattern_32(G(b,32),c)+ G(a,32) = pcre2_match_data_create_from_pattern_32(G(b,32),G(c,32)) #define PCRE2_MATCH_DATA_FREE(a) pcre2_match_data_free_32(G(a,32)) #define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) a = pcre2_pattern_convert_32(G(b,32),c,d,(PCRE2_UCHAR32 **)e,f,G(g,32)) #define PCRE2_PATTERN_INFO(a,b,c,d) a = pcre2_pattern_info_32(G(b,32),c,d)@@ -2308,7 +2401,7 @@ #define PCRE2_SET_GLOB_SEPARATOR(r,a,b) r = pcre2_set_glob_separator_32(G(a,32),b) #define PCRE2_SET_HEAP_LIMIT(a,b) pcre2_set_heap_limit_32(G(a,32),b) #define PCRE2_SET_MATCH_LIMIT(a,b) pcre2_set_match_limit_32(G(a,32),b)-#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) pcre2_set_max_pattern_length_32(G(a,32),b)+#define PCRE2_SET_MAX_VARLOOKBEHIND(a,b) pcre2_set_max_varlookbehind_32(G(a,32),b) #define PCRE2_SET_OFFSET_LIMIT(a,b) pcre2_set_offset_limit_32(G(a,32),b) #define PCRE2_SET_PARENS_NEST_LIMIT(a,b) pcre2_set_parens_nest_limit_32(G(a,32),b) #define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \@@ -2333,7 +2426,7 @@ #define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \ a = pcre2_substring_list_get_32(G(b,32),(PCRE2_UCHAR32 ***)c,d) #define PCRE2_SUBSTRING_LIST_FREE(a) \- pcre2_substring_list_free_32((PCRE2_SPTR32 *)a)+ pcre2_substring_list_free_32((PCRE2_UCHAR32 **)a) #define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \ a = pcre2_substring_number_from_name_32(G(b,32),G(c,32)); #define PTR(x) (void *)G(x,32)@@ -2748,7 +2841,7 @@ /* Alternative memory functions, to test functionality. */ -static void *my_malloc(PCRE2_SIZE size, void *data)+static void *my_malloc(size_t size, void *data) { void *block = malloc(size); (void)data;@@ -2780,7 +2873,7 @@ static void my_free(void *block, void *data) { (void)data;-if (show_memory)+if (show_memory && block != NULL) { uint32_t i, j; BOOL found = FALSE;@@ -2858,6 +2951,7 @@ Argument: utf8bytes a pointer to the byte vector+ end a pointer to the end of the byte vector vptr a pointer to an int to receive the value Returns: > 0 => the number of bytes consumed@@ -2865,7 +2959,7 @@ */ static int-utf82ord(PCRE2_SPTR8 utf8bytes, uint32_t *vptr)+utf82ord(PCRE2_SPTR8 utf8bytes, PCRE2_SPTR8 end, uint32_t *vptr) { uint32_t c = *utf8bytes++; uint32_t d = c;@@ -2887,6 +2981,8 @@ for (j = 0; j < i; j++) {+ if (utf8bytes >= end) return 0;+ c = *utf8bytes++; if ((c & 0xc0) != 0x80) return -(j+1); s -= 6;@@ -2997,14 +3093,16 @@ static int pchars8(PCRE2_SPTR8 p, int length, BOOL utf, FILE *f) {+PCRE2_SPTR8 end; uint32_t c = 0; int yield = 0; if (length < 0) length = *p++;+end = p + length; while (length-- > 0) { if (utf) {- int rc = utf82ord(p, &c);+ int rc = utf82ord(p, end, &c); if (rc > 0 && rc <= length + 1) /* Mustn't run over the end */ { length -= rc - 1;@@ -3183,7 +3281,8 @@ else while (len > 0) { uint32_t c;- int chlen = utf82ord(p, &c);+ const uint8_t *end = p + len;+ int chlen = utf82ord(p, end, &c); if (chlen <= 0) return -1; if (!utf && c > 0xffff) return -3; if (c > 0x10ffff) return -2;@@ -3274,13 +3373,14 @@ int chlen; uint32_t c; uint32_t topbit = 0;+ const uint8_t *end = p + len; if (!utf && *p == 0xff && len > 1) { topbit = 0x80000000u; p++; len--; }- chlen = utf82ord(p, &c);+ chlen = utf82ord(p, end, &c); if (chlen <= 0) return -1; if (utf && c > 0x10ffff) return -2; p += chlen;@@ -4112,7 +4212,7 @@ static void show_controls(uint32_t controls, uint32_t controls2, const char *before) {-fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",+fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", before, ((controls & CTL_AFTERTEXT) != 0)? " aftertext" : "", ((controls & CTL_ALLAFTERTEXT) != 0)? " allaftertext" : "",@@ -4130,10 +4230,12 @@ ((controls & CTL_DFA) != 0)? " dfa" : "", ((controls & CTL_EXPAND) != 0)? " expand" : "", ((controls & CTL_FINDLIMITS) != 0)? " find_limits" : "",- ((controls & CTL_FRAMESIZE) != 0)? " framesize" : "",+ ((controls & CTL_FINDLIMITS_NOHEAP) != 0)? " find_limits_noheap" : "",+ ((controls2 & CTL2_FRAMESIZE) != 0)? " framesize" : "", ((controls & CTL_FULLBINCODE) != 0)? " fullbincode" : "", ((controls & CTL_GETALL) != 0)? " getall" : "", ((controls & CTL_GLOBAL) != 0)? " global" : "",+ ((controls2 & CTL2_HEAPFRAMES_SIZE) != 0)? " heapframes_size" : "", ((controls & CTL_HEXPAT) != 0)? " hex" : "", ((controls & CTL_INFO) != 0)? " info" : "", ((controls & CTL_JITFAST) != 0)? " jitfast" : "",@@ -4238,14 +4340,20 @@ const char *after) { if (options == 0) fprintf(outfile, "%s <none>%s", before, after);-else fprintf(outfile, "%s%s%s%s%s%s%s%s",+else fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", before, ((options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) != 0)? " allow_surrogate_escapes" : "",+ ((options & PCRE2_EXTRA_ALT_BSUX) != 0)? " alt_bsux" : "",+ ((options & PCRE2_EXTRA_ASCII_BSD) != 0)? " ascii_bsd" : "",+ ((options & PCRE2_EXTRA_ASCII_BSS) != 0)? " ascii_bss" : "",+ ((options & PCRE2_EXTRA_ASCII_BSW) != 0)? " ascii_bsw" : "",+ ((options & PCRE2_EXTRA_ASCII_DIGIT) != 0)? " ascii_digit" : "",+ ((options & PCRE2_EXTRA_ASCII_POSIX) != 0)? " ascii_posix" : "", ((options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) != 0)? " bad_escape_is_literal" : "",- ((options & PCRE2_EXTRA_ALT_BSUX) != 0)? " extra_alt_bsux" : "",+ ((options & PCRE2_EXTRA_CASELESS_RESTRICT) != 0)? " caseless_restrict" : "",+ ((options & PCRE2_EXTRA_ESCAPED_CR_IS_LF) != 0)? " escaped_cr_is_lf" : "", ((options & PCRE2_EXTRA_MATCH_WORD) != 0)? " match_word" : "", ((options & PCRE2_EXTRA_MATCH_LINE) != 0)? " match_line" : "",- ((options & PCRE2_EXTRA_ESCAPED_CR_IS_LF) != 0)? " escaped_cr_is_lf" : "", after); } @@ -4261,11 +4369,12 @@ static void show_match_options(uint32_t options) {-fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s",+fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", ((options & PCRE2_ANCHORED) != 0)? " anchored" : "", ((options & PCRE2_COPY_MATCHED_SUBJECT) != 0)? " copy_matched_subject" : "", ((options & PCRE2_DFA_RESTART) != 0)? " dfa_restart" : "", ((options & PCRE2_DFA_SHORTEST) != 0)? " dfa_shortest" : "",+ ((options & PCRE2_DISABLE_RECURSELOOP_CHECK) != 0)? " disable_recurseloop_check" : "", ((options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "", ((options & PCRE2_NO_JIT) != 0)? " no_jit" : "", ((options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",@@ -4288,7 +4397,7 @@ show_memory_info(void) { uint32_t name_count, name_entry_size;-size_t size, cblock_size;+PCRE2_SIZE size, cblock_size; /* One of the test_mode values will always be true, but to stop a compiler warning we must initialize cblock_size. */@@ -4307,12 +4416,19 @@ (void)pattern_info(PCRE2_INFO_SIZE, &size, FALSE); (void)pattern_info(PCRE2_INFO_NAMECOUNT, &name_count, FALSE); (void)pattern_info(PCRE2_INFO_NAMEENTRYSIZE, &name_entry_size, FALSE);-fprintf(outfile, "Memory allocation (code space): %d\n",- (int)(size - name_count*name_entry_size*code_unit_size - cblock_size));++/* The uint32_t variables are cast before multiplying to stop code analyzers+grumbling about potential overflow. */++fprintf(outfile, "Memory allocation - compiled block : %" SIZ_FORM "\n", size);+fprintf(outfile, "Memory allocation - code portion : %" SIZ_FORM "\n", size -+ (PCRE2_SIZE)name_count * (PCRE2_SIZE)name_entry_size * (PCRE2_SIZE)code_unit_size -+ cblock_size);+ if (pat_patctl.jit != 0) { (void)pattern_info(PCRE2_INFO_JITSIZE, &size, FALSE);- fprintf(outfile, "Memory allocation (JIT code): %d\n", (int)size);+ fprintf(outfile, "Memory allocation - JIT code : %" SIZ_FORM "\n", size); } } @@ -4325,14 +4441,29 @@ static void show_framesize(void) {-size_t frame_size;+PCRE2_SIZE frame_size; (void)pattern_info(PCRE2_INFO_FRAMESIZE, &frame_size, FALSE);-fprintf(outfile, "Frame size for pcre2_match(): %d\n", (int)frame_size);+fprintf(outfile, "Frame size for pcre2_match(): %" SIZ_FORM "\n", frame_size); } /*************************************************+* Show heapframes size info for a match_data *+*************************************************/++static void+show_heapframes_size(void)+{+PCRE2_SIZE heapframes_size;+PCRE2_GET_MATCH_DATA_HEAPFRAMES_SIZE(heapframes_size, match_data);+fprintf(outfile, "Heapframes size in match_data: %" SIZ_FORM "\n",+ heapframes_size);+}++++/************************************************* * Get and output an error message * *************************************************/ @@ -4749,19 +4880,19 @@ if (pat_patctl.jit != 0 && (pat_patctl.control & CTL_JITVERIFY) != 0) {+#ifdef SUPPORT_JIT if (FLD(compiled_code, executable_jit) != NULL) fprintf(outfile, "JIT compilation was successful\n"); else {-#ifdef SUPPORT_JIT fprintf(outfile, "JIT compilation was not successful"); if (jitrc != 0 && !print_error_message(jitrc, " (", ")")) return PR_ABEND; fprintf(outfile, "\n");+ } #else fprintf(outfile, "JIT support is not available in this version of PCRE2\n"); #endif- } } } @@ -4980,7 +5111,7 @@ PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit); } if ((pat_patctl.control & CTL_MEMORY) != 0) show_memory_info();- if ((pat_patctl.control & CTL_FRAMESIZE) != 0) show_framesize();+ if ((pat_patctl.control2 & CTL2_FRAMESIZE) != 0) show_framesize(); if ((pat_patctl.control & CTL_ANYINFO) != 0) { rc = show_pattern_info();@@ -5146,6 +5277,7 @@ unsigned int delimiter = *p++; int errorcode; void *use_pat_context;+void *use_pbuffer = NULL; uint32_t use_forbid_utf = forbid_utf; PCRE2_SIZE patlen; PCRE2_SIZE valgrind_access_length;@@ -5426,8 +5558,11 @@ if (strcmp((const char *)pat_patctl.locale, (const char *)locale_name) != 0) { strcpy((char *)locale_name, (char *)pat_patctl.locale);- if (locale_tables != NULL) free((void *)locale_tables);- PCRE2_MAKETABLES(locale_tables);+ if (locale_tables != NULL)+ {+ PCRE2_MAKETABLES_FREE(general_context, (void *)locale_tables);+ }+ PCRE2_MAKETABLES(locale_tables, general_context); } use_tables = locale_tables; }@@ -5515,11 +5650,19 @@ pat_patctl.control2 & (uint32_t)(~POSIX_SUPPORTED_COMPILE_CONTROLS2), msg); msg = "";++ /* Remove ignored options so as not to get a repeated message for those+ that are actually subject controls. */++ pat_patctl.control &= (uint32_t)(POSIX_SUPPORTED_COMPILE_CONTROLS);+ pat_patctl.control2 &= (uint32_t)(POSIX_SUPPORTED_COMPILE_CONTROLS2); } if (local_newline_default != 0) prmsg(&msg, "#newline_default"); if (FLD(pat_context, max_pattern_length) != PCRE2_UNSET) prmsg(&msg, "max_pattern_length");+ if (FLD(pat_context, max_pattern_compiled_length) != PCRE2_UNSET)+ prmsg(&msg, "max_pattern_compiled_length"); if (FLD(pat_context, parens_nest_limit) != PARENS_NEST_DEFAULT) prmsg(&msg, "parens_nest_limit"); @@ -5732,10 +5875,27 @@ else {+ BOOL toolong; PCHARSV(converted_pattern, 0, converted_length, utf, outfile); fprintf(outfile, "\n");- patlen = converted_length;- CONVERT_COPY(pbuffer, converted_pattern, converted_length + 1);++ if (test_mode == PCRE8_MODE)+ toolong = (converted_length + 1 > pbuffer8_size);+ else if (test_mode == PCRE16_MODE)+ toolong = (2*(converted_length + 1) > pbuffer8_size);+ else /* 32-bit */+ toolong = (4*(converted_length + 1) > pbuffer8_size);++ if (toolong)+ {+ fprintf(outfile, "** Pattern conversion is too long for the buffer\n");+ convert_return = PR_SKIP;+ }+ else+ {+ CONVERT_COPY(pbuffer, converted_pattern, converted_length + 1);+ patlen = converted_length;+ } } /* Free the converted pattern. */@@ -5809,6 +5969,21 @@ if ((pat_patctl.options & PCRE2_LITERAL) != 0) use_forbid_utf = 0; +/* Set use_pbuffer to the input buffer, or leave it as NULL if requested. */++if ((pat_patctl.control2 & CTL2_NULL_PATTERN) == 0)+ {+#ifdef SUPPORT_PCRE2_8+ if (test_mode == PCRE8_MODE) use_pbuffer = pbuffer8;+#endif+#ifdef SUPPORT_PCRE2_16+ if (test_mode == PCRE16_MODE) use_pbuffer = pbuffer16;+#endif+#ifdef SUPPORT_PCRE2_32+ if (test_mode == PCRE32_MODE) use_pbuffer = pbuffer32;+#endif+ }+ /* Compile many times when timing. */ if (timeit > 0)@@ -5818,7 +5993,7 @@ for (i = 0; i < timeit; i++) { clock_t start_time = clock();- PCRE2_COMPILE(compiled_code, pbuffer, patlen,+ PCRE2_COMPILE(compiled_code, use_pbuffer, patlen, pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset, use_pat_context); time_taken += clock() - start_time;@@ -5826,16 +6001,42 @@ { SUB1(pcre2_code_free, compiled_code); } } total_compile_time += time_taken;- fprintf(outfile, "Compile time %.4f milliseconds\n",- (((double)time_taken * 1000.0) / (double)timeit) /- (double)CLOCKS_PER_SEC);+ fprintf(outfile, "Compile time %8.4f microseconds\n",+ ((1000000 / CLOCKS_PER_SEC) * (double)time_taken) / timeit); } /* A final compile that is used "for real". */ -PCRE2_COMPILE(compiled_code, pbuffer, patlen, pat_patctl.options|use_forbid_utf,- &errorcode, &erroroffset, use_pat_context);+PCRE2_COMPILE(compiled_code, use_pbuffer, patlen,+ pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset, use_pat_context); +/* If valgrind is supported, mark the pbuffer as accessible again. The 16-bit+and 32-bit buffers can be marked completely undefined, but we must leave the+pattern in the 8-bit buffer defined because it may be read from a callout+during matching. */++#ifdef SUPPORT_VALGRIND+#ifdef SUPPORT_PCRE2_8+if (test_mode == PCRE8_MODE)+ {+ VALGRIND_MAKE_MEM_UNDEFINED(pbuffer8 + valgrind_access_length,+ pbuffer8_size - valgrind_access_length);+ }+#endif+#ifdef SUPPORT_PCRE2_16+if (test_mode == PCRE16_MODE)+ {+ VALGRIND_MAKE_MEM_UNDEFINED(pbuffer16, pbuffer16_size);+ }+#endif+#ifdef SUPPORT_PCRE2_32+if (test_mode == PCRE32_MODE)+ {+ VALGRIND_MAKE_MEM_UNDEFINED(pbuffer32, pbuffer32_size);+ }+#endif+#endif+ /* Call the JIT compiler if requested. When timing, we must free and recompile the pattern each time because that is the only way to free the JIT compiled code. We know that compilation will always succeed. */@@ -5851,51 +6052,35 @@ { clock_t start_time; SUB1(pcre2_code_free, compiled_code);- PCRE2_COMPILE(compiled_code, pbuffer, patlen,+ PCRE2_COMPILE(compiled_code, use_pbuffer, patlen, pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset, use_pat_context); start_time = clock(); PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit); time_taken += clock() - start_time;+ if (jitrc != 0)+ {+ fprintf(outfile, "JIT compilation was not successful");+ if (!print_error_message(jitrc, " (", ")\n")) return PR_ABEND;+ break;+ } } total_jit_compile_time += time_taken;- fprintf(outfile, "JIT compile %.4f milliseconds\n",- (((double)time_taken * 1000.0) / (double)timeit) /- (double)CLOCKS_PER_SEC);+ if (jitrc == 0)+ fprintf(outfile, "JIT compile %8.4f microseconds\n",+ ((1000000 / CLOCKS_PER_SEC) * (double)time_taken) / timeit); } else { PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit);+ if (jitrc != 0 && (pat_patctl.control & CTL_JITVERIFY) != 0)+ {+ fprintf(outfile, "JIT compilation was not successful");+ if (!print_error_message(jitrc, " (", ")\n")) return PR_ABEND;+ } } } -/* If valgrind is supported, mark the pbuffer as accessible again. The 16-bit-and 32-bit buffers can be marked completely undefined, but we must leave the-pattern in the 8-bit buffer defined because it may be read from a callout-during matching. */--#ifdef SUPPORT_VALGRIND-#ifdef SUPPORT_PCRE2_8-if (test_mode == PCRE8_MODE)- {- VALGRIND_MAKE_MEM_UNDEFINED(pbuffer8 + valgrind_access_length,- pbuffer8_size - valgrind_access_length);- }-#endif-#ifdef SUPPORT_PCRE2_16-if (test_mode == PCRE16_MODE)- {- VALGRIND_MAKE_MEM_UNDEFINED(pbuffer16, pbuffer16_size);- }-#endif-#ifdef SUPPORT_PCRE2_32-if (test_mode == PCRE32_MODE)- {- VALGRIND_MAKE_MEM_UNDEFINED(pbuffer32, pbuffer32_size);- }-#endif-#endif- /* Compilation failed; go back for another re, skipping to blank line if non-interactive. */ @@ -5942,7 +6127,7 @@ /* Output code size and other information if requested. */ if ((pat_patctl.control & CTL_MEMORY) != 0) show_memory_info();-if ((pat_patctl.control & CTL_FRAMESIZE) != 0) show_framesize();+if ((pat_patctl.control2 & CTL2_FRAMESIZE) != 0) show_framesize(); if ((pat_patctl.control & CTL_ANYINFO) != 0) { int rc = show_pattern_info();@@ -6021,10 +6206,46 @@ { uint32_t stack_start = 0; + /* If we are checking the heap limit, free any frames vector that is cached+ in the match_data so we always start without one. */+ if (errnumber == PCRE2_ERROR_HEAPLIMIT) { PCRE2_SET_HEAP_LIMIT(dat_context, mid);++#ifdef SUPPORT_PCRE2_8+ if (code_unit_size == 1)+ {+ match_data8->memctl.free(match_data8->heapframes,+ match_data8->memctl.memory_data);+ match_data8->heapframes = NULL;+ match_data8->heapframes_size = 0;+ }+#endif++#ifdef SUPPORT_PCRE2_16+ if (code_unit_size == 2)+ {+ match_data16->memctl.free(match_data16->heapframes,+ match_data16->memctl.memory_data);+ match_data16->heapframes = NULL;+ match_data16->heapframes_size = 0;+ }+#endif++#ifdef SUPPORT_PCRE2_32+ if (code_unit_size == 4)+ {+ match_data32->memctl.free(match_data32->heapframes,+ match_data32->memctl.memory_data);+ match_data32->heapframes = NULL;+ match_data32->heapframes_size = 0;+ }+#endif }++ /* No need to mess with the frames vector for match or depth limits. */+ else if (errnumber == PCRE2_ERROR_MATCHLIMIT) { PCRE2_SET_MATCH_LIMIT(dat_context, mid);@@ -6034,6 +6255,8 @@ PCRE2_SET_DEPTH_LIMIT(dat_context, mid); } + /* Do the appropriate match */+ if ((dat_datctl.control & CTL_DFA) != 0) { stack_start = DFA_START_RWS_SIZE/1024;@@ -6052,7 +6275,6 @@ else {- stack_start = START_FRAMES_SIZE/1024; PCRE2_MATCH(capcount, compiled_code, pp, ulen, dat_datctl.offset, dat_datctl.options, match_data, PTR(dat_context)); }@@ -6707,7 +6929,9 @@ uint8_t *q; uint32_t cc; int n = 1;- for (q = p; n > 0 && *q; q += n) n = utf82ord(q, &cc);+ uint8_t *q_end = p + len;++ for (q = p; n > 0 && *q; q += n) n = utf82ord(q, q_end, &cc); if (n <= 0) { fprintf(outfile, "** Failed: invalid UTF-8 string cannot be used as input "@@ -6728,14 +6952,18 @@ the number of code units that will be needed (though the buffer may have to be extended if replication is involved). */ -needlen = (size_t)((len+1) * code_unit_size);+needlen = (len+1) * code_unit_size; if (dbuffer == NULL || needlen >= dbuffer_size) {- while (needlen >= dbuffer_size) dbuffer_size *= 2;+ while (needlen >= dbuffer_size)+ {+ if (dbuffer_size < SIZE_MAX/2) dbuffer_size *= 2;+ else dbuffer_size = needlen + 1;+ } dbuffer = (uint8_t *)realloc(dbuffer, dbuffer_size); if (dbuffer == NULL) {- fprintf(stderr, "pcre2test: realloc(%d) failed\n", (int)dbuffer_size);+ fprintf(stderr, "pcre2test: realloc(%" SIZ_FORM ") failed\n", dbuffer_size); exit(1); } }@@ -6755,10 +6983,9 @@ if (c == ']' && start_rep != NULL) {+ PCRE2_SIZE d; long li; char *endptr;- size_t qoffset = CAST8VAR(q) - dbuffer;- size_t rep_offset = start_rep - dbuffer; if (*p++ != '{') {@@ -6781,22 +7008,34 @@ } i = (int32_t)li;- if (i-- == 0)+ if (i-- <= 0) {- fprintf(outfile, "** Zero repeat not allowed\n");+ fprintf(outfile, "** Zero or negative repeat not allowed\n"); return PR_OK; } replen = CAST8VAR(q) - start_rep;- needlen += replen * i;+ if (PRIV(ckd_smul)(&d, replen, i))+ {+ fprintf(outfile, "** Expanded content too large\n");+ return PR_OK;+ }+ needlen += d; if (needlen >= dbuffer_size) {- while (needlen >= dbuffer_size) dbuffer_size *= 2;+ size_t qoffset = CAST8VAR(q) - dbuffer;+ size_t rep_offset = start_rep - dbuffer;+ while (needlen >= dbuffer_size)+ {+ if (dbuffer_size < SIZE_MAX/2) dbuffer_size *= 2;+ else dbuffer_size = needlen + 1;+ } dbuffer = (uint8_t *)realloc(dbuffer, dbuffer_size); if (dbuffer == NULL) {- fprintf(stderr, "pcre2test: realloc(%d) failed\n", (int)dbuffer_size);+ fprintf(stderr, "pcre2test: realloc(%" SIZ_FORM ") failed\n",+ dbuffer_size); exit(1); } SETCASTPTR(q, dbuffer + qoffset);@@ -7058,7 +7297,9 @@ if ((dat_datctl.control & CTL_DFA) != 0) { if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)- fprintf(outfile, "** Ignored after DFA matching: allcaptures\n");+ fprintf(outfile, "** Ignored for DFA matching: allcaptures\n");+ if ((dat_datctl.control2 & CTL2_HEAPFRAMES_SIZE) != 0)+ fprintf(outfile, "** Ignored for DFA matching: heapframes_size\n"); } /* We now have the subject in dbuffer, with len containing the byte length, and@@ -7113,6 +7354,7 @@ show_match_options(dat_datctl.options & ~POSIX_SUPPORTED_MATCH_OPTIONS); msg = ""; }+ if ((dat_datctl.control & ~POSIX_SUPPORTED_MATCH_CONTROLS) != 0 || (dat_datctl.control2 & ~POSIX_SUPPORTED_MATCH_CONTROLS2) != 0) {@@ -7270,7 +7512,8 @@ if (dat_datctl.oveccount == 0) { PCRE2_MATCH_DATA_FREE(match_data);- PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(match_data, compiled_code, NULL);+ PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(match_data, compiled_code,+ general_context); PCRE2_GET_OVECTOR_COUNT(max_oveccount, match_data); } else if (dat_datctl.oveccount <= max_oveccount)@@ -7281,7 +7524,7 @@ { max_oveccount = dat_datctl.oveccount; PCRE2_MATCH_DATA_FREE(match_data);- PCRE2_MATCH_DATA_CREATE(match_data, max_oveccount, NULL);+ PCRE2_MATCH_DATA_CREATE(match_data, max_oveccount, general_context); } if (CASTVAR(void *, match_data) == NULL)@@ -7303,9 +7546,9 @@ dat_datctl.replacement[0] = 0; } -/* If a replacement string is provided, call pcre2_substitute() instead of one-of the matching functions. First we have to convert the replacement string to-the appropriate width. */+/* If a replacement string is provided, call pcre2_substitute() instead of or+after one of the matching functions. First we have to convert the replacement+string to the appropriate width. */ if (dat_datctl.replacement[0] != 0) {@@ -7349,8 +7592,16 @@ if (emoption != 0) {- PCRE2_MATCH(rc, compiled_code, pp, arg_ulen, dat_datctl.offset,- dat_datctl.options, match_data, use_dat_context);+ if ((pat_patctl.control & CTL_JITFAST) != 0)+ {+ PCRE2_JIT_MATCH(rc, compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options, match_data, use_dat_context);+ }+ else+ {+ PCRE2_MATCH(rc, compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options, match_data, use_dat_context);+ } } xoptions = emoption |@@ -7493,11 +7744,15 @@ fprintf(outfile, "\n"); show_memory = FALSE; - /* Show final ovector contents if requested. */+ /* Show final ovector contents and resulting heapframe size if requested. */ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0) show_ovector(ovector, oveccount); + if ((dat_datctl.control2 & CTL2_HEAPFRAMES_SIZE) != 0 &&+ (dat_datctl.control & CTL_DFA) == 0)+ show_heapframes_size();+ return PR_OK; } /* End of substitution handling */ @@ -7569,21 +7824,21 @@ } } total_match_time += (time_taken = clock() - start_time);- fprintf(outfile, "Match time %.4f milliseconds\n",- (((double)time_taken * 1000.0) / (double)timeitm) /- (double)CLOCKS_PER_SEC);+ fprintf(outfile, "Match time %7.4f microseconds\n",+ ((1000000 / CLOCKS_PER_SEC) * (double)time_taken) / timeitm); } /* Find the heap, match and depth limits if requested. The depth and heap limits are not relevant for JIT. The return from check_match_limit() is the return from the final call to pcre2_match() or pcre2_dfa_match(). */ - if ((dat_datctl.control & CTL_FINDLIMITS) != 0)+ if ((dat_datctl.control & (CTL_FINDLIMITS|CTL_FINDLIMITS_NOHEAP)) != 0) { capcount = 0; /* This stops compiler warnings */ - if (FLD(compiled_code, executable_jit) == NULL ||- (dat_datctl.options & PCRE2_NO_JIT) != 0)+ if ((dat_datctl.control & CTL_FINDLIMITS_NOHEAP) == 0 &&+ (FLD(compiled_code, executable_jit) == NULL ||+ (dat_datctl.options & PCRE2_NO_JIT) != 0)) { (void)check_match_limit(pp, arg_ulen, PCRE2_ERROR_HEAPLIMIT, "heap"); }@@ -7913,7 +8168,7 @@ rubriclength += 15; PCHARS(backlength, pp, leftchar, ovector[0] - leftchar, utf, outfile);- PCHARSV(pp, ovector[0], ulen - ovector[0], utf, outfile);+ PCHARSV(pp, ovector[0], ovector[1] - ovector[0], utf, outfile); if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used) fprintf(outfile, " (JIT)");@@ -8131,6 +8386,12 @@ } } /* End of global loop */ +/* All matching is done; show the resulting heapframe size if requested. */++if ((dat_datctl.control2 & CTL2_HEAPFRAMES_SIZE) != 0 &&+ (dat_datctl.control & CTL_DFA) == 0)+ show_heapframes_size();+ show_memory = FALSE; return PR_OK; }@@ -8143,11 +8404,17 @@ *************************************************/ static void-print_version(FILE *f)+print_version(FILE *f, BOOL include_mode) {+char buf[16]; VERSION_TYPE *vp; fprintf(f, "PCRE2 version "); for (vp = version; *vp != 0; vp++) fprintf(f, "%c", *vp);+if (include_mode)+ {+ sprintf(buf, "%d-bit", test_mode);+ fprintf(f, " (%s)", buf);+ } fprintf(f, "\n"); } @@ -8264,7 +8531,7 @@ printf(" -tm [<n>] time execution (matching) only, repeating <n> times\n"); printf(" -T same as -t, but show total times at the end\n"); printf(" -TM same as -tm, but show total time at the end\n");-printf(" -version show PCRE2 version and exit\n");+printf(" -v|--version show PCRE2 version and exit\n"); } @@ -8365,7 +8632,7 @@ /* No argument for -C: output all configuration information. */ -print_version(stdout);+print_version(stdout, FALSE); printf("Compiled with\n"); #ifdef EBCDIC@@ -8506,25 +8773,13 @@ printf("** This version of PCRE2 was compiled without Unicode support.\n"); #else -const char *typename; uint16_t seentypes[1024]; uint16_t seenvalues[1024]; int seencount = 0; int16_t found[256][MAX_SYNONYMS + 1]; int fc = 0; int colwidth = 40;-int n;--if (wantscripts)- {- n = ucp_Script_Count;- typename = "SCRIPTS";- }-else- {- n = ucp_Bprop_Count;- typename = "PROPERTIES";- }+int n = wantscripts? ucp_Script_Count : ucp_Bprop_Count; for (size_t i = 0; i < PRIV(utt_size); i++) {@@ -8569,7 +8824,7 @@ } printf("-------------------------- SUPPORTED %s --------------------------\n\n",- typename);+ wantscripts? "SCRIPTS" : "PROPERTIES"); if (!wantscripts) printf( "This release of PCRE2 supports Unicode's general category properties such\n"@@ -8935,9 +9190,13 @@ if (rlim.rlim_cur > rlim.rlim_max) { fprintf(stderr,- "pcre2test: requested stack size %luMiB is greater than hard limit "- "%luMiB\n", (unsigned long int)stack_size,- (unsigned long int)(rlim.rlim_max));+ "pcre2test: requested stack size %luMiB is greater than hard limit ",+ (unsigned long int)stack_size);+ if (rlim.rlim_max % (1024*1024) == 0) fprintf(stderr, "%luMiB\n",+ (unsigned long int)(rlim.rlim_max/(1024 * 1024)));+ else if (rlim.rlim_max % 1024 == 0) fprintf(stderr, "%luKiB\n",+ (unsigned long int)(rlim.rlim_max/1024));+ else fprintf(stderr, "%lu bytes\n", (unsigned long int)(rlim.rlim_max)); exit(1); } rc = setrlimit(RLIMIT_STACK, &rlim);@@ -9014,10 +9273,10 @@ /* Show version */ - else if (strcmp(arg, "-version") == 0 ||+ else if (memcmp(arg, "-v", 2) == 0 || strcmp(arg, "--version") == 0) {- print_version(stdout);+ print_version(stdout, FALSE); goto EXIT; } @@ -9169,11 +9428,11 @@ #define CONTEXTTESTS \ (void)G(pcre2_set_compile_extra_options_,BITS)(G(pat_context,BITS), 0); \ (void)G(pcre2_set_max_pattern_length_,BITS)(G(pat_context,BITS), 0); \+ (void)G(pcre2_set_max_pattern_compiled_length_,BITS)(G(pat_context,BITS), 0); \+ (void)G(pcre2_set_max_varlookbehind_,BITS)(G(pat_context,BITS), 0); \ (void)G(pcre2_set_offset_limit_,BITS)(G(dat_context,BITS), 0); \- (void)G(pcre2_set_recursion_memory_management_,BITS)(G(dat_context,BITS), my_malloc, my_free, NULL); \ (void)G(pcre2_get_match_data_size_,BITS)(G(match_data,BITS)) - /* Call the appropriate functions for the current mode, and exercise some functions that are not otherwise called. */ @@ -9259,7 +9518,7 @@ /* Output a heading line unless quiet, then process input lines. */ -if (!quiet) print_version(outfile);+if (!quiet) print_version(outfile, TRUE); SET(compiled_code, NULL); @@ -9365,18 +9624,16 @@ fprintf(outfile, "--------------------------------------\n"); if (timeit > 0) {- fprintf(outfile, "Total compile time %.4f milliseconds\n",- (((double)total_compile_time * 1000.0) / (double)timeit) /- (double)CLOCKS_PER_SEC);+ fprintf(outfile, "Total compile time %8.2f microseconds\n",+ ((1000000 / CLOCKS_PER_SEC) * (double)total_compile_time) / timeit); if (total_jit_compile_time > 0)- fprintf(outfile, "Total JIT compile %.4f milliseconds\n",- (((double)total_jit_compile_time * 1000.0) / (double)timeit) /- (double)CLOCKS_PER_SEC);+ fprintf(outfile, "Total JIT compile %8.2f microseconds\n",+ ((1000000 / CLOCKS_PER_SEC) * (double)total_jit_compile_time) / \+ timeit); pad = " "; }- fprintf(outfile, "Total match time %s%.4f milliseconds\n", pad,- (((double)total_match_time * 1000.0) / (double)timeitm) /- (double)CLOCKS_PER_SEC);+ fprintf(outfile, "Total match time %s%8.2f microseconds\n", pad,+ ((1000000 / CLOCKS_PER_SEC) * (double)total_match_time) / timeitm); } @@ -9393,8 +9650,8 @@ free(dbuffer); free(pbuffer8); free(dfa_workspace);-free((void *)locale_tables); free(tables3);+PCRE2_MAKETABLES_FREE(general_context, (void *)locale_tables); PCRE2_MATCH_DATA_FREE(match_data); SUB1(pcre2_code_free, compiled_code);
+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c view
@@ -0,0 +1,137 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include <sys/types.h>+#include <sys/mman.h>+/*+ On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a+ version where it's OK to have more than one JIT block or where MAP_JIT is+ required.+ On non-macOS systems, returns MAP_JIT if it is defined.+*/+#include <TargetConditionals.h>++#if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (TARGET_OS_MAC && !TARGET_OS_IPHONE)++#if defined(SLJIT_CONFIG_X86) && SLJIT_CONFIG_X86++#include <sys/utsname.h>+#include <stdlib.h>++#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)++#ifdef MAP_JIT+#define SLJIT_MAP_JIT (get_map_jit_flag())+static SLJIT_INLINE int get_map_jit_flag(void)+{+ size_t page_size;+ void *ptr;+ struct utsname name;+ static int map_jit_flag = -1;++ if (map_jit_flag < 0) {+ map_jit_flag = 0;+ uname(&name);++ /* Kernel version for 10.14.0 (Mojave) or later */+ if (atoi(name.release) >= 18) {+ page_size = get_page_alignment() + 1;+ /* Only use MAP_JIT if a hardened runtime is used */+ ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC,+ MAP_PRIVATE | MAP_ANON, -1, 0);++ if (ptr != MAP_FAILED)+ munmap(ptr, page_size);+ else+ map_jit_flag = MAP_JIT;+ }+ }+ return map_jit_flag;+}+#else /* !defined(MAP_JIT) */+#define SLJIT_MAP_JIT (0)+#endif++#elif defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM++#include <AvailabilityMacros.h>+#include <pthread.h>++#define SLJIT_MAP_JIT (MAP_JIT)+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \+ apple_update_wx_flags(enable_exec)++static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)+{+#if MAC_OS_X_VERSION_MIN_REQUIRED < 110000+ if (__builtin_available(macos 11, *))+#endif /* BigSur */+ pthread_jit_write_protect_np(enable_exec);+}++#elif defined(SLJIT_CONFIG_PPC) && SLJIT_CONFIG_PPC++#define SLJIT_MAP_JIT (0)+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)++#else+#error "Unsupported architecture"+#endif /* SLJIT_CONFIG */++#else /* !TARGET_OS_OSX */++#ifdef MAP_JIT+#define SLJIT_MAP_JIT (MAP_JIT)+#else+#define SLJIT_MAP_JIT (0)+#endif++#endif /* TARGET_OS_OSX */++static SLJIT_INLINE void* alloc_chunk(sljit_uw size)+{+ void *retval;+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC;+ int flags = MAP_PRIVATE;+ int fd = -1;++ flags |= MAP_ANON | SLJIT_MAP_JIT;++ retval = mmap(NULL, size, prot, flags, fd, 0);+ if (retval == MAP_FAILED)+ return NULL;++ SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0);++ return retval;+}++static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)+{+ munmap(chunk, size);+}++#include "sljitExecAllocatorCore.c"
+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c view
@@ -0,0 +1,327 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++/*+ This file contains a simple executable memory allocator++ It is assumed, that executable code blocks are usually medium (or sometimes+ large) memory blocks, and the allocator is not too frequently called (less+ optimized than other allocators). Thus, using it as a generic allocator is+ not suggested.++ How does it work:+ Memory is allocated in continuous memory areas called chunks by alloc_chunk()+ Chunk format:+ [ block ][ block ] ... [ block ][ block terminator ]++ All blocks and the block terminator is started with block_header. The block+ header contains the size of the previous and the next block. These sizes+ can also contain special values.+ Block size:+ 0 - The block is a free_block, with a different size member.+ 1 - The block is a block terminator.+ n - The block is used at the moment, and the value contains its size.+ Previous block size:+ 0 - This is the first block of the memory chunk.+ n - The size of the previous block.++ Using these size values we can go forward or backward on the block chain.+ The unused blocks are stored in a chain list pointed by free_blocks. This+ list is useful if we need to find a suitable memory area when the allocator+ is called.++ When a block is freed, the new free block is connected to its adjacent free+ blocks if possible.++ [ free block ][ used block ][ free block ]+ and "used block" is freed, the three blocks are connected together:+ [ one big free block ]+*/++/* Expected functions:+ alloc_chunk / free_chunk :+ * allocate executable system memory chunks+ * the size is always divisible by CHUNK_SIZE+ SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK :+ * provided as part of sljitUtils+ * only the allocator requires this lock, sljit is fully thread safe+ as it only uses local variables++ Supported defines:+ SLJIT_HAS_CHUNK_HEADER - (optional) sljit_chunk_header is defined+ SLJIT_HAS_EXECUTABLE_OFFSET - (optional) has executable offset data+ SLJIT_UPDATE_WX_FLAGS - (optional) update WX flags+*/++#ifdef SLJIT_HAS_CHUNK_HEADER+#define CHUNK_HEADER_SIZE (sizeof(struct sljit_chunk_header))+#else /* !SLJIT_HAS_CHUNK_HEADER */+#define CHUNK_HEADER_SIZE 0+#endif /* SLJIT_HAS_CHUNK_HEADER */++#ifndef SLJIT_UPDATE_WX_FLAGS+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)+#endif /* SLJIT_UPDATE_WX_FLAGS */++#ifndef CHUNK_SIZE+/* 64 KByte if not specified. */+#define CHUNK_SIZE (sljit_uw)0x10000+#endif /* CHUNK_SIZE */++struct block_header {+ sljit_uw size;+ sljit_uw prev_size;+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET+ sljit_sw executable_offset;+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */+};++struct free_block {+ struct block_header header;+ struct free_block *next;+ struct free_block *prev;+ sljit_uw size;+};++#define AS_BLOCK_HEADER(base, offset) \+ ((struct block_header*)(((sljit_u8*)base) + offset))+#define AS_FREE_BLOCK(base, offset) \+ ((struct free_block*)(((sljit_u8*)base) + offset))+#define MEM_START(base) ((void*)((base) + 1))+#define CHUNK_MASK (~(CHUNK_SIZE - 1))+#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7)+#define CHUNK_EXTRA_SIZE (sizeof(struct block_header) + CHUNK_HEADER_SIZE)++static struct free_block* free_blocks;+static sljit_uw allocated_size;+static sljit_uw total_size;++static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)+{+ free_block->header.size = 0;+ free_block->size = size;++ free_block->next = free_blocks;+ free_block->prev = NULL;+ if (free_blocks)+ free_blocks->prev = free_block;+ free_blocks = free_block;+}++static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)+{+ if (free_block->next)+ free_block->next->prev = free_block->prev;++ if (free_block->prev)+ free_block->prev->next = free_block->next;+ else {+ SLJIT_ASSERT(free_blocks == free_block);+ free_blocks = free_block->next;+ }+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)+{+ struct block_header *header;+ struct block_header *next_header;+ struct free_block *free_block;+ sljit_uw chunk_size;++#ifdef SLJIT_HAS_CHUNK_HEADER+ struct sljit_chunk_header *chunk_header;+#else /* !SLJIT_HAS_CHUNK_HEADER */+ void *chunk_header;+#endif /* SLJIT_HAS_CHUNK_HEADER */++#ifdef SLJIT_HAS_EXECUTABLE_OFFSET+ sljit_sw executable_offset;+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */++ if (size < (64 - sizeof(struct block_header)))+ size = (64 - sizeof(struct block_header));+ size = ALIGN_SIZE(size);++ SLJIT_ALLOCATOR_LOCK();+ free_block = free_blocks;+ while (free_block) {+ if (free_block->size >= size) {+ chunk_size = free_block->size;+ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);+ if (chunk_size > size + 64) {+ /* We just cut a block from the end of the free block. */+ chunk_size -= size;+ free_block->size = chunk_size;+ header = AS_BLOCK_HEADER(free_block, chunk_size);+ header->prev_size = chunk_size;+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET+ header->executable_offset = free_block->header.executable_offset;+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */+ AS_BLOCK_HEADER(header, size)->prev_size = size;+ } else {+ sljit_remove_free_block(free_block);+ header = (struct block_header*)free_block;+ size = chunk_size;+ }+ allocated_size += size;+ header->size = size;+ SLJIT_ALLOCATOR_UNLOCK();+ return MEM_START(header);+ }+ free_block = free_block->next;+ }++ chunk_size = (size + CHUNK_EXTRA_SIZE + CHUNK_SIZE - 1) & CHUNK_MASK;++ chunk_header = alloc_chunk(chunk_size);+ if (!chunk_header) {+ SLJIT_ALLOCATOR_UNLOCK();+ return NULL;+ }++#ifdef SLJIT_HAS_EXECUTABLE_OFFSET+ executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (sljit_u8*)chunk_header);+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */++ chunk_size -= CHUNK_EXTRA_SIZE;+ total_size += chunk_size;++ header = (struct block_header*)(((sljit_u8*)chunk_header) + CHUNK_HEADER_SIZE);++ header->prev_size = 0;+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET+ header->executable_offset = executable_offset;+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */++ if (chunk_size > size + 64) {+ /* Cut the allocated space into a free and a used block. */+ allocated_size += size;+ header->size = size;+ chunk_size -= size;++ free_block = AS_FREE_BLOCK(header, size);+ free_block->header.prev_size = size;+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET+ free_block->header.executable_offset = executable_offset;+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */+ sljit_insert_free_block(free_block, chunk_size);+ next_header = AS_BLOCK_HEADER(free_block, chunk_size);+ } else {+ /* All space belongs to this allocation. */+ allocated_size += chunk_size;+ header->size = chunk_size;+ next_header = AS_BLOCK_HEADER(header, chunk_size);+ }+ next_header->size = 1;+ next_header->prev_size = chunk_size;+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET+ next_header->executable_offset = executable_offset;+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */+ SLJIT_ALLOCATOR_UNLOCK();+ return MEM_START(header);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void *ptr)+{+ struct block_header *header;+ struct free_block *free_block;++ SLJIT_ALLOCATOR_LOCK();+ header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET+ header = AS_BLOCK_HEADER(header, -header->executable_offset);+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */+ allocated_size -= header->size;++ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);++ /* Connecting free blocks together if possible. */++ /* If header->prev_size == 0, free_block will equal to header.+ In this case, free_block->header.size will be > 0. */+ free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);+ if (SLJIT_UNLIKELY(!free_block->header.size)) {+ free_block->size += header->size;+ header = AS_BLOCK_HEADER(free_block, free_block->size);+ header->prev_size = free_block->size;+ } else {+ free_block = (struct free_block*)header;+ sljit_insert_free_block(free_block, header->size);+ }++ header = AS_BLOCK_HEADER(free_block, free_block->size);+ if (SLJIT_UNLIKELY(!header->size)) {+ free_block->size += ((struct free_block*)header)->size;+ sljit_remove_free_block((struct free_block*)header);+ header = AS_BLOCK_HEADER(free_block, free_block->size);+ header->prev_size = free_block->size;+ }++ /* The whole chunk is free. */+ if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {+ /* If this block is freed, we still have (allocated_size / 2) free space. */+ if (total_size - free_block->size > (allocated_size * 3 / 2)) {+ total_size -= free_block->size;+ sljit_remove_free_block(free_block);+ free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE);+ }+ }++ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);+ SLJIT_ALLOCATOR_UNLOCK();+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)+{+ struct free_block* free_block;+ struct free_block* next_free_block;++ SLJIT_ALLOCATOR_LOCK();+ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);++ free_block = free_blocks;+ while (free_block) {+ next_free_block = free_block->next;+ if (!free_block->header.prev_size &&+ AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {+ total_size -= free_block->size;+ sljit_remove_free_block(free_block);+ free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE);+ }+ free_block = next_free_block;+ }++ SLJIT_ASSERT(total_size || (!total_size && !free_blocks));+ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);+ SLJIT_ALLOCATOR_UNLOCK();+}++#ifdef SLJIT_HAS_EXECUTABLE_OFFSET+SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code)+{+ return ((struct block_header*)SLJIT_CODE_TO_PTR(code))[-1].executable_offset;+}+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c view
@@ -0,0 +1,89 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include <sys/mman.h>+#include <sys/procctl.h>++#ifdef PROC_WXMAP_CTL+static SLJIT_INLINE int sljit_is_wx_block(void)+{+ static int wx_block = -1;+ if (wx_block < 0) {+ int sljit_wx_enable = PROC_WX_MAPPINGS_PERMIT;+ wx_block = !!procctl(P_PID, 0, PROC_WXMAP_CTL, &sljit_wx_enable);+ }+ return wx_block;+}++#define SLJIT_IS_WX_BLOCK sljit_is_wx_block()+#else /* !PROC_WXMAP_CTL */+#define SLJIT_IS_WX_BLOCK (1)+#endif /* PROC_WXMAP_CTL */++static SLJIT_INLINE void* alloc_chunk(sljit_uw size)+{+ void *retval;+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC;+ int flags = MAP_PRIVATE;+ int fd = -1;++#ifdef PROT_MAX+ prot |= PROT_MAX(prot);+#endif++#ifdef MAP_ANON+ flags |= MAP_ANON;+#else /* !MAP_ANON */+ if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))+ return NULL;++ fd = dev_zero;+#endif /* MAP_ANON */++retry:+ retval = mmap(NULL, size, prot, flags, fd, 0);+ if (retval == MAP_FAILED) {+ if (!SLJIT_IS_WX_BLOCK)+ goto retry;++ return NULL;+ }++ /* HardenedBSD's mmap lies, so check permissions again. */+ if (mprotect(retval, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {+ munmap(retval, size);+ return NULL;+ }++ return retval;+}++static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)+{+ munmap(chunk, size);+}++#include "sljitExecAllocatorCore.c"
+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c view
@@ -0,0 +1,62 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include <sys/types.h>+#include <sys/mman.h>++static SLJIT_INLINE void* alloc_chunk(sljit_uw size)+{+ void *retval;+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC;+ int flags = MAP_PRIVATE;+ int fd = -1;++#ifdef PROT_MAX+ prot |= PROT_MAX(prot);+#endif++#ifdef MAP_ANON+ flags |= MAP_ANON;+#else /* !MAP_ANON */+ if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))+ return NULL;++ fd = dev_zero;+#endif /* MAP_ANON */++ retval = mmap(NULL, size, prot, flags, fd, 0);+ if (retval == MAP_FAILED)+ return NULL;++ return retval;+}++static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)+{+ munmap(chunk, size);+}++#include "sljitExecAllocatorCore.c"
+ src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c view
@@ -0,0 +1,40 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)++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(void *chunk, sljit_uw size)+{+ SLJIT_UNUSED_ARG(size);+ VirtualFree(chunk, 0, MEM_RELEASE);+}++#include "sljitExecAllocatorCore.c"
+ src/c/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c view
@@ -0,0 +1,72 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#define SLJIT_HAS_CHUNK_HEADER+#define SLJIT_HAS_EXECUTABLE_OFFSET++struct sljit_chunk_header {+ void *executable;+};++/*+ * MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to+ * adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed+ */+static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size)+{+ struct sljit_chunk_header *retval;++ retval = (struct sljit_chunk_header *)mmap(NULL, size,+ PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC),+ MAP_ANON | MAP_SHARED, -1, 0);++ if (retval == MAP_FAILED)+ return NULL;++ retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP);+ if (retval->executable == MAP_FAILED) {+ munmap((void *)retval, size);+ return NULL;+ }++ if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) {+ munmap(retval->executable, size);+ munmap((void *)retval, size);+ return NULL;+ }++ return retval;+}++static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)+{+ struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1;++ munmap(header->executable, size);+ munmap((void *)header, size);+}++#include "sljitExecAllocatorCore.c"
+ src/c/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c view
@@ -0,0 +1,172 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#define SLJIT_HAS_CHUNK_HEADER+#define SLJIT_HAS_EXECUTABLE_OFFSET++struct sljit_chunk_header {+ void *executable;+};++#include <sys/stat.h>+#include <fcntl.h>+#include <stdio.h>+#include <string.h>++#ifndef O_NOATIME+#define O_NOATIME 0+#endif++/* this is a linux extension available since kernel 3.11 */+#ifndef O_TMPFILE+#define O_TMPFILE 0x404000+#endif++#ifndef _GNU_SOURCE+char *secure_getenv(const char *name);+int mkostemp(char *template, int flags);+#endif++static SLJIT_INLINE int create_tempfile(void)+{+ int fd;+ char tmp_name[256];+ size_t tmp_name_len = 0;+ char *dir;+ struct stat st;+#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED+ mode_t mode;+#endif++#ifdef HAVE_MEMFD_CREATE+ /* this is a GNU extension, make sure to use -D_GNU_SOURCE */+ fd = memfd_create("sljit", MFD_CLOEXEC);+ if (fd != -1) {+ fchmod(fd, 0);+ return fd;+ }+#endif++ dir = secure_getenv("TMPDIR");++ if (dir) {+ size_t len = strlen(dir);+ if (len > 0 && len < sizeof(tmp_name)) {+ if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode)) {+ memcpy(tmp_name, dir, len + 1);+ tmp_name_len = len;+ }+ }+ }++#ifdef P_tmpdir+ if (!tmp_name_len) {+ tmp_name_len = strlen(P_tmpdir);+ if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name))+ strcpy(tmp_name, P_tmpdir);+ }+#endif+ if (!tmp_name_len) {+ strcpy(tmp_name, "/tmp");+ tmp_name_len = 4;+ }++ SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name));++ if (tmp_name_len > 1 && tmp_name[tmp_name_len - 1] == '/')+ tmp_name[--tmp_name_len] = '\0';++ fd = open(tmp_name, O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0);+ if (fd != -1)+ return fd;++ if (tmp_name_len >= sizeof(tmp_name) - 7)+ return -1;++ strcpy(tmp_name + tmp_name_len, "/XXXXXX");+#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED+ mode = umask(0777);+#endif+ fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME);+#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED+ umask(mode);+#else+ fchmod(fd, 0);+#endif++ if (fd == -1)+ return -1;++ if (unlink(tmp_name)) {+ close(fd);+ return -1;+ }++ return fd;+}++static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size)+{+ struct sljit_chunk_header *retval;+ int fd;++ fd = create_tempfile();+ if (fd == -1)+ return NULL;++ if (ftruncate(fd, (off_t)size)) {+ close(fd);+ return NULL;+ }++ retval = (struct sljit_chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);++ if (retval == MAP_FAILED) {+ close(fd);+ return NULL;+ }++ retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);++ if (retval->executable == MAP_FAILED) {+ munmap((void *)retval, size);+ close(fd);+ return NULL;+ }++ close(fd);+ return retval;+}++static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)+{+ struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1;++ munmap(header->executable, size);+ munmap((void *)header, size);+}++#include "sljitExecAllocatorCore.c"
+ src/c/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c view
@@ -0,0 +1,141 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++/*+ This file contains a simple W^X executable memory allocator++ In *NIX, MAP_ANON is required (that is considered a feature) so make+ sure to set the right availability macros for your system or the code+ will fail to build.++ If your system doesn't support mapping of anonymous pages (ex: IRIX) it+ is also likely that it doesn't need this allocator and should be using+ the standard one instead.++ It allocates a separate map for each code block and may waste a lot of+ memory, because whatever was requested, will be rounded up to the page+ size (minimum 4KB, but could be even bigger).++ It changes the page permissions (RW <-> RX) as needed and therefore, if you+ will be updating the code after it has been generated, need to make sure to+ block any concurrent execution, or could result in a SIGBUS, that could+ even manifest itself at a different address than the one that was being+ modified.++ Only use if you are unable to use the regular allocator because of security+ restrictions and adding exceptions to your application or the system are+ not possible.+*/++#include <sys/types.h>+#include <sys/mman.h>++#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \+ sljit_update_wx_flags((from), (to), (enable_exec))++#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)+#include <pthread.h>+#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock)+#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock)+#else+#define SLJIT_SE_LOCK()+#define SLJIT_SE_UNLOCK()+#endif /* !SLJIT_SINGLE_THREADED */++#define SLJIT_WX_IS_BLOCK(ptr, size) generic_check_is_wx_block(ptr, size)++static SLJIT_INLINE int generic_check_is_wx_block(void *ptr, sljit_uw size)+{+ if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC)))+ return !!mprotect(ptr, size, PROT_READ | PROT_WRITE);++ return 1;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)+{+#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)+ static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER;+#endif+ static int wx_block = -1;+ int prot = PROT_READ | PROT_WRITE;+ sljit_uw* ptr;++ if (SLJIT_UNLIKELY(wx_block > 0))+ return NULL;++#ifdef PROT_MAX+ prot |= PROT_MAX(PROT_READ | PROT_WRITE | PROT_EXEC);+#endif++ size += sizeof(sljit_uw);+ ptr = (sljit_uw*)mmap(NULL, size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);++ if (ptr == MAP_FAILED)+ return NULL;++ if (SLJIT_UNLIKELY(wx_block < 0)) {+ SLJIT_SE_LOCK();+ wx_block = SLJIT_WX_IS_BLOCK(ptr, size);+ SLJIT_SE_UNLOCK();+ if (SLJIT_UNLIKELY(wx_block)) {+ munmap((void *)ptr, size);+ return NULL;+ }+ }++ *ptr++ = size;+ return ptr;+}++#undef SLJIT_SE_UNLOCK+#undef SLJIT_SE_LOCK++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)+{+ sljit_uw *start_ptr = ((sljit_uw*)ptr) - 1;+ munmap((void*)start_ptr, *start_ptr);+}++static void sljit_update_wx_flags(void *from, void *to, int enable_exec)+{+ sljit_uw page_mask = (sljit_uw)get_page_alignment();+ sljit_uw start = (sljit_uw)from;+ sljit_uw end = (sljit_uw)to;+ int prot = PROT_READ | (enable_exec ? PROT_EXEC : PROT_WRITE);++ SLJIT_ASSERT(start < end);++ start &= ~page_mask;+ end = (end + page_mask) & ~page_mask;++ mprotect((void*)start, end - start, prot);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)+{+ /* This allocator does not keep unused memory for future allocations. */+}
+ src/c/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c view
@@ -0,0 +1,102 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++/*+ This file contains a simple W^X executable memory allocator++ In *NIX, MAP_ANON is required (that is considered a feature) so make+ sure to set the right availability macros for your system or the code+ will fail to build.++ If your system doesn't support mapping of anonymous pages (ex: IRIX) it+ is also likely that it doesn't need this allocator and should be using+ the standard one instead.++ It allocates a separate map for each code block and may waste a lot of+ memory, because whatever was requested, will be rounded up to the page+ size (minimum 4KB, but could be even bigger).++ It changes the page permissions (RW <-> RX) as needed and therefore, if you+ will be updating the code after it has been generated, need to make sure to+ block any concurrent execution, or could result in a SIGBUS, that could+ even manifest itself at a different address than the one that was being+ modified.++ Only use if you are unable to use the regular allocator because of security+ restrictions and adding exceptions to your application or the system are+ not possible.+*/++#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \+ sljit_update_wx_flags((from), (to), (enable_exec))++SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)+{+ sljit_uw *ptr;++ size += sizeof(sljit_uw);+ ptr = (sljit_uw*)VirtualAlloc(NULL, size,+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);++ if (!ptr)+ return NULL;++ *ptr++ = size;++ return ptr;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)+{+ sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw);+#if defined(SLJIT_DEBUG) && SLJIT_DEBUG+ sljit_uw page_mask = (sljit_uw)get_page_alignment();++ SLJIT_ASSERT(!(start & page_mask));+#endif+ VirtualFree((void*)start, 0, MEM_RELEASE);+}++static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)+{+ DWORD oldprot;+ sljit_uw page_mask = (sljit_uw)get_page_alignment();+ sljit_uw start = (sljit_uw)from;+ sljit_uw end = (sljit_uw)to;+ DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE;++ SLJIT_ASSERT(start < end);++ start &= ~page_mask;+ end = (end + page_mask) & ~page_mask;++ VirtualProtect((void*)start, end - start, prot, &oldprot);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)+{+ /* This allocator does not keep unused memory for future allocations. */+}
src/c/pcre2/src/sljit/sljitConfig.h view
@@ -39,27 +39,6 @@ */ /* --------------------------------------------------------------------- */-/* Architecture */-/* --------------------------------------------------------------------- */--/* Architecture selection. */-/* #define SLJIT_CONFIG_X86_32 1 */-/* #define SLJIT_CONFIG_X86_64 1 */-/* #define SLJIT_CONFIG_ARM_V5 1 */-/* #define SLJIT_CONFIG_ARM_V7 1 */-/* #define SLJIT_CONFIG_ARM_THUMB2 1 */-/* #define SLJIT_CONFIG_ARM_64 1 */-/* #define SLJIT_CONFIG_PPC_32 1 */-/* #define SLJIT_CONFIG_PPC_64 1 */-/* #define SLJIT_CONFIG_MIPS_32 1 */-/* #define SLJIT_CONFIG_MIPS_64 1 */-/* #define SLJIT_CONFIG_SPARC_32 1 */-/* #define SLJIT_CONFIG_S390X 1 */--/* #define SLJIT_CONFIG_AUTO 1 */-/* #define SLJIT_CONFIG_UNSUPPORTED 1 */--/* --------------------------------------------------------------------- */ /* Utilities */ /* --------------------------------------------------------------------- */ @@ -95,7 +74,9 @@ /* Executable code allocation: If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should- define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_EXEC_OFFSET. */+ define SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC.+ Optionally, depending on the implementation used for the allocator,+ SLJIT_EXEC_OFFSET and SLJIT_UPDATE_WX_FLAGS might also be needed. */ #ifndef SLJIT_EXECUTABLE_ALLOCATOR /* Enabled by default. */ #define SLJIT_EXECUTABLE_ALLOCATOR 1@@ -126,17 +107,6 @@ #endif #endif /* !SLJIT_EXECUTABLE_ALLOCATOR */--/* Force cdecl calling convention even if a better calling- convention (e.g. fastcall) is supported by the C compiler.- If this option is disabled (this is the default), functions- called from JIT should be defined with SLJIT_FUNC attribute.- Standard C functions can still be called by using the- SLJIT_CALL_CDECL jump type. */-#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION-/* Disabled by default */-#define SLJIT_USE_CDECL_CALLING_CONVENTION 0-#endif /* Return with error when an invalid argument is passed. */ #ifndef SLJIT_ARGUMENT_CHECKS
+ src/c/pcre2/src/sljit/sljitConfigCPU.h view
@@ -0,0 +1,188 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef SLJIT_CONFIG_CPU_H_+#define SLJIT_CONFIG_CPU_H_++/* --------------------------------------------------------------------- */+/* Architecture */+/* --------------------------------------------------------------------- */++/* Architecture selection. */+/* #define SLJIT_CONFIG_X86_32 1 */+/* #define SLJIT_CONFIG_X86_64 1 */+/* #define SLJIT_CONFIG_ARM_V6 1 */+/* #define SLJIT_CONFIG_ARM_V7 1 */+/* #define SLJIT_CONFIG_ARM_THUMB2 1 */+/* #define SLJIT_CONFIG_ARM_64 1 */+/* #define SLJIT_CONFIG_PPC_32 1 */+/* #define SLJIT_CONFIG_PPC_64 1 */+/* #define SLJIT_CONFIG_MIPS_32 1 */+/* #define SLJIT_CONFIG_MIPS_64 1 */+/* #define SLJIT_CONFIG_RISCV_32 1 */+/* #define SLJIT_CONFIG_RISCV_64 1 */+/* #define SLJIT_CONFIG_S390X 1 */+/* #define SLJIT_CONFIG_LOONGARCH_64 */++/* #define SLJIT_CONFIG_AUTO 1 */+/* #define SLJIT_CONFIG_UNSUPPORTED 1 */++/*****************/+/* Sanity check. */+/*****************/++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \+ + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \+ + (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \+ + (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \+ + (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \+ + (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \+ + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \+ + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \+ + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \+ + (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \+ + (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \+ + (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \+ + (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \+ + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \+ + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2+#error "Multiple architectures are selected"+#endif++#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \+ && !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \+ && !(defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \+ && !(defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \+ && !(defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ && !(defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \+ && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \+ && !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \+ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \+ && !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \+ && !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \+ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \+ && !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \+ && !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \+ && !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)+#if defined SLJIT_CONFIG_AUTO && !SLJIT_CONFIG_AUTO+#error "An architecture must be selected"+#else /* SLJIT_CONFIG_AUTO */+#define SLJIT_CONFIG_AUTO 1+#endif /* !SLJIT_CONFIG_AUTO */+#endif /* !SLJIT_CONFIG */++/********************************************************/+/* Automatic CPU detection (requires compiler support). */+/********************************************************/++#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)+#ifndef _WIN32++#if defined(__i386__) || defined(__i386)+#define SLJIT_CONFIG_X86_32 1+#elif defined(__x86_64__)+#define SLJIT_CONFIG_X86_64 1+#elif defined(__aarch64__)+#define SLJIT_CONFIG_ARM_64 1+#elif defined(__thumb2__)+#define SLJIT_CONFIG_ARM_THUMB2 1+#elif (defined(__ARM_ARCH) && __ARM_ARCH >= 7) || \+ ((defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7S__)) \+ || (defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8R__)) \+ || (defined(__ARM_ARCH_9A__)))+#define SLJIT_CONFIG_ARM_V7 1+#elif defined(__arm__) || defined (__ARM__)+#define SLJIT_CONFIG_ARM_V6 1+#elif defined(__ppc64__) || defined(__powerpc64__) || (defined(_ARCH_PPC64) && defined(__64BIT__)) || (defined(_POWER) && defined(__64BIT__))+#define SLJIT_CONFIG_PPC_64 1+#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)+#define SLJIT_CONFIG_PPC_32 1+#elif defined(__mips__) && !defined(_LP64)+#define SLJIT_CONFIG_MIPS_32 1+#elif defined(__mips64)+#define SLJIT_CONFIG_MIPS_64 1+#elif defined (__riscv_xlen) && (__riscv_xlen == 32)+#define SLJIT_CONFIG_RISCV_32 1+#elif defined (__riscv_xlen) && (__riscv_xlen == 64)+#define SLJIT_CONFIG_RISCV_64 1+#elif defined (__loongarch_lp64)+#define SLJIT_CONFIG_LOONGARCH_64 1+#elif defined(__s390x__)+#define SLJIT_CONFIG_S390X 1+#else+/* Unsupported architecture */+#define SLJIT_CONFIG_UNSUPPORTED 1+#endif++#else /* _WIN32 */++#if defined(_M_X64) || defined(__x86_64__)+#define SLJIT_CONFIG_X86_64 1+#elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__)+#define SLJIT_CONFIG_ARM_THUMB2 1+#elif (defined(_M_ARM) && _M_ARM >= 7)+#define SLJIT_CONFIG_ARM_V7 1+#elif defined(_ARM_)+#define SLJIT_CONFIG_ARM_V6 1+#elif defined(_M_ARM64) || defined(__aarch64__)+#define SLJIT_CONFIG_ARM_64 1+#else+#define SLJIT_CONFIG_X86_32 1+#endif++#endif /* !_WIN32 */+#endif /* SLJIT_CONFIG_AUTO */++#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)+#undef SLJIT_EXECUTABLE_ALLOCATOR+#endif /* SLJIT_CONFIG_UNSUPPORTED */++/******************************/+/* CPU family type detection. */+/******************************/++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \+ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+#define SLJIT_CONFIG_ARM_32 1+#endif++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+#define SLJIT_CONFIG_X86 1+#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+#define SLJIT_CONFIG_ARM 1+#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define SLJIT_CONFIG_PPC 1+#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+#define SLJIT_CONFIG_MIPS 1+#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+#define SLJIT_CONFIG_RISCV 1+#elif (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64)+#define SLJIT_CONFIG_LOONGARCH 1+#endif++#endif /* SLJIT_CONFIG_CPU_H_ */
src/c/pcre2/src/sljit/sljitConfigInternal.h view
@@ -49,8 +49,8 @@ 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_sp, sljit_up : signed and unsigned 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 @@ -59,7 +59,10 @@ SLJIT_64BIT_ARCHITECTURE : 64 bit architecture SLJIT_LITTLE_ENDIAN : little endian architecture SLJIT_BIG_ENDIAN : big endian architecture- SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)+ SLJIT_UNALIGNED : unaligned memory accesses for non-fpu operations are supported+ SLJIT_FPU_UNALIGNED : unaligned memory accesses for fpu operations are supported+ SLJIT_MASKED_SHIFT : all word shifts are always masked+ SLJIT_MASKED_SHIFT32 : all 32 bit shifts are always masked SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information Constants:@@ -69,6 +72,8 @@ SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers 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_NUMBER_OF_TEMPORARY_REGISTERS : number of available temporary registers+ SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS : number of available temporary floating point registers SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index SLJIT_F32_SHIFT : the shift required to apply when accessing a single precision floating point array by index@@ -78,137 +83,31 @@ the scratch register index of ecx is stored in this variable 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+ SLJIT_CONV_MAX_FLOAT : result when a floating point value is converted to integer+ and the floating point value is higher than the maximum integer value+ (possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT)+ SLJIT_CONV_MIN_FLOAT : result when a floating point value is converted to integer+ and the floating point value is lower than the minimum integer value+ (possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT)+ SLJIT_CONV_NAN_FLOAT : result when a NaN floating point value is converted to integer+ (possible values: SLJIT_CONV_RESULT_MAX_INT, SLJIT_CONV_RESULT_MIN_INT,+ or SLJIT_CONV_RESULT_ZERO) Other macros:+ SLJIT_TMP_R0 .. R9 : accessing temporary registers+ SLJIT_TMP_R(i) : accessing temporary registers+ SLJIT_TMP_FR0 .. FR9 : accessing temporary floating point registers+ SLJIT_TMP_FR(i) : accessing temporary floating point registers+ SLJIT_TMP_DEST_REG : a temporary register for results+ SLJIT_TMP_MEM_REG : a temporary base register for accessing memory+ (can be the same as SLJIT_TMP_DEST_REG)+ SLJIT_TMP_DEST_FREG : a temporary register for float results SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (platform independent helper)+ SLJIT_F64_SECOND(reg) : provides the register index of the second 32 bit part of a 64 bit+ floating point register when SLJIT_HAS_F64_AS_F32_PAIR returns non-zero */ -/*****************/-/* Sanity check. */-/*****************/--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \- + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \- + (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \- + (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \- + (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \- + (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \- + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \- + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \- + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \- + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \- + (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \- + (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \- + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \- + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2-#error "Multiple architectures are selected"-#endif--#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \- && !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \- && !(defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \- && !(defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \- && !(defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \- && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \- && !(defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \- && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \- && !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \- && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \- && !(defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \- && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \- && !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \- && !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)-#if defined SLJIT_CONFIG_AUTO && !SLJIT_CONFIG_AUTO-#error "An architecture must be selected"-#else /* SLJIT_CONFIG_AUTO */-#define SLJIT_CONFIG_AUTO 1-#endif /* !SLJIT_CONFIG_AUTO */-#endif /* !SLJIT_CONFIG */--/********************************************************/-/* Automatic CPU detection (requires compiler support). */-/********************************************************/--#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)--#ifndef _WIN32--#if defined(__i386__) || defined(__i386)-#define SLJIT_CONFIG_X86_32 1-#elif defined(__x86_64__)-#define SLJIT_CONFIG_X86_64 1-#elif defined(__arm__) || defined(__ARM__)-#ifdef __thumb2__-#define SLJIT_CONFIG_ARM_THUMB2 1-#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__)-#define SLJIT_CONFIG_ARM_V7 1-#else-#define SLJIT_CONFIG_ARM_V5 1-#endif-#elif defined (__aarch64__)-#define SLJIT_CONFIG_ARM_64 1-#elif defined(__ppc64__) || defined(__powerpc64__) || (defined(_ARCH_PPC64) && defined(__64BIT__)) || (defined(_POWER) && defined(__64BIT__))-#define SLJIT_CONFIG_PPC_64 1-#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)-#define SLJIT_CONFIG_PPC_32 1-#elif defined(__mips__) && !defined(_LP64)-#define SLJIT_CONFIG_MIPS_32 1-#elif defined(__mips64)-#define SLJIT_CONFIG_MIPS_64 1-#elif (defined(__sparc__) || defined(__sparc)) && !defined(_LP64)-#define SLJIT_CONFIG_SPARC_32 1-#elif defined(__s390x__)-#define SLJIT_CONFIG_S390X 1-#else-/* Unsupported architecture */-#define SLJIT_CONFIG_UNSUPPORTED 1-#endif--#else /* _WIN32 */--#if defined(_M_X64) || defined(__x86_64__)-#define SLJIT_CONFIG_X86_64 1-#elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__)-#define SLJIT_CONFIG_ARM_THUMB2 1-#elif (defined(_M_ARM) && _M_ARM >= 7)-#define SLJIT_CONFIG_ARM_V7 1-#elif defined(_ARM_)-#define SLJIT_CONFIG_ARM_V5 1-#elif defined(_M_ARM64) || defined(__aarch64__)-#define SLJIT_CONFIG_ARM_64 1-#else-#define SLJIT_CONFIG_X86_32 1-#endif--#endif /* !_WIN32 */-#endif /* SLJIT_CONFIG_AUTO */--#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)-#undef SLJIT_EXECUTABLE_ALLOCATOR-#endif--/******************************/-/* CPU family type detection. */-/******************************/--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \- || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)-#define SLJIT_CONFIG_ARM_32 1-#endif--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)-#define SLJIT_CONFIG_X86 1-#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)-#define SLJIT_CONFIG_ARM 1-#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-#define SLJIT_CONFIG_PPC 1-#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)-#define SLJIT_CONFIG_MIPS 1-#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) || (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)-#define SLJIT_CONFIG_SPARC 1-#endif- /***********************************************************/ /* Intel Control-flow Enforcement Technology (CET) spport. */ /***********************************************************/@@ -237,23 +136,23 @@ */ #ifndef SLJIT_MALLOC-#define SLJIT_MALLOC(size, allocator_data) malloc(size)+#define SLJIT_MALLOC(size, allocator_data) (malloc(size)) #endif #ifndef SLJIT_FREE-#define SLJIT_FREE(ptr, allocator_data) free(ptr)+#define SLJIT_FREE(ptr, allocator_data) (free(ptr)) #endif #ifndef SLJIT_MEMCPY-#define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len)+#define SLJIT_MEMCPY(dest, src, len) (memcpy(dest, src, len)) #endif #ifndef SLJIT_MEMMOVE-#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)+#define SLJIT_MEMMOVE(dest, src, len) (memmove(dest, src, len)) #endif #ifndef SLJIT_ZEROMEM-#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len)+#define SLJIT_ZEROMEM(dest, len) (memset(dest, 0, len)) #endif /***************************/@@ -303,7 +202,7 @@ /* Type of public API functions. */ /*********************************/ -#ifndef SLJIT_API_FUNC_ATTRIBUTE +#ifndef SLJIT_API_FUNC_ATTRIBUTE #if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) /* Static ABI functions. For all-in-one programs. */ @@ -323,6 +222,10 @@ /* Instruction cache flush. */ /****************************/ +#ifdef __APPLE__+#include <AvailabilityMacros.h>+#endif+ /* * TODO: *@@ -330,8 +233,14 @@ * older versions are known to abort in some targets * https://github.com/PhilipHazel/pcre2/issues/92 *- * beware APPLE is known to have removed the code in iOS so- * it will need to be excempted or result in broken builds+ * beware some vendors (ex: Microsoft, Apple) are known to have+ * removed the code to support this builtin even if the call for+ * __has_builtin reports it is available.+ *+ * make sure linking doesn't fail because __clear_cache() is+ * missing before changing it or add an exception so that the+ * system provided method that should be defined below is used+ * instead. */ #if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) #if __has_builtin(__builtin___clear_cache) && !defined(__clang__)@@ -339,9 +248,9 @@ /* * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=91248 * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=93811- * gcc's clear_cache builtin for power and sparc are broken+ * gcc's clear_cache builtin for power is broken */-#if !defined(SLJIT_CONFIG_PPC) && !defined(SLJIT_CONFIG_SPARC_32)+#if !defined(SLJIT_CONFIG_PPC) #define SLJIT_CACHE_FLUSH(from, to) \ __builtin___clear_cache((char*)(from), (char*)(to)) #endif@@ -357,7 +266,7 @@ /* Not required to implement on archs with unified caches. */ #define SLJIT_CACHE_FLUSH(from, to) -#elif defined __APPLE__+#elif defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 /* Supported by all macs since Mac OS 10.5. However, it does not work on non-jailbroken iOS devices,@@ -373,12 +282,10 @@ ppc_cache_flush((from), (to)) #define SLJIT_CACHE_FLUSH_OWN_IMPL 1 -#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+#elif defined(_WIN32) -/* 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+ FlushInstructionCache(GetCurrentProcess(), (void*)(from), (char*)(to) - (char*)(from)) #elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || defined(__clang__) @@ -392,11 +299,6 @@ #define SLJIT_CACHE_FLUSH(from, to) \ cacheflush((long)(from), (long)(to), 0) -#elif defined _WIN32--#define SLJIT_CACHE_FLUSH(from, to) \- FlushInstructionCache(GetCurrentProcess(), (void*)(from), (char*)(to) - (char*)(from))- #else /* Call __ARM_NR_cacheflush on ARM-Linux or the corresponding MIPS syscall. */@@ -429,13 +331,15 @@ #if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) /* Just to have something. */ #define SLJIT_WORD_SHIFT 0-typedef unsigned long int sljit_uw;-typedef long int sljit_sw;+typedef unsigned int sljit_uw;+typedef int sljit_sw; #elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \- && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+ && !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \+ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \+ && !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) #define SLJIT_32BIT_ARCHITECTURE 1 #define SLJIT_WORD_SHIFT 2 typedef unsigned int sljit_uw;@@ -458,7 +362,8 @@ #endif /* _WIN32 */ #endif -typedef sljit_uw sljit_p;+typedef sljit_sw sljit_sp;+typedef sljit_uw sljit_up; /* Floating point types. */ typedef float sljit_f32;@@ -471,12 +376,46 @@ #define SLJIT_F32_SHIFT 2 #define SLJIT_F64_SHIFT 3 +#define SLJIT_CONV_RESULT_MAX_INT 0+#define SLJIT_CONV_RESULT_MIN_INT 1+#define SLJIT_CONV_RESULT_ZERO 2++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MIN_INT+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT+#elif (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO+#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MAX_INT+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT+#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT+#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO+#else+#error "Result for float to integer conversion is not defined"+#endif+ #ifndef SLJIT_W /* Defining long constants. */-#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)-#define SLJIT_W(w) (w##l)-#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #ifdef _WIN64 #define SLJIT_W(w) (w##ll) #else /* !windows */@@ -495,8 +434,7 @@ #if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) /* These macros are mostly useful for the applications. */-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \- || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) #ifdef __LITTLE_ENDIAN__ #define SLJIT_LITTLE_ENDIAN 1@@ -504,8 +442,7 @@ #define SLJIT_BIG_ENDIAN 1 #endif -#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \- || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) #ifdef __MIPSEL__ #define SLJIT_LITTLE_ENDIAN 1@@ -518,9 +455,10 @@ /* Auto detecting mips revision. */ #if (defined __mips_isa_rev) && (__mips_isa_rev >= 6) #define SLJIT_MIPS_REV 6-#elif (defined __mips_isa_rev && __mips_isa_rev >= 1) \- || (defined __clang__ && defined _MIPS_ARCH_OCTEON) \- || (defined __clang__ && defined _MIPS_ARCH_P5600)+#elif defined(__mips_isa_rev) && __mips_isa_rev >= 1+#define SLJIT_MIPS_REV __mips_isa_rev+#elif defined(__clang__) \+ && (defined(_MIPS_ARCH_OCTEON) || defined(_MIPS_ARCH_P5600)) /* clang either forgets to define (clang-7) __mips_isa_rev at all * or sets it to zero (clang-8,-9) for -march=octeon (MIPS64 R2+) * and -march=p5600 (MIPS32 R5).@@ -532,8 +470,7 @@ #endif /* !SLJIT_MIPS_REV */ -#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \- || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) #define SLJIT_BIG_ENDIAN 1 @@ -554,19 +491,32 @@ #ifndef SLJIT_UNALIGNED -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \- || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \- || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \- || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \- || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \+ || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \+ || (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) #define SLJIT_UNALIGNED 1 #endif #endif /* !SLJIT_UNALIGNED */ +#ifndef SLJIT_FPU_UNALIGNED++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \+ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \+ || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \+ || (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)+#define SLJIT_FPU_UNALIGNED 1+#endif++#endif /* !SLJIT_FPU_UNALIGNED */+ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) /* Auto detect SSE2 support using CPUID. On 64 bit x86 cpus, sse2 must be present. */@@ -578,38 +528,7 @@ /*****************************************************************************************/ #ifndef SLJIT_FUNC--#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) \- || !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- #define SLJIT_FUNC--#elif defined(__GNUC__) && !defined(__APPLE__)--#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)-#define SLJIT_FUNC __attribute__ ((fastcall))-#define SLJIT_X86_32_FASTCALL 1-#else-#define SLJIT_FUNC-#endif /* gcc >= 3.4 */--#elif defined(_MSC_VER)--#define SLJIT_FUNC __fastcall-#define SLJIT_X86_32_FASTCALL 1--#elif defined(__BORLANDC__)--#define SLJIT_FUNC __msfastcall-#define SLJIT_X86_32_FASTCALL 1--#else /* Unknown compiler. */--/* The cdecl calling convention is usually the x86 default. */-#define SLJIT_FUNC--#endif /* SLJIT_USE_CDECL_CALLING_CONVENTION */- #endif /* !SLJIT_FUNC */ #ifndef SLJIT_INDIRECT_CALL@@ -621,14 +540,10 @@ #endif #endif /* SLJIT_INDIRECT_CALL */ -/* The offset which needs to be substracted from the return address to+/* The offset which needs to be subtracted from the return address to determine the next executed instruction after return. */ #ifndef SLJIT_RETURN_ADDRESS_OFFSET-#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)-#define SLJIT_RETURN_ADDRESS_OFFSET 8-#else #define SLJIT_RETURN_ADDRESS_OFFSET 0-#endif #endif /* SLJIT_RETURN_ADDRESS_OFFSET */ /***************************************************/@@ -651,14 +566,16 @@ #endif /* SLJIT_FREE_EXEC */ #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+SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);+#define SLJIT_EXEC_OFFSET(code) sljit_exec_offset(code)+#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */ #endif /* SLJIT_EXECUTABLE_ALLOCATOR */ +#ifndef SLJIT_EXEC_OFFSET+#define SLJIT_EXEC_OFFSET(ptr) 0+#endif+ /**********************************************/ /* Registers and locals offset determination. */ /**********************************************/@@ -666,16 +583,25 @@ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #define SLJIT_NUMBER_OF_REGISTERS 12-#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 1 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 7 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0-#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0+#define SLJIT_TMP_MEM_REG SLJIT_TMP_R0+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_LOCALS_OFFSET_BASE (8 * SSIZE_OF(sw)) #define SLJIT_PREF_SHIFT_REG SLJIT_R2+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1 #elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #define SLJIT_NUMBER_OF_REGISTERS 13+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1 #ifndef _WIN64 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 6 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0@@ -683,40 +609,54 @@ #else /* _WIN64 */ #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10-#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))+#define SLJIT_LOCALS_OFFSET_BASE (4 * SSIZE_OF(sw)) #endif /* !_WIN64 */+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0+#define SLJIT_TMP_MEM_REG SLJIT_TMP_R0+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0 #define SLJIT_PREF_SHIFT_REG SLJIT_R3--#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)--#define SLJIT_NUMBER_OF_REGISTERS 12-#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8-#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14-#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8-#define SLJIT_LOCALS_OFFSET_BASE 0+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1 -#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) #define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1+#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0 #define SLJIT_LOCALS_OFFSET_BASE 0 #elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) #define SLJIT_NUMBER_OF_REGISTERS 26 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 10+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0+#define SLJIT_TMP_MEM_REG SLJIT_TMP_R0+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0 #define SLJIT_LOCALS_OFFSET_BASE (2 * (sljit_s32)sizeof(sljit_sw))+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1 #elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) #define SLJIT_NUMBER_OF_REGISTERS 23 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 17+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 18+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1+#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX) #define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * (sljit_s32)sizeof(sljit_sw)) #elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)@@ -739,18 +679,28 @@ #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 29 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 #endif+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 3+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1+#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1 -#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)+#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) -#define SLJIT_NUMBER_OF_REGISTERS 18-#define SLJIT_NUMBER_OF_SAVED_REGISTERS 14-#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14-#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0-#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)-/* saved registers (16), return struct pointer (1), space for 6 argument words (1),- 4th double arg (2), double alignment (1). */-#define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * (sljit_s32)sizeof(sljit_sw))-#endif+#define SLJIT_NUMBER_OF_REGISTERS 23+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 12+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1+#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_LOCALS_OFFSET_BASE 0+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1 #elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) @@ -777,16 +727,43 @@ #define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0+#define SLJIT_TMP_MEM_REG SLJIT_TMP_R2+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0 #define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE+#define SLJIT_MASKED_SHIFT 1 +#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)++#define SLJIT_NUMBER_OF_REGISTERS 23+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1+#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_LOCALS_OFFSET_BASE 0+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1+ #elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) +/* Just to have something. */ #define SLJIT_NUMBER_OF_REGISTERS 0 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 0+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 0 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 0 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 0+#define SLJIT_TMP_DEST_REG 0+#define SLJIT_TMP_MEM_REG 0+#define SLJIT_TMP_DEST_FREG 0 #define SLJIT_LOCALS_OFFSET_BASE 0 #endif@@ -799,6 +776,45 @@ #define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \ (SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS) +/**********************************/+/* Temporary register management. */+/**********************************/++#define SLJIT_TMP_REGISTER_BASE (SLJIT_NUMBER_OF_REGISTERS + 2)+#define SLJIT_TMP_FREGISTER_BASE (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)++/* WARNING: Accessing temporary registers is not recommended, because they+ are also used by the JIT compiler for various computations. Using them+ might have any side effects including incorrect operations and crashes,+ so use them at your own risk. The machine registers themselves might have+ limitations, e.g. the r0 register on s390x / ppc cannot be used as+ base address for memory operations. */++/* Temporary registers */+#define SLJIT_TMP_R0 (SLJIT_TMP_REGISTER_BASE + 0)+#define SLJIT_TMP_R1 (SLJIT_TMP_REGISTER_BASE + 1)+#define SLJIT_TMP_R2 (SLJIT_TMP_REGISTER_BASE + 2)+#define SLJIT_TMP_R3 (SLJIT_TMP_REGISTER_BASE + 3)+#define SLJIT_TMP_R4 (SLJIT_TMP_REGISTER_BASE + 4)+#define SLJIT_TMP_R5 (SLJIT_TMP_REGISTER_BASE + 5)+#define SLJIT_TMP_R6 (SLJIT_TMP_REGISTER_BASE + 6)+#define SLJIT_TMP_R7 (SLJIT_TMP_REGISTER_BASE + 7)+#define SLJIT_TMP_R8 (SLJIT_TMP_REGISTER_BASE + 8)+#define SLJIT_TMP_R9 (SLJIT_TMP_REGISTER_BASE + 9)+#define SLJIT_TMP_R(i) (SLJIT_TMP_REGISTER_BASE + (i))++#define SLJIT_TMP_FR0 (SLJIT_TMP_FREGISTER_BASE + 0)+#define SLJIT_TMP_FR1 (SLJIT_TMP_FREGISTER_BASE + 1)+#define SLJIT_TMP_FR2 (SLJIT_TMP_FREGISTER_BASE + 2)+#define SLJIT_TMP_FR3 (SLJIT_TMP_FREGISTER_BASE + 3)+#define SLJIT_TMP_FR4 (SLJIT_TMP_FREGISTER_BASE + 4)+#define SLJIT_TMP_FR5 (SLJIT_TMP_FREGISTER_BASE + 5)+#define SLJIT_TMP_FR6 (SLJIT_TMP_FREGISTER_BASE + 6)+#define SLJIT_TMP_FR7 (SLJIT_TMP_FREGISTER_BASE + 7)+#define SLJIT_TMP_FR8 (SLJIT_TMP_FREGISTER_BASE + 8)+#define SLJIT_TMP_FR9 (SLJIT_TMP_FREGISTER_BASE + 9)+#define SLJIT_TMP_FR(i) (SLJIT_TMP_FREGISTER_BASE + (i))+ /********************************/ /* CPU status flags management. */ /********************************/@@ -806,10 +822,24 @@ #if (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ || (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \- || (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) \- || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+ || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \+ || (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) #define SLJIT_HAS_STATUS_FLAGS_STATE 1 #endif++/***************************************/+/* Floating point register management. */+/***************************************/++#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define SLJIT_F64_SECOND(reg) \+ ((reg) + SLJIT_FS0 + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)+#else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */+#define SLJIT_F64_SECOND(reg) \+ (reg)+#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */ /*************************************/ /* Debug and verbose related macros. */
− src/c/pcre2/src/sljit/sljitExecAllocator.c
@@ -1,411 +0,0 @@-/*- * Stack-less Just-In-Time compiler- *- * 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:- *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.- *- * 2. Redistributions in binary form must reproduce the above copyright notice, this list- * of conditions and the following disclaimer in the documentation and/or other materials- * provided with the distribution.- *- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT- * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.- */--/*- This file contains a simple executable memory allocator-- It is assumed, that executable code blocks are usually medium (or sometimes- large) memory blocks, and the allocator is not too frequently called (less- optimized than other allocators). Thus, using it as a generic allocator is- not suggested.-- How does it work:- Memory is allocated in continuous memory areas called chunks by alloc_chunk()- Chunk format:- [ block ][ block ] ... [ block ][ block terminator ]-- All blocks and the block terminator is started with block_header. The block- header contains the size of the previous and the next block. These sizes- can also contain special values.- Block size:- 0 - The block is a free_block, with a different size member.- 1 - The block is a block terminator.- n - The block is used at the moment, and the value contains its size.- Previous block size:- 0 - This is the first block of the memory chunk.- n - The size of the previous block.-- Using these size values we can go forward or backward on the block chain.- The unused blocks are stored in a chain list pointed by free_blocks. This- list is useful if we need to find a suitable memory area when the allocator- is called.-- When a block is freed, the new free block is connected to its adjacent free- blocks if possible.-- [ free block ][ used block ][ free block ]- and "used block" is freed, the three blocks are connected together:- [ one big free block ]-*/--/* --------------------------------------------------------------------- */-/* System (OS) functions */-/* --------------------------------------------------------------------- */--/* 64 KByte. */-#define CHUNK_SIZE (sljit_uw)0x10000u--/*- alloc_chunk / free_chunk :- * allocate executable system memory chunks- * the size is always divisible by CHUNK_SIZE- SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK :- * provided as part of sljitUtils- * only the allocator requires this lock, sljit is fully thread safe- as it only uses local variables-*/--#ifdef _WIN32-#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)--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(void *chunk, sljit_uw size)-{- SLJIT_UNUSED_ARG(size);- VirtualFree(chunk, 0, MEM_RELEASE);-}--#else /* POSIX */--#if defined(__APPLE__) && defined(MAP_JIT)-/*- On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a- version where it's OK to have more than one JIT block or where MAP_JIT is- required.- On non-macOS systems, returns MAP_JIT if it is defined.-*/-#include <TargetConditionals.h>-#if TARGET_OS_OSX-#if defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86-#ifdef MAP_ANON-#include <sys/utsname.h>-#include <stdlib.h>--#define SLJIT_MAP_JIT (get_map_jit_flag())--static SLJIT_INLINE int get_map_jit_flag()-{- size_t page_size;- void *ptr;- struct utsname name;- static int map_jit_flag = -1;-- if (map_jit_flag < 0) {- map_jit_flag = 0;- uname(&name);-- /* Kernel version for 10.14.0 (Mojave) or later */- if (atoi(name.release) >= 18) {- page_size = get_page_alignment() + 1;- /* Only use MAP_JIT if a hardened runtime is used */- ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC,- MAP_PRIVATE | MAP_ANON, -1, 0);-- if (ptr != MAP_FAILED)- munmap(ptr, page_size);- else- map_jit_flag = MAP_JIT;- }- }- return map_jit_flag;-}-#endif /* MAP_ANON */-#else /* !SLJIT_CONFIG_X86 */-#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)-#error "Unsupported architecture"-#endif /* SLJIT_CONFIG_ARM */-#include <AvailabilityMacros.h>-#include <pthread.h>--#define SLJIT_MAP_JIT (MAP_JIT)-#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \- apple_update_wx_flags(enable_exec)--static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)-{-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000- pthread_jit_write_protect_np(enable_exec);-#else-#error "Must target Big Sur or newer"-#endif /* BigSur */-}-#endif /* SLJIT_CONFIG_X86 */-#else /* !TARGET_OS_OSX */-#define SLJIT_MAP_JIT (MAP_JIT)-#endif /* TARGET_OS_OSX */-#endif /* __APPLE__ && MAP_JIT */-#ifndef SLJIT_UPDATE_WX_FLAGS-#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)-#endif /* !SLJIT_UPDATE_WX_FLAGS */-#ifndef SLJIT_MAP_JIT-#define SLJIT_MAP_JIT (0)-#endif /* !SLJIT_MAP_JIT */--static SLJIT_INLINE void* alloc_chunk(sljit_uw size)-{- void *retval;- int prot = PROT_READ | PROT_WRITE | PROT_EXEC;- int flags = MAP_PRIVATE;- int fd = -1;--#ifdef PROT_MAX- prot |= PROT_MAX(prot);-#endif--#ifdef MAP_ANON- flags |= MAP_ANON | SLJIT_MAP_JIT;-#else /* !MAP_ANON */- if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))- return NULL;-- fd = dev_zero;-#endif /* MAP_ANON */-- retval = mmap(NULL, size, prot, flags, fd, 0);- if (retval == MAP_FAILED)- return NULL;--#ifdef __FreeBSD__- /* HardenedBSD's mmap lies, so check permissions again */- if (mprotect(retval, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {- munmap(retval, size);- return NULL;- }-#endif /* FreeBSD */-- SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0);-- return retval;-}--static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)-{- munmap(chunk, size);-}--#endif /* windows */--/* --------------------------------------------------------------------- */-/* Common functions */-/* --------------------------------------------------------------------- */--#define CHUNK_MASK (~(CHUNK_SIZE - 1))--struct block_header {- sljit_uw size;- sljit_uw prev_size;-};--struct free_block {- struct block_header header;- struct free_block *next;- struct free_block *prev;- sljit_uw size;-};--#define AS_BLOCK_HEADER(base, offset) \- ((struct block_header*)(((sljit_u8*)base) + offset))-#define AS_FREE_BLOCK(base, offset) \- ((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) + 7u) & ~(sljit_uw)7)--static struct free_block* free_blocks;-static sljit_uw allocated_size;-static sljit_uw total_size;--static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)-{- free_block->header.size = 0;- free_block->size = size;-- free_block->next = free_blocks;- free_block->prev = NULL;- if (free_blocks)- free_blocks->prev = free_block;- free_blocks = free_block;-}--static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)-{- if (free_block->next)- free_block->next->prev = free_block->prev;-- if (free_block->prev)- free_block->prev->next = free_block->next;- else {- SLJIT_ASSERT(free_blocks == free_block);- free_blocks = free_block->next;- }-}--SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)-{- struct block_header *header;- struct block_header *next_header;- struct free_block *free_block;- sljit_uw chunk_size;-- SLJIT_ALLOCATOR_LOCK();- if (size < (64 - sizeof(struct block_header)))- size = (64 - sizeof(struct block_header));- size = ALIGN_SIZE(size);-- free_block = free_blocks;- while (free_block) {- if (free_block->size >= size) {- chunk_size = free_block->size;- SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);- if (chunk_size > size + 64) {- /* We just cut a block from the end of the free block. */- chunk_size -= size;- free_block->size = chunk_size;- header = AS_BLOCK_HEADER(free_block, chunk_size);- header->prev_size = chunk_size;- AS_BLOCK_HEADER(header, size)->prev_size = size;- }- else {- sljit_remove_free_block(free_block);- header = (struct block_header*)free_block;- size = chunk_size;- }- allocated_size += size;- header->size = size;- SLJIT_ALLOCATOR_UNLOCK();- return MEM_START(header);- }- free_block = free_block->next;- }-- chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK;- header = (struct block_header*)alloc_chunk(chunk_size);- if (!header) {- SLJIT_ALLOCATOR_UNLOCK();- return NULL;- }-- chunk_size -= sizeof(struct block_header);- total_size += chunk_size;-- header->prev_size = 0;- if (chunk_size > size + 64) {- /* Cut the allocated space into a free and a used block. */- allocated_size += size;- header->size = size;- chunk_size -= size;-- free_block = AS_FREE_BLOCK(header, size);- free_block->header.prev_size = size;- sljit_insert_free_block(free_block, chunk_size);- next_header = AS_BLOCK_HEADER(free_block, chunk_size);- }- else {- /* All space belongs to this allocation. */- allocated_size += chunk_size;- header->size = chunk_size;- next_header = AS_BLOCK_HEADER(header, chunk_size);- }- next_header->size = 1;- next_header->prev_size = chunk_size;- SLJIT_ALLOCATOR_UNLOCK();- return MEM_START(header);-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)-{- struct block_header *header;- struct free_block* free_block;-- SLJIT_ALLOCATOR_LOCK();- header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));- allocated_size -= header->size;-- /* Connecting free blocks together if possible. */- SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);-- /* If header->prev_size == 0, free_block will equal to header.- In this case, free_block->header.size will be > 0. */- free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);- if (SLJIT_UNLIKELY(!free_block->header.size)) {- free_block->size += header->size;- header = AS_BLOCK_HEADER(free_block, free_block->size);- header->prev_size = free_block->size;- }- else {- free_block = (struct free_block*)header;- sljit_insert_free_block(free_block, header->size);- }-- header = AS_BLOCK_HEADER(free_block, free_block->size);- if (SLJIT_UNLIKELY(!header->size)) {- free_block->size += ((struct free_block*)header)->size;- sljit_remove_free_block((struct free_block*)header);- header = AS_BLOCK_HEADER(free_block, free_block->size);- header->prev_size = free_block->size;- }-- /* The whole chunk is free. */- if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {- /* If this block is freed, we still have (allocated_size / 2) free space. */- if (total_size - free_block->size > (allocated_size * 3 / 2)) {- total_size -= free_block->size;- sljit_remove_free_block(free_block);- free_chunk(free_block, free_block->size + sizeof(struct block_header));- }- }-- SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);- SLJIT_ALLOCATOR_UNLOCK();-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)-{- struct free_block* free_block;- struct free_block* next_free_block;-- SLJIT_ALLOCATOR_LOCK();- SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);-- free_block = free_blocks;- while (free_block) {- next_free_block = free_block->next;- if (!free_block->header.prev_size && - AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {- total_size -= free_block->size;- sljit_remove_free_block(free_block);- free_chunk(free_block, free_block->size + sizeof(struct block_header));- }- free_block = next_free_block;- }-- SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));- SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);- SLJIT_ALLOCATOR_UNLOCK();-}
src/c/pcre2/src/sljit/sljitLir.c view
@@ -93,2669 +93,3469 @@ #define SSIZE_OF(type) ((sljit_s32)sizeof(sljit_ ## type)) #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_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))--#define HAS_FLAGS(op) \- ((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))--#define GET_ALL_FLAGS(op) \- ((op) & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))--#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)-#define TYPE_CAST_NEEDED(op) \- ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32)-#else /* !SLJIT_64BIT_ARCHITECTURE */-#define TYPE_CAST_NEEDED(op) \- ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16)-#endif /* SLJIT_64BIT_ARCHITECTURE */--#define BUF_SIZE 4096--#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)-#define ABUF_SIZE 2048-#else-#define ABUF_SIZE 4096-#endif--/* Parameter parsing. */-#define REG_MASK 0x3f-#define OFFS_REG(reg) (((reg) >> 8) & REG_MASK)-#define OFFS_REG_MASK (REG_MASK << 8)-#define TO_OFFS_REG(reg) ((reg) << 8)-/* When reg cannot be unused. */-#define FAST_IS_REG(reg) ((reg) <= REG_MASK)--/* Mask for argument types. */-#define SLJIT_ARG_MASK 0x7-#define SLJIT_ARG_FULL_MASK (SLJIT_ARG_MASK | SLJIT_ARG_TYPE_SCRATCH_REG)--/* Jump flags. */-#define JUMP_LABEL 0x1-#define JUMP_ADDR 0x2-/* SLJIT_REWRITABLE_JUMP is 0x1000. */--#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)-# define PATCH_MB 0x4-# define PATCH_MW 0x8-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)-# define PATCH_MD 0x10-#endif-# define TYPE_SHIFT 13-#endif--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)-# define IS_BL 0x4-# define PATCH_B 0x8-#endif--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)-# define CPOOL_SIZE 512-#endif--#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)-# define IS_COND 0x04-# define IS_BL 0x08- /* conditional + imm8 */-# define PATCH_TYPE1 0x10- /* conditional + imm20 */-# define PATCH_TYPE2 0x20- /* IT + imm24 */-# define PATCH_TYPE3 0x30- /* imm11 */-# define PATCH_TYPE4 0x40- /* imm24 */-# define PATCH_TYPE5 0x50- /* BL + imm24 */-# define PATCH_BL 0x60- /* 0xf00 cc code for branches */-#endif--#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)-# define IS_COND 0x004-# define IS_CBZ 0x008-# define IS_BL 0x010-# define PATCH_B 0x020-# define PATCH_COND 0x040-# define PATCH_ABS48 0x080-# define PATCH_ABS64 0x100-#endif--#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)-# define IS_COND 0x004-# define IS_CALL 0x008-# define PATCH_B 0x010-# define PATCH_ABS_B 0x020-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-# define PATCH_ABS32 0x040-# define PATCH_ABS48 0x080-#endif-# define REMOVE_COND 0x100-#endif--#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)-# define IS_MOVABLE 0x004-# define IS_JAL 0x008-# define IS_CALL 0x010-# define IS_BIT26_COND 0x020-# define IS_BIT16_COND 0x040-# define IS_BIT23_COND 0x080--# define IS_COND (IS_BIT26_COND | IS_BIT16_COND | IS_BIT23_COND)--# define PATCH_B 0x100-# define PATCH_J 0x200--#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)-# define PATCH_ABS32 0x400-# define PATCH_ABS48 0x800-#endif-- /* instruction types */-# define MOVABLE_INS 0- /* 1 - 31 last destination register */- /* no destination (i.e: store) */-# define UNMOVABLE_INS 32- /* FPU status register */-# define FCSR_FCC 33-#endif--#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)-# define IS_MOVABLE 0x04-# define IS_COND 0x08-# define IS_CALL 0x10--# define PATCH_B 0x20-# define PATCH_CALL 0x40-- /* instruction types */-# define MOVABLE_INS 0- /* 1 - 31 last destination register */- /* no destination (i.e: store) */-# define UNMOVABLE_INS 32--# define DST_INS_MASK 0xff-- /* ICC_SET is the same as SET_FLAGS. */-# define ICC_IS_SET (1 << 23)-# define FCC_IS_SET (1 << 24)-#endif--/* Stack management. */--#define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \- (((scratches < SLJIT_NUMBER_OF_SCRATCH_REGISTERS ? 0 : (scratches - SLJIT_NUMBER_OF_SCRATCH_REGISTERS)) + \- (saveds) + (sljit_s32)(extra)) * (sljit_s32)sizeof(sljit_sw))--#define GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, size) \- (((fscratches < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS ? 0 : (fscratches - SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)) + \- (fsaveds)) * (sljit_s32)(size))--#define ADJUST_LOCAL_OFFSET(p, i) \- if ((p) == (SLJIT_MEM1(SLJIT_SP))) \- (i) += SLJIT_LOCALS_OFFSET;--#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */--/* Utils can still be used even if SLJIT_CONFIG_UNSUPPORTED is set. */-#include "sljitUtils.c"--#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"-#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)-#include "sljitWXExecAllocator.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--#ifndef SLJIT_UPDATE_WX_FLAGS-#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)-#endif--/* Argument checking features. */--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)--/* Returns with error when an invalid argument is passed. */--#define CHECK_ARGUMENT(x) \- do { \- if (SLJIT_UNLIKELY(!(x))) \- return 1; \- } while (0)--#define CHECK_RETURN_TYPE sljit_s32-#define CHECK_RETURN_OK return 0--#define CHECK(x) \- do { \- if (SLJIT_UNLIKELY(x)) { \- compiler->error = SLJIT_ERR_BAD_ARGUMENT; \- return SLJIT_ERR_BAD_ARGUMENT; \- } \- } while (0)--#define CHECK_PTR(x) \- do { \- if (SLJIT_UNLIKELY(x)) { \- compiler->error = SLJIT_ERR_BAD_ARGUMENT; \- return NULL; \- } \- } while (0)--#define CHECK_REG_INDEX(x) \- do { \- if (SLJIT_UNLIKELY(x)) { \- return -2; \- } \- } while (0)--#elif (defined SLJIT_DEBUG && SLJIT_DEBUG)--/* Assertion failure occures if an invalid argument is passed. */-#undef SLJIT_ARGUMENT_CHECKS-#define SLJIT_ARGUMENT_CHECKS 1--#define CHECK_ARGUMENT(x) SLJIT_ASSERT(x)-#define CHECK_RETURN_TYPE void-#define CHECK_RETURN_OK return-#define CHECK(x) x-#define CHECK_PTR(x) x-#define CHECK_REG_INDEX(x) x--#elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE)--/* Arguments are not checked. */-#define CHECK_RETURN_TYPE void-#define CHECK_RETURN_OK return-#define CHECK(x) x-#define CHECK_PTR(x) x-#define CHECK_REG_INDEX(x) x--#else--/* Arguments are not checked. */-#define CHECK(x)-#define CHECK_PTR(x)-#define CHECK_REG_INDEX(x)--#endif /* SLJIT_ARGUMENT_CHECKS */--/* --------------------------------------------------------------------- */-/* Public functions */-/* --------------------------------------------------------------------- */--#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)-#define SLJIT_NEEDS_COMPILER_INIT 1-static sljit_s32 compiler_initialized = 0;-/* A thread safe initialization. */-static void init_compiler(void);-#endif--SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data)-{- struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler), allocator_data);- if (!compiler)- return NULL;- SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler));-- SLJIT_COMPILE_ASSERT(- 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_REWRITABLE_JUMP != SLJIT_32,- 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;-- compiler->allocator_data = allocator_data;- compiler->exec_allocator_data = exec_allocator_data;- compiler->buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);- compiler->abuf = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, allocator_data);-- if (!compiler->buf || !compiler->abuf) {- if (compiler->buf)- SLJIT_FREE(compiler->buf, allocator_data);- if (compiler->abuf)- SLJIT_FREE(compiler->abuf, allocator_data);- SLJIT_FREE(compiler, allocator_data);- return NULL;- }-- compiler->buf->next = NULL;- compiler->buf->used_size = 0;- compiler->abuf->next = NULL;- compiler->abuf->used_size = 0;-- compiler->scratches = -1;- compiler->saveds = -1;- compiler->fscratches = -1;- compiler->fsaveds = -1;- compiler->local_size = -1;--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- compiler->args_size = -1;-#endif--#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_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_u8*)(compiler->cpool + CPOOL_SIZE);- compiler->cpool_diff = 0xffffffff;-#endif--#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)- compiler->delay_slot = UNMOVABLE_INS;-#endif--#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- compiler->delay_slot = UNMOVABLE_INS;-#endif--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \- || (defined SLJIT_DEBUG && SLJIT_DEBUG)- compiler->last_flags = 0;- compiler->last_return = -1;- compiler->logical_local_size = 0;-#endif--#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT)- if (!compiler_initialized) {- init_compiler();- compiler_initialized = 1;- }-#endif-- return compiler;-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)-{- struct sljit_memory_fragment *buf;- struct sljit_memory_fragment *curr;- void *allocator_data = compiler->allocator_data;- SLJIT_UNUSED_ARG(allocator_data);-- buf = compiler->buf;- while (buf) {- curr = buf;- buf = buf->next;- SLJIT_FREE(curr, allocator_data);- }-- buf = compiler->abuf;- while (buf) {- curr = buf;- buf = buf->next;- SLJIT_FREE(curr, allocator_data);- }--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- SLJIT_FREE(compiler->cpool, allocator_data);-#endif- SLJIT_FREE(compiler, allocator_data);-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)-{- if (compiler->error == SLJIT_SUCCESS)- compiler->error = SLJIT_ERR_ALLOC_FAILED;-}--#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)-SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)-{- SLJIT_UNUSED_ARG(exec_allocator_data);-- /* Remove thumb mode flag. */- SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~(sljit_uw)0x1), exec_allocator_data);-}-#elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)-SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)-{- SLJIT_UNUSED_ARG(exec_allocator_data);-- /* Resolve indirection. */- code = (void*)(*(sljit_uw*)code);- SLJIT_FREE_EXEC(code, exec_allocator_data);-}-#else-SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)-{- SLJIT_UNUSED_ARG(exec_allocator_data);-- SLJIT_FREE_EXEC(code, exec_allocator_data);-}-#endif--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)-{- if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) {- jump->flags &= (sljit_uw)~JUMP_ADDR;- jump->flags |= JUMP_LABEL;- jump->u.label = label;- }-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)-{- if (SLJIT_LIKELY(!!jump)) {- jump->flags &= (sljit_uw)~JUMP_LABEL;- jump->flags |= JUMP_ADDR;- jump->u.target = target;- }-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label)-{- if (SLJIT_LIKELY(!!put_label))- put_label->label = label;-}--#define SLJIT_CURRENT_FLAGS_ALL \- (SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE)--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_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)- compiler->status_flags_state = current_flags;-#endif--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->last_flags = 0;- if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_ALL)) == 0) {- compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_32 | SLJIT_SET_Z));- }-#endif-}--/* --------------------------------------------------------------------- */-/* Private functions */-/* --------------------------------------------------------------------- */--static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size)-{- sljit_u8 *ret;- struct sljit_memory_fragment *new_frag;-- SLJIT_ASSERT(size <= 256);- if (compiler->buf->used_size + size <= (BUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {- ret = compiler->buf->memory + compiler->buf->used_size;- compiler->buf->used_size += size;- return ret;- }- new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, compiler->allocator_data);- PTR_FAIL_IF_NULL(new_frag);- new_frag->next = compiler->buf;- compiler->buf = new_frag;- new_frag->used_size = size;- return new_frag->memory;-}--static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size)-{- sljit_u8 *ret;- struct sljit_memory_fragment *new_frag;-- SLJIT_ASSERT(size <= 256);- if (compiler->abuf->used_size + size <= (ABUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {- ret = compiler->abuf->memory + compiler->abuf->used_size;- compiler->abuf->used_size += size;- return ret;- }- new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, compiler->allocator_data);- PTR_FAIL_IF_NULL(new_frag);- new_frag->next = compiler->abuf;- compiler->abuf = new_frag;- new_frag->used_size = size;- return new_frag->memory;-}--SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)-{- CHECK_ERROR_PTR();--#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)- if (size <= 0 || size > 128)- return NULL;- size = (size + 7) & ~7;-#else- if (size <= 0 || size > 64)- return NULL;- size = (size + 3) & ~3;-#endif- return ensure_abuf(compiler, (sljit_uw)size);-}--static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)-{- struct sljit_memory_fragment *buf = compiler->buf;- struct sljit_memory_fragment *prev = NULL;- struct sljit_memory_fragment *tmp;-- do {- tmp = buf->next;- buf->next = prev;- prev = buf;- buf = tmp;- } while (buf != NULL);-- compiler->buf = prev;-}--/* Only used in RISC architectures where the instruction size is constant */-#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \- && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)--static SLJIT_INLINE sljit_uw compute_next_addr(struct sljit_label *label, struct sljit_jump *jump,- struct sljit_const *const_, struct sljit_put_label *put_label)-{- sljit_uw result = ~(sljit_uw)0;-- if (label)- result = label->size;-- if (jump && jump->addr < result)- result = jump->addr;-- if (const_ && const_->addr < result)- result = const_->addr;-- if (put_label && put_label->addr < result)- result = put_label->addr;-- return result;-}--#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_S390X */--static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- SLJIT_UNUSED_ARG(args);- SLJIT_UNUSED_ARG(local_size);-- compiler->options = options;- compiler->scratches = scratches;- compiler->saveds = saveds;- compiler->fscratches = fscratches;- compiler->fsaveds = fsaveds;-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->last_return = args & SLJIT_ARG_MASK;- compiler->logical_local_size = local_size;-#endif-}--static SLJIT_INLINE void set_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(args);- SLJIT_UNUSED_ARG(local_size);-- compiler->options = options;- compiler->scratches = scratches;- compiler->saveds = saveds;- compiler->fscratches = fscratches;- compiler->fsaveds = fsaveds;-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->last_return = args & SLJIT_ARG_MASK;- compiler->logical_local_size = local_size;-#endif-}--static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler)-{- label->next = NULL;- label->size = compiler->size;- if (compiler->last_label)- compiler->last_label->next = label;- else- compiler->labels = label;- compiler->last_label = label;-}--static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_u32 flags)-{- jump->next = NULL;- jump->flags = flags;- if (compiler->last_jump)- compiler->last_jump->next = jump;- else- compiler->jumps = jump;- compiler->last_jump = jump;-}--static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_compiler *compiler)-{- const_->next = NULL;- const_->addr = compiler->size;- if (compiler->last_const)- compiler->last_const->next = const_;- else- compiler->consts = const_;- compiler->last_const = const_;-}--static SLJIT_INLINE void set_put_label(struct sljit_put_label *put_label, struct sljit_compiler *compiler, sljit_uw offset)-{- put_label->next = NULL;- put_label->label = NULL;- put_label->addr = compiler->size - offset;- put_label->flags = 0;- if (compiler->last_put_label)- compiler->last_put_label->next = put_label;- else- compiler->put_labels = put_label;- compiler->last_put_label = put_label;-}--#define ADDRESSING_DEPENDS_ON(exp, reg) \- (((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)--static sljit_s32 function_check_arguments(sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches)-{- sljit_s32 word_arg_count, scratch_arg_end, saved_arg_count, float_arg_count, curr_type;-- curr_type = (arg_types & SLJIT_ARG_FULL_MASK);-- if (curr_type >= SLJIT_ARG_TYPE_F64) {- if (curr_type > SLJIT_ARG_TYPE_F32 || fscratches == 0)- return 0;- } else if (curr_type >= SLJIT_ARG_TYPE_W) {- if (scratches == 0)- return 0;- }-- arg_types >>= SLJIT_ARG_SHIFT;-- word_arg_count = 0;- scratch_arg_end = 0;- saved_arg_count = 0;- float_arg_count = 0;- while (arg_types != 0) {- if (word_arg_count + float_arg_count >= 4)- return 0;-- curr_type = (arg_types & SLJIT_ARG_MASK);-- if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {- if (saveds == -1 || curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_P)- return 0;-- word_arg_count++;- scratch_arg_end = word_arg_count;- } else {- if (curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_F32)- return 0;-- if (curr_type < SLJIT_ARG_TYPE_F64) {- word_arg_count++;- saved_arg_count++;- } else- float_arg_count++;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- if (saveds == -1)- return (word_arg_count <= scratches && float_arg_count <= fscratches);-- return (saved_arg_count <= saveds && scratch_arg_end <= scratches && float_arg_count <= fscratches);-}--#define FUNCTION_CHECK_IS_REG(r) \- (((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \- || ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))--#define FUNCTION_CHECK_IS_FREG(fr) \- (((fr) >= SLJIT_FR0 && (fr) < (SLJIT_FR0 + compiler->fscratches)) \- || ((fr) > (SLJIT_FS0 - compiler->fsaveds) && (fr) <= SLJIT_FS0))--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)-#define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8)-#else-#define CHECK_IF_VIRTUAL_REGISTER(p) 0-#endif--static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)-{- if (compiler->scratches == -1 || compiler->saveds == -1)- return 0;-- if (!(p & SLJIT_MEM))- return 0;-- if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK)))- return 0;-- if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK))- return 0;-- if (p & OFFS_REG_MASK) {- if (!(p & REG_MASK))- return 0;-- if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p))))- return 0;-- if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p)))- return 0;-- if ((i & ~0x3) != 0)- return 0;- }-- return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0;-}--#define FUNCTION_CHECK_SRC_MEM(p, i) \- CHECK_ARGUMENT(function_check_src_mem(compiler, p, i));--static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)-{- if (compiler->scratches == -1 || compiler->saveds == -1)- return 0;-- if (FUNCTION_CHECK_IS_REG(p))- return (i == 0);-- if (p == SLJIT_IMM)- return 1;-- if (p == SLJIT_MEM1(SLJIT_SP))- return (i >= 0 && i < compiler->logical_local_size);-- return function_check_src_mem(compiler, p, i);-}--#define FUNCTION_CHECK_SRC(p, i) \- CHECK_ARGUMENT(function_check_src(compiler, p, i));--static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)-{- if (compiler->scratches == -1 || compiler->saveds == -1)- return 0;-- if (FUNCTION_CHECK_IS_REG(p))- return (i == 0);-- if (p == SLJIT_MEM1(SLJIT_SP))- return (i >= 0 && i < compiler->logical_local_size);-- return function_check_src_mem(compiler, p, i);-}--#define FUNCTION_CHECK_DST(p, i) \- CHECK_ARGUMENT(function_check_dst(compiler, p, i));--static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)-{- if (compiler->scratches == -1 || compiler->saveds == -1)- return 0;-- if (FUNCTION_CHECK_IS_FREG(p))- return (i == 0);-- if (p == SLJIT_MEM1(SLJIT_SP))- return (i >= 0 && i < compiler->logical_local_size);-- return function_check_src_mem(compiler, p, i);-}--#define FUNCTION_FCHECK(p, i) \- CHECK_ARGUMENT(function_fcheck(compiler, p, i));--#endif /* SLJIT_ARGUMENT_CHECKS */--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)--SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)-{- compiler->verbose = verbose;-}--#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)-#ifdef _WIN64-# define SLJIT_PRINT_D "I64"-#else-# define SLJIT_PRINT_D "l"-#endif-#else-# define SLJIT_PRINT_D ""-#endif--static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r)-{- if (r < (SLJIT_R0 + compiler->scratches))- fprintf(compiler->verbose, "r%d", r - SLJIT_R0);- else if (r != SLJIT_SP)- fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r);- else- fprintf(compiler->verbose, "sp");-}--static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r)-{- if (r < (SLJIT_FR0 + compiler->fscratches))- fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0);- else- fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r);-}--static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)-{- if ((p) & SLJIT_IMM)- fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i));- else if ((p) & SLJIT_MEM) {- if ((p) & REG_MASK) {- fputc('[', compiler->verbose);- sljit_verbose_reg(compiler, (p) & REG_MASK);- if ((p) & OFFS_REG_MASK) {- fprintf(compiler->verbose, " + ");- sljit_verbose_reg(compiler, OFFS_REG(p));- if (i)- fprintf(compiler->verbose, " * %d", 1 << (i));- }- else if (i)- fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));- fputc(']', compiler->verbose);- }- else- fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));- } else- sljit_verbose_reg(compiler, p);-}--static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)-{- if ((p) & SLJIT_MEM) {- if ((p) & REG_MASK) {- fputc('[', compiler->verbose);- sljit_verbose_reg(compiler, (p) & REG_MASK);- if ((p) & OFFS_REG_MASK) {- fprintf(compiler->verbose, " + ");- sljit_verbose_reg(compiler, OFFS_REG(p));- if (i)- fprintf(compiler->verbose, "%d", 1 << (i));- }- else if (i)- fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));- fputc(']', compiler->verbose);- }- else- fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));- }- else- sljit_verbose_freg(compiler, p);-}--static const char* op0_names[] = {- "breakpoint", "nop", "lmul.uw", "lmul.sw",- "divmod.u", "divmod.s", "div.u", "div.s",- "endbr", "skip_frames_before_return"-};--static const char* op1_names[] = {- "", ".u8", ".s8", ".u16",- ".s16", ".u32", ".s32", "32",- ".p", "not", "clz",-};--static const char* op2_names[] = {- "add", "addc", "sub", "subc",- "mul", "and", "or", "xor",- "shl", "lshr", "ashr",-};--static const char* op_src_names[] = {- "fast_return", "skip_frames_before_fast_return",- "prefetch_l1", "prefetch_l2",- "prefetch_l3", "prefetch_once",-};--static const char* fop1_names[] = {- "mov", "conv", "conv", "conv",- "conv", "conv", "cmp", "neg",- "abs",-};--static const char* fop2_names[] = {- "add", "sub", "mul", "div"-};--#define JUMP_POSTFIX(type) \- ((type & 0xff) <= SLJIT_NOT_OVERFLOW ? ((type & SLJIT_32) ? "32" : "") \- : ((type & 0xff) <= SLJIT_ORDERED_F64 ? ((type & SLJIT_32) ? ".f32" : ".f64") : ""))--static const char* jump_names[] = {- "equal", "not_equal",- "less", "greater_equal",- "greater", "less_equal",- "sig_less", "sig_greater_equal",- "sig_greater", "sig_less_equal",- "overflow", "not_overflow",- "carry", "",- "equal", "not_equal",- "less", "greater_equal",- "greater", "less_equal",- "unordered", "ordered",- "jump", "fast_call",- "call", "call.cdecl"-};--static const char* call_arg_names[] = {- "void", "w", "32", "p", "f64", "f32"-};--#endif /* SLJIT_VERBOSE */--/* --------------------------------------------------------------------- */-/* Arch dependent */-/* --------------------------------------------------------------------- */--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \- || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler)-{-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- struct sljit_jump *jump;-#endif-- SLJIT_UNUSED_ARG(compiler);--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(compiler->size > 0);- jump = compiler->jumps;- while (jump) {- /* All jumps have target. */- CHECK_ARGUMENT(jump->flags & (JUMP_LABEL | JUMP_ADDR));- jump = jump->next;- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- SLJIT_UNUSED_ARG(compiler);--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(!(options & ~SLJIT_ENTER_CDECL));- CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);- CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);- CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);- CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);- CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);- CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);- CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);- CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);- CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds, fscratches));-- compiler->last_flags = 0;-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " enter ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);-- arg_types >>= SLJIT_ARG_SHIFT;- if (arg_types) {- fprintf(compiler->verbose, "], args[");- do {- fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],- (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");- arg_types >>= SLJIT_ARG_SHIFT;- if (arg_types)- fprintf(compiler->verbose, ",");- } while (arg_types);- }-- fprintf(compiler->verbose, "],%s scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",- (options & SLJIT_ENTER_CDECL) ? " enter:cdecl," : "",- scratches, saveds, fscratches, fsaveds, local_size);- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- SLJIT_UNUSED_ARG(compiler);--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(!(options & ~SLJIT_ENTER_CDECL));- CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);- CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);- CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);- CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);- CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);- CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);- CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);- CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);- CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds, fscratches));-- compiler->last_flags = 0;-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " set_context ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);-- arg_types >>= SLJIT_ARG_SHIFT;- if (arg_types) {- fprintf(compiler->verbose, "], args[");- do {- fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],- (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");- arg_types >>= SLJIT_ARG_SHIFT;- if (arg_types)- fprintf(compiler->verbose, ",");- } while (arg_types);- }-- fprintf(compiler->verbose, "],%s scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",- (options & SLJIT_ENTER_CDECL) ? " enter:cdecl," : "",- scratches, saveds, fscratches, fsaveds, local_size);- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_void(struct sljit_compiler *compiler)-{- if (SLJIT_UNLIKELY(compiler->skip_checks)) {- compiler->skip_checks = 0;- CHECK_RETURN_OK;- }--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(compiler->last_return == SLJIT_ARG_TYPE_VOID);-#endif--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " return_void\n");- }-#endif- CHECK_RETURN_OK;-}--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);-- switch (compiler->last_return) {- case SLJIT_ARG_TYPE_W:- CHECK_ARGUMENT(op >= SLJIT_MOV && op <= SLJIT_MOV_S32);- break;- case SLJIT_ARG_TYPE_32:- CHECK_ARGUMENT(op == SLJIT_MOV32 || (op >= SLJIT_MOV32_U8 && op <= SLJIT_MOV32_S16));- break;- case SLJIT_ARG_TYPE_P:- CHECK_ARGUMENT(op == SLJIT_MOV_P);- break;- default:- /* Context not initialized, void, etc. */- CHECK_ARGUMENT(0);- break;- }- FUNCTION_CHECK_SRC(src, srcw);- compiler->last_flags = 0;-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32",- op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE]);- sljit_verbose_param(compiler, src, srcw);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--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);- compiler->last_flags = 0;-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " fast_enter ");- sljit_verbose_param(compiler, dst, dstw);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--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_LMUL_SW)- || ((op & ~SLJIT_32) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_32) <= SLJIT_DIV_SW)- || (op >= SLJIT_ENDBR && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN));- CHECK_ARGUMENT(GET_OPCODE(op) < SLJIT_LMUL_UW || GET_OPCODE(op) >= SLJIT_ENDBR || compiler->scratches >= 2);- if ((GET_OPCODE(op) >= SLJIT_LMUL_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN)- compiler->last_flags = 0;-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose))- {- fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);- if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) {- fprintf(compiler->verbose, (op & SLJIT_32) ? "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_s32 op,- sljit_s32 dst, sljit_sw dstw,- sljit_s32 src, sljit_sw srcw)-{- if (SLJIT_UNLIKELY(compiler->skip_checks)) {- compiler->skip_checks = 0;- CHECK_RETURN_OK;- }--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ);-- switch (GET_OPCODE(op)) {- case SLJIT_NOT:- /* Only SLJIT_32 and SLJIT_SET_Z are allowed. */- CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));- break;- case SLJIT_MOV:- case SLJIT_MOV_U32:- case SLJIT_MOV_P:- /* Nothing allowed */- CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));- break;- default:- /* Only SLJIT_32 is allowed. */- CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));- break;- }-- FUNCTION_CHECK_DST(dst, dstw);- FUNCTION_CHECK_SRC(src, srcw);-- if (GET_OPCODE(op) >= SLJIT_NOT) {- CHECK_ARGUMENT(src != SLJIT_IMM);- compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));- }-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- if (GET_OPCODE(op) <= SLJIT_MOV_P)- {- fprintf(compiler->verbose, " mov%s%s ", !(op & SLJIT_32) ? "" : "32",- 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_32) ? "" : "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);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 unset,- 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;- CHECK_RETURN_OK;- }--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR);-- 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_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_32) == (compiler->last_flags & SLJIT_32));- break;- default:- SLJIT_UNREACHABLE();- break;- }-- if (unset) {- CHECK_ARGUMENT(HAS_FLAGS(op));- } else {- FUNCTION_CHECK_DST(dst, dstw);- }- FUNCTION_CHECK_SRC(src1, src1w);- FUNCTION_CHECK_SRC(src2, src2w);- compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",- !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",- !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);- if (unset)- fprintf(compiler->verbose, "unset");- else- sljit_verbose_param(compiler, dst, dstw);- fprintf(compiler->verbose, ", ");- sljit_verbose_param(compiler, src1, src1w);- fprintf(compiler->verbose, ", ");- sljit_verbose_param(compiler, src2, src2w);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw)-{-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE);- FUNCTION_CHECK_SRC(src, srcw);-- if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN)- {- CHECK_ARGUMENT(src != SLJIT_IMM);- compiler->last_flags = 0;- }- else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE)- {- CHECK_ARGUMENT(src & SLJIT_MEM);- }-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " %s ", op_src_names[op - SLJIT_OP_SRC_BASE]);- sljit_verbose_param(compiler, src, srcw);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--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)- CHECK_ARGUMENT(reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS);-#endif- CHECK_RETURN_OK;-}--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)- CHECK_ARGUMENT(reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- sljit_u32 i;-#endif-- SLJIT_UNUSED_ARG(compiler);--#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)- CHECK_ARGUMENT((size == 2 && (((sljit_sw)instruction) & 0x1) == 0)- || (size == 4 && (((sljit_sw)instruction) & 0x3) == 0));-#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)- CHECK_ARGUMENT(size == 2 || size == 4 || size == 6);-#else- 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_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_s32 op,- sljit_s32 dst, sljit_sw dstw,- sljit_s32 src, sljit_sw srcw)-{- if (SLJIT_UNLIKELY(compiler->skip_checks)) {- compiler->skip_checks = 0;- CHECK_RETURN_OK;- }--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- 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_CONV_F64_FROM_F32)- fprintf(compiler->verbose, " %s%s ", fop1_names[SLJIT_CONV_F64_FROM_F32 - SLJIT_FOP1_BASE],- (op & SLJIT_32) ? ".f32.from.f64" : ".f64.from.f32");- else- fprintf(compiler->verbose, " %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],- (op & SLJIT_32) ? ".f32" : ".f64");-- sljit_verbose_fparam(compiler, dst, dstw);- fprintf(compiler->verbose, ", ");- sljit_verbose_fparam(compiler, src, srcw);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--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_32 | 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_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", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_32) ? ".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);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--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;- CHECK_RETURN_OK;- }--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- 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);-#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_CONV_S32_FROM_F64) ? ".s32" : ".sw",- (op & SLJIT_32) ? ".f32" : ".f64");- sljit_verbose_param(compiler, dst, dstw);- fprintf(compiler->verbose, ", ");- sljit_verbose_fparam(compiler, src, srcw);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--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;- CHECK_RETURN_OK;- }--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- 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_32) ? ".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);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--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_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 ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_32) ? ".f32" : ".f64");- sljit_verbose_fparam(compiler, dst, dstw);- fprintf(compiler->verbose, ", ");- sljit_verbose_fparam(compiler, src1, src1w);- fprintf(compiler->verbose, ", ");- sljit_verbose_fparam(compiler, src2, src2w);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compiler *compiler)-{- 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");-#endif- CHECK_RETURN_OK;-}--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;- CHECK_RETURN_OK;- }--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));- CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL);- CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_32));-- if ((type & 0xff) < SLJIT_JUMP) {- if ((type & 0xff) <= SLJIT_NOT_ZERO)- CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);- else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {- CHECK_ARGUMENT((type & 0xff) == SLJIT_CARRY || (type & 0xff) == SLJIT_NOT_CARRY);- compiler->last_flags = 0;- } else- CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)- || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW));- }-#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_names[type & 0xff], JUMP_POSTFIX(type));-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types)-{-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN)));- CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);- CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));-- if (type & SLJIT_CALL_RETURN) {- CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);- }-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " %s%s%s ret[%s", jump_names[type & 0xff],- !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",- !(type & SLJIT_CALL_RETURN) ? "" : ".ret",- call_arg_names[arg_types & SLJIT_ARG_MASK]);-- arg_types >>= SLJIT_ARG_SHIFT;- if (arg_types) {- fprintf(compiler->verbose, "], args[");- do {- fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);- arg_types >>= SLJIT_ARG_SHIFT;- if (arg_types)- fprintf(compiler->verbose, ",");- } while (arg_types);- }- fprintf(compiler->verbose, "]\n");- }-#endif- CHECK_RETURN_OK;-}--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_32)));- 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",- jump_names[type & 0xff], (type & SLJIT_32) ? "32" : "");- sljit_verbose_param(compiler, src1, src1w);- fprintf(compiler->verbose, ", ");- sljit_verbose_param(compiler, src2, src2w);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--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_has_cpu_feature(SLJIT_HAS_FPU));- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));- 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",- jump_names[type & 0xff], (type & SLJIT_32) ? ".f32" : ".f64");- sljit_verbose_fparam(compiler, src1, src1w);- fprintf(compiler->verbose, ", ");- sljit_verbose_fparam(compiler, src2, src2w);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 src, sljit_sw srcw)-{- if (SLJIT_UNLIKELY(compiler->skip_checks)) {- compiler->skip_checks = 0;- CHECK_RETURN_OK;- }--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL);- FUNCTION_CHECK_SRC(src, srcw);-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " ijump.%s ", jump_names[type]);- sljit_verbose_param(compiler, src, srcw);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN)));- CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);- CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));- FUNCTION_CHECK_SRC(src, srcw);-- if (type & SLJIT_CALL_RETURN) {- CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);- }-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff],- !(type & SLJIT_CALL_RETURN) ? "" : ".ret",- call_arg_names[arg_types & SLJIT_ARG_MASK]);-- arg_types >>= SLJIT_ARG_SHIFT;- if (arg_types) {- fprintf(compiler->verbose, "], args[");- do {- fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);- arg_types >>= SLJIT_ARG_SHIFT;- if (arg_types)- fprintf(compiler->verbose, ",");- } while (arg_types);- }- 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_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_32)));- CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);- CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32- || (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));- 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_CARRY && (compiler->last_flags & 0xff) == SLJIT_CARRY)- || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW));-- FUNCTION_CHECK_DST(dst, dstw);-- if (GET_OPCODE(op) >= SLJIT_ADD)- compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- 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_32) ? "32" : ""));- sljit_verbose_param(compiler, dst, dstw);- 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_32)));- CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);-- CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1);- CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_32));- if (src != SLJIT_IMM) {- CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src));- CHECK_ARGUMENT(srcw == 0);- }-- 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));-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " cmov%s %s%s, ",- !(dst_reg & SLJIT_32) ? "" : "32",- jump_names[type & 0xff], JUMP_POSTFIX(type));- sljit_verbose_reg(compiler, dst_reg & ~SLJIT_32);- 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_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 reg,- sljit_s32 mem, sljit_sw memw)-{-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);- CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P));- CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));- CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));- CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);-- FUNCTION_CHECK_SRC_MEM(mem, memw);- CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));-- CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {- if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED)- fprintf(compiler->verbose, " //");-- fprintf(compiler->verbose, " mem%s.%s%s%s ",- !(type & SLJIT_32) ? "" : "32",- (type & SLJIT_MEM_STORE) ? "st" : "ld",- op1_names[(type & 0xff) - SLJIT_OP1_BASE],- (type & SLJIT_MEM_PRE) ? ".pre" : ".post");- sljit_verbose_reg(compiler, reg);- fprintf(compiler->verbose, ", ");- sljit_verbose_param(compiler, mem, memw);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 freg,- sljit_s32 mem, sljit_sw memw)-{-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);- CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));- CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));- CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);-- FUNCTION_CHECK_SRC_MEM(mem, memw);- CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg));-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {- if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED)- fprintf(compiler->verbose, " //");-- fprintf(compiler->verbose, " fmem.%s%s%s ",- (type & SLJIT_MEM_STORE) ? "st" : "ld",- !(type & SLJIT_32) ? ".f64" : ".f32",- (type & SLJIT_MEM_PRE) ? ".pre" : ".post");- sljit_verbose_freg(compiler, freg);- fprintf(compiler->verbose, ", ");- sljit_verbose_param(compiler, mem, memw);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)-{- /* Any offset is allowed. */- SLJIT_UNUSED_ARG(offset);--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- FUNCTION_CHECK_DST(dst, dstw);-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " local_base ");- sljit_verbose_param(compiler, dst, dstw);- fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset);- }-#endif- CHECK_RETURN_OK;-}--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);-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " const ");- sljit_verbose_param(compiler, dst, dstw);- fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);- }-#endif- CHECK_RETURN_OK;-}--static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- FUNCTION_CHECK_DST(dst, dstw);-#endif-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- if (SLJIT_UNLIKELY(!!compiler->verbose)) {- fprintf(compiler->verbose, " put_label ");- sljit_verbose_param(compiler, dst, dstw);- fprintf(compiler->verbose, "\n");- }-#endif- CHECK_RETURN_OK;-}--#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */--#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \- SLJIT_COMPILE_ASSERT(!(SLJIT_CONV_SW_FROM_F64 & 0x1) && !(SLJIT_CONV_F64_FROM_SW & 0x1), \- invalid_float_opcodes); \- 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_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_conv_sw_from_f64(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_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_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)-{-#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)- /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */- 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_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P))- return SLJIT_SUCCESS;-#endif--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \- || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- compiler->skip_checks = 1;-#endif- return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);-}--#if !(defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)--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));-- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \- || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- compiler->skip_checks = 1;-#endif- return sljit_emit_return_void(compiler);-}--#endif--#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_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6))--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_32) ? 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_32, 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)-#define SLJIT_CPUINFO_PART1 " 32bit ("-#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)-#define SLJIT_CPUINFO_PART1 " 64bit ("-#else-#error "Internal error: CPU type info missing"-#endif--#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)-#define SLJIT_CPUINFO_PART2 "little endian + "-#elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)-#define SLJIT_CPUINFO_PART2 "big endian + "-#else-#error "Internal error: CPU type info missing"-#endif--#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)-#define SLJIT_CPUINFO_PART3 "unaligned)"-#else-#define SLJIT_CPUINFO_PART3 "aligned)"-#endif--#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3--#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)-# include "sljitNativeX86_common.c"-#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)-# include "sljitNativeARM_32.c"-#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)-# include "sljitNativeARM_32.c"-#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)-# include "sljitNativeARM_T2_32.c"-#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)-# include "sljitNativeARM_64.c"-#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)-# include "sljitNativePPC_common.c"-#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)-# include "sljitNativeMIPS_common.c"-#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)-# include "sljitNativeSPARC_common.c"-#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)-# include "sljitNativeS390X.c"-#endif--#if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)--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_s32 flags, tmp_src, condition;- sljit_sw tmp_srcw;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));-- condition = type & 0xff;-#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)- if ((condition == SLJIT_EQUAL || condition == SLJIT_NOT_EQUAL)) {- if ((src1 & SLJIT_IMM) && !src1w) {- src1 = src2;- src1w = src2w;- src2 = SLJIT_IMM;- src2w = 0;- }- if ((src2 & SLJIT_IMM) && !src2w)- return emit_cmp_to0(compiler, type, src1, src1w);- }-#endif-- if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) {- /* Immediate is preferred as second argument by most architectures. */- switch (condition) {- case SLJIT_LESS:- condition = SLJIT_GREATER;- break;- case SLJIT_GREATER_EQUAL:- condition = SLJIT_LESS_EQUAL;- break;- case SLJIT_GREATER:- condition = SLJIT_LESS;- break;- case SLJIT_LESS_EQUAL:- condition = SLJIT_GREATER_EQUAL;- break;- case SLJIT_SIG_LESS:- condition = SLJIT_SIG_GREATER;- break;- case SLJIT_SIG_GREATER_EQUAL:- condition = SLJIT_SIG_LESS_EQUAL;- break;- case SLJIT_SIG_GREATER:- condition = SLJIT_SIG_LESS;- break;- case SLJIT_SIG_LESS_EQUAL:- condition = SLJIT_SIG_GREATER_EQUAL;- break;- }-- type = condition | (type & (SLJIT_32 | SLJIT_REWRITABLE_JUMP));- tmp_src = src1;- src1 = src2;- src2 = tmp_src;- tmp_srcw = src1w;- src1w = src2w;- src2w = tmp_srcw;- }-- if (condition <= SLJIT_NOT_ZERO)- flags = SLJIT_SET_Z;- else- 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_op2u(compiler,- SLJIT_SUB | flags | (type & SLJIT_32), 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 | SLJIT_32)));-}--#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));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif- sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), 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, type);-}--#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \- && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \- && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 reg,- sljit_s32 mem, sljit_sw memw)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(type);- SLJIT_UNUSED_ARG(reg);- SLJIT_UNUSED_ARG(mem);- SLJIT_UNUSED_ARG(memw);-- CHECK_ERROR();- CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));-- return SLJIT_ERR_UNSUPPORTED;-}--#endif--#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \- && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 freg,- sljit_s32 mem, sljit_sw memw)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(type);- SLJIT_UNUSED_ARG(freg);- SLJIT_UNUSED_ARG(mem);- SLJIT_UNUSED_ARG(memw);-- CHECK_ERROR();- CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));-- return SLJIT_ERR_UNSUPPORTED;-}--#endif--#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \- && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)--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));-- ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif- if (offset != 0)- 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);-}--#endif--#else /* SLJIT_CONFIG_UNSUPPORTED */--/* Empty function bodies for those machines, which are not (yet) supported. */--SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)-{- return "unsupported";-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data)-{- SLJIT_UNUSED_ARG(allocator_data);- SLJIT_UNUSED_ARG(exec_allocator_data);- SLJIT_UNREACHABLE();- return NULL;-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNREACHABLE();-}--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_UNREACHABLE();- return NULL;-}--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)-SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(verbose);- SLJIT_UNREACHABLE();-}-#endif--SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)-{- SLJIT_UNUSED_ARG(compiler);- 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, void *exec_allocator_data)-{- SLJIT_UNUSED_ARG(code);- SLJIT_UNUSED_ARG(exec_allocator_data);- SLJIT_UNREACHABLE();-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(options);- SLJIT_UNUSED_ARG(arg_types);- SLJIT_UNUSED_ARG(scratches);- SLJIT_UNUSED_ARG(saveds);- SLJIT_UNUSED_ARG(fscratches);- SLJIT_UNUSED_ARG(fsaveds);- SLJIT_UNUSED_ARG(local_size);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(options);- SLJIT_UNUSED_ARG(arg_types);- SLJIT_UNUSED_ARG(scratches);- SLJIT_UNUSED_ARG(saveds);- SLJIT_UNUSED_ARG(fscratches);- SLJIT_UNUSED_ARG(fsaveds);- SLJIT_UNUSED_ARG(local_size);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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);- SLJIT_UNUSED_ARG(dst);- SLJIT_UNUSED_ARG(dstw);- SLJIT_UNUSED_ARG(src);- SLJIT_UNUSED_ARG(srcw);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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);- SLJIT_UNUSED_ARG(dst);- SLJIT_UNUSED_ARG(dstw);- SLJIT_UNUSED_ARG(src1);- SLJIT_UNUSED_ARG(src1w);- SLJIT_UNUSED_ARG(src2);- SLJIT_UNUSED_ARG(src2w);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(op);- SLJIT_UNUSED_ARG(src1);- SLJIT_UNUSED_ARG(src1w);- SLJIT_UNUSED_ARG(src2);- SLJIT_UNUSED_ARG(src2w);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(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_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)-{- SLJIT_UNREACHABLE();- return reg;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(instruction);- SLJIT_UNUSED_ARG(size);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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);-}--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);- SLJIT_UNUSED_ARG(dst);- SLJIT_UNUSED_ARG(dstw);- SLJIT_UNUSED_ARG(src);- SLJIT_UNUSED_ARG(srcw);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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);- SLJIT_UNUSED_ARG(dst);- SLJIT_UNUSED_ARG(dstw);- SLJIT_UNUSED_ARG(src1);- SLJIT_UNUSED_ARG(src1w);- SLJIT_UNUSED_ARG(src2);- SLJIT_UNUSED_ARG(src2w);- 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_UNREACHABLE();- return NULL;-}--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_UNREACHABLE();- return NULL;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(type);- SLJIT_UNUSED_ARG(arg_types);- SLJIT_UNREACHABLE();- return NULL;-}--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);- SLJIT_UNUSED_ARG(src1);- SLJIT_UNUSED_ARG(src1w);- SLJIT_UNUSED_ARG(src2);- SLJIT_UNUSED_ARG(src2w);- SLJIT_UNREACHABLE();- return NULL;-}--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);- SLJIT_UNUSED_ARG(src1);- SLJIT_UNUSED_ARG(src1w);- SLJIT_UNUSED_ARG(src2);- SLJIT_UNUSED_ARG(src2w);- SLJIT_UNREACHABLE();- return NULL;-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)-{- SLJIT_UNUSED_ARG(jump);- SLJIT_UNUSED_ARG(label);- 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_UNREACHABLE();-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label)-{- SLJIT_UNUSED_ARG(put_label);- SLJIT_UNUSED_ARG(label);- SLJIT_UNREACHABLE();-}--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_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(type);- SLJIT_UNUSED_ARG(arg_types);- SLJIT_UNUSED_ARG(src);- SLJIT_UNUSED_ARG(srcw);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(type);- SLJIT_UNUSED_ARG(reg);- SLJIT_UNUSED_ARG(mem);- SLJIT_UNUSED_ARG(memw);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(type);- SLJIT_UNUSED_ARG(freg);- SLJIT_UNUSED_ARG(mem);- SLJIT_UNUSED_ARG(memw);- SLJIT_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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_UNREACHABLE();- return SLJIT_ERR_UNSUPPORTED;-}--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_UNREACHABLE();- return NULL;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(dst);- SLJIT_UNUSED_ARG(dstw);- return NULL;-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)-{- SLJIT_UNUSED_ARG(addr);- 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_sw executable_offset)-{- SLJIT_UNUSED_ARG(addr);- SLJIT_UNUSED_ARG(new_constant);- SLJIT_UNUSED_ARG(executable_offset);- SLJIT_UNREACHABLE();-}+/* All variable flags are even. */+#define VARIABLE_FLAG_MASK (0x3e << VARIABLE_FLAG_SHIFT)+#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT)++#define GET_OPCODE(op) \+ ((op) & ~(SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))++#define HAS_FLAGS(op) \+ ((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))++#define GET_ALL_FLAGS(op) \+ ((op) & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))++#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#define TYPE_CAST_NEEDED(op) \+ ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32)+#else /* !SLJIT_64BIT_ARCHITECTURE */+#define TYPE_CAST_NEEDED(op) \+ ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16)+#endif /* SLJIT_64BIT_ARCHITECTURE */++#define BUF_SIZE 4096++#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)+#define ABUF_SIZE 2048+#else+#define ABUF_SIZE 4096+#endif++/* Parameter parsing. */+#define REG_MASK 0x7f+#define OFFS_REG(reg) (((reg) >> 8) & REG_MASK)+#define OFFS_REG_MASK (REG_MASK << 8)+#define TO_OFFS_REG(reg) ((reg) << 8)+#define FAST_IS_REG(reg) ((reg) < REG_MASK)++/* Mask for argument types. */+#define SLJIT_ARG_MASK 0x7+#define SLJIT_ARG_FULL_MASK (SLJIT_ARG_MASK | SLJIT_ARG_TYPE_SCRATCH_REG)++/* Mask for register pairs. */+#define REG_PAIR_MASK 0x7f00+#define REG_PAIR_FIRST(reg) ((reg) & 0x7f)+#define REG_PAIR_SECOND(reg) ((reg) >> 8)++/* Mask for sljit_emit_enter. */+#define SLJIT_KEPT_SAVEDS_COUNT(options) ((options) & 0x3)++/* Getters for simd operations, which returns with log2(size). */+#define SLJIT_SIMD_GET_OPCODE(type) ((type) & 0xff)+#define SLJIT_SIMD_GET_REG_SIZE(type) (((type) >> 12) & 0x3f)+#define SLJIT_SIMD_GET_ELEM_SIZE(type) (((type) >> 18) & 0x3f)+#define SLJIT_SIMD_GET_ELEM2_SIZE(type) (((type) >> 24) & 0x3f)++#define SLJIT_SIMD_CHECK_REG(type) (((type) & 0x3f000) >= SLJIT_SIMD_REG_64 && ((type) & 0x3f000) <= SLJIT_SIMD_REG_512)+#define SLJIT_SIMD_TYPE_MASK(m) ((sljit_s32)0xff000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m)))+#define SLJIT_SIMD_TYPE_MASK2(m) ((sljit_s32)0xc0000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m)))++/* Jump flags. */+#define JUMP_ADDR 0x1+#define JUMP_MOV_ADDR 0x2+/* SLJIT_REWRITABLE_JUMP is 0x1000. */++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+# define PATCH_MB 0x04+# define PATCH_MW 0x08+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+# define PATCH_MD 0x10+# define MOV_ADDR_HI 0x20+# define JUMP_MAX_SIZE ((sljit_uw)(10 + 3))+# define CJUMP_MAX_SIZE ((sljit_uw)(2 + 10 + 3))+#else /* !SLJIT_CONFIG_X86_64 */+# define JUMP_MAX_SIZE ((sljit_uw)5)+# define CJUMP_MAX_SIZE ((sljit_uw)6)+#endif /* SLJIT_CONFIG_X86_64 */+# define TYPE_SHIFT 13+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+/* Bits 7..12 is for debug jump size, SLJIT_REWRITABLE_JUMP is 0x1000 */+# define JUMP_SIZE_SHIFT 7+#endif /* SLJIT_DEBUG */+#endif /* SLJIT_CONFIG_X86 */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+# define IS_BL 0x04+# define PATCH_B 0x08+#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V7 */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+# define CPOOL_SIZE 512+#endif /* SLJIT_CONFIG_ARM_V6 */++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+# define JUMP_SIZE_SHIFT 26+# define JUMP_MAX_SIZE ((sljit_uw)3)+#endif /* SLJIT_CONFIG_ARM_V7 */++#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+# define IS_COND 0x04+# define IS_BL 0x08+ /* conditional + imm8 */+# define PATCH_TYPE1 0x10+ /* conditional + imm20 */+# define PATCH_TYPE2 0x20+ /* imm11 */+# define PATCH_TYPE3 0x30+ /* imm24 */+# define PATCH_TYPE4 0x40+ /* BL + imm24 */+# define PATCH_TYPE5 0x50+ /* addwi/subwi */+# define PATCH_TYPE6 0x60+ /* 0xf00 cc code for branches */+# define JUMP_SIZE_SHIFT 26+# define JUMP_MAX_SIZE ((sljit_uw)5)+#endif /* SLJIT_CONFIG_ARM_THUMB2 */++#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+# define IS_COND 0x004+# define IS_CBZ 0x008+# define IS_BL 0x010+# define PATCH_COND 0x020+# define PATCH_B 0x040+# define PATCH_B32 0x080+# define PATCH_ABS48 0x100+# define PATCH_ABS64 0x200+# define JUMP_SIZE_SHIFT 58+# define JUMP_MAX_SIZE ((sljit_uw)5)+#endif /* SLJIT_CONFIG_ARM_64 */++#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+# define IS_COND 0x004+# define IS_CALL 0x008+# define PATCH_B 0x010+# define PATCH_ABS_B 0x020+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+# define PATCH_ABS32 0x040+# define PATCH_ABS48 0x080+# define JUMP_SIZE_SHIFT 58+# define JUMP_MAX_SIZE ((sljit_uw)7)+#else /* !SLJIT_CONFIG_PPC_64 */+# define JUMP_SIZE_SHIFT 26+# define JUMP_MAX_SIZE ((sljit_uw)4)+#endif /* SLJIT_CONFIG_PPC_64 */+#endif /* SLJIT_CONFIG_PPC */++#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+# define IS_MOVABLE 0x004+# define IS_JAL 0x008+# define IS_CALL 0x010+# define IS_BIT26_COND 0x020+# define IS_BIT16_COND 0x040+# define IS_BIT23_COND 0x080++# define IS_COND (IS_BIT26_COND | IS_BIT16_COND | IS_BIT23_COND)++# define PATCH_B 0x100+# define PATCH_J 0x200++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+# define PATCH_ABS32 0x400+# define PATCH_ABS48 0x800+#endif /* SLJIT_CONFIG_MIPS_64 */++ /* instruction types */+# define MOVABLE_INS 0+ /* 1 - 31 last destination register */+ /* no destination (i.e: store) */+# define UNMOVABLE_INS 32+ /* FPU status register */+# define FCSR_FCC 33+#endif /* SLJIT_CONFIG_MIPS */++#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)+# define IS_COND 0x004+# define IS_CALL 0x008++# define PATCH_B 0x010+# define PATCH_J 0x020++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+# define PATCH_REL32 0x040+# define PATCH_ABS32 0x080+# define PATCH_ABS44 0x100+# define PATCH_ABS52 0x200+# define JUMP_SIZE_SHIFT 58+# define JUMP_MAX_SIZE ((sljit_uw)6)+#else /* !SLJIT_CONFIG_RISCV_64 */+# define JUMP_SIZE_SHIFT 26+# define JUMP_MAX_SIZE ((sljit_uw)2)+#endif /* SLJIT_CONFIG_RISCV_64 */+#endif /* SLJIT_CONFIG_RISCV */++#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)+# define IS_COND 0x004+# define IS_CALL 0x008++# define PATCH_B 0x010+# define PATCH_J 0x020++# define PATCH_REL32 0x040+# define PATCH_ABS32 0x080+# define PATCH_ABS52 0x100+# define JUMP_SIZE_SHIFT 58+# define JUMP_MAX_SIZE ((sljit_uw)4)++#endif /* SLJIT_CONFIG_LOONGARCH */+/* Stack management. */++#define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \+ (((scratches < SLJIT_NUMBER_OF_SCRATCH_REGISTERS ? 0 : (scratches - SLJIT_NUMBER_OF_SCRATCH_REGISTERS)) + \+ (saveds) + (sljit_s32)(extra)) * (sljit_s32)sizeof(sljit_sw))++#define GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, type) \+ (((fscratches < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS ? 0 : (fscratches - SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)) + \+ (fsaveds)) * SSIZE_OF(type))++#define ADJUST_LOCAL_OFFSET(p, i) \+ if ((p) == (SLJIT_MEM1(SLJIT_SP))) \+ (i) += SLJIT_LOCALS_OFFSET;++#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */++/* Utils can still be used even if SLJIT_CONFIG_UNSUPPORTED is set. */+#include "sljitUtils.c"++#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+#define SLJIT_CODE_TO_PTR(code) ((void*)((sljit_up)(code) & ~(sljit_up)0x1))+#elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+#define SLJIT_CODE_TO_PTR(code) ((void*)(*(sljit_up*)code))+#else /* !SLJIT_CONFIG_ARM_THUMB2 && !SLJIT_INDIRECT_CALL */+#define SLJIT_CODE_TO_PTR(code) ((void*)(code))+#endif /* SLJIT_CONFIG_ARM_THUMB2 || SLJIT_INDIRECT_CALL */++#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)++#if defined(__NetBSD__)+#include "allocator_src/sljitProtExecAllocatorNetBSD.c"+#else+#include "allocator_src/sljitProtExecAllocatorPosix.c"+#endif++#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)++#if defined(_WIN32)+#include "allocator_src/sljitWXExecAllocatorWindows.c"+#else+#include "allocator_src/sljitWXExecAllocatorPosix.c"+#endif++#else++#if defined(_WIN32)+#include "allocator_src/sljitExecAllocatorWindows.c"+#elif defined(__APPLE__)+#include "allocator_src/sljitExecAllocatorApple.c"+#elif defined(__FreeBSD__)+#include "allocator_src/sljitExecAllocatorFreeBSD.c"+#else+#include "allocator_src/sljitExecAllocatorPosix.c"+#endif++#endif++#else /* !SLJIT_EXECUTABLE_ALLOCATOR */++#ifndef SLJIT_UPDATE_WX_FLAGS+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)+#endif++#endif /* SLJIT_EXECUTABLE_ALLOCATOR */++#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)++/* Returns with error when an invalid argument is passed. */++#define CHECK_ARGUMENT(x) \+ do { \+ if (SLJIT_UNLIKELY(!(x))) \+ return 1; \+ } while (0)++#define CHECK_RETURN_TYPE sljit_s32+#define CHECK_RETURN_OK return 0++#define CHECK(x) \+ do { \+ if (SLJIT_UNLIKELY(x)) { \+ compiler->error = SLJIT_ERR_BAD_ARGUMENT; \+ return SLJIT_ERR_BAD_ARGUMENT; \+ } \+ } while (0)++#define CHECK_PTR(x) \+ do { \+ if (SLJIT_UNLIKELY(x)) { \+ compiler->error = SLJIT_ERR_BAD_ARGUMENT; \+ return NULL; \+ } \+ } while (0)++#define CHECK_REG_INDEX(x) \+ do { \+ if (SLJIT_UNLIKELY(x)) { \+ return -2; \+ } \+ } while (0)++#elif (defined SLJIT_DEBUG && SLJIT_DEBUG)++/* Assertion failure occures if an invalid argument is passed. */+#undef SLJIT_ARGUMENT_CHECKS+#define SLJIT_ARGUMENT_CHECKS 1++#define CHECK_ARGUMENT(x) SLJIT_ASSERT(x)+#define CHECK_RETURN_TYPE void+#define CHECK_RETURN_OK return+#define CHECK(x) x+#define CHECK_PTR(x) x+#define CHECK_REG_INDEX(x) x++#elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE)++/* Arguments are not checked. */+#define CHECK_RETURN_TYPE void+#define CHECK_RETURN_OK return+#define CHECK(x) x+#define CHECK_PTR(x) x+#define CHECK_REG_INDEX(x) x++#else++/* Arguments are not checked. */+#define CHECK(x)+#define CHECK_PTR(x)+#define CHECK_REG_INDEX(x)++#endif /* SLJIT_ARGUMENT_CHECKS */++/* --------------------------------------------------------------------- */+/* Public functions */+/* --------------------------------------------------------------------- */++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+#define SLJIT_NEEDS_COMPILER_INIT 1+static sljit_s32 compiler_initialized = 0;+/* A thread safe initialization. */+static void init_compiler(void);+#endif++SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data)+{+ struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler), allocator_data);+ if (!compiler)+ return NULL;+ SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler));++ SLJIT_COMPILE_ASSERT(+ 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_up) == 4 || sizeof(sljit_up) == 8)+ && sizeof(sljit_up) <= sizeof(sljit_sw)+ && sizeof(sljit_up) == sizeof(sljit_sp)+ && (sizeof(sljit_sw) == 4 || sizeof(sljit_sw) == 8)+ && (sizeof(sljit_uw) == sizeof(sljit_sw)),+ invalid_integer_types);+ SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_32,+ rewritable_jump_and_single_op_must_not_be_the_same);+ SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_F_EQUAL & 0x1) && !(SLJIT_JUMP & 0x1),+ conditional_flags_must_be_even_numbers);++ /* Only the non-zero members must be set. */+ compiler->error = SLJIT_SUCCESS;++ compiler->allocator_data = allocator_data;+ compiler->buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);+ compiler->abuf = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, allocator_data);++ if (!compiler->buf || !compiler->abuf) {+ if (compiler->buf)+ SLJIT_FREE(compiler->buf, allocator_data);+ if (compiler->abuf)+ SLJIT_FREE(compiler->abuf, allocator_data);+ SLJIT_FREE(compiler, allocator_data);+ return NULL;+ }++ compiler->buf->next = NULL;+ compiler->buf->used_size = 0;+ compiler->abuf->next = NULL;+ compiler->abuf->used_size = 0;++ compiler->scratches = -1;+ compiler->saveds = -1;+ compiler->fscratches = -1;+ compiler->fsaveds = -1;+ compiler->local_size = -1;++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ compiler->args_size = -1;+#endif /* SLJIT_CONFIG_X86_32 */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ compiler->cpool = (sljit_uw*)SLJIT_MALLOC(CPOOL_SIZE * sizeof(sljit_uw)+ + 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_u8*)(compiler->cpool + CPOOL_SIZE);+ compiler->cpool_diff = 0xffffffff;+#endif /* SLJIT_CONFIG_ARM_V6 */++#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+ compiler->delay_slot = UNMOVABLE_INS;+#endif /* SLJIT_CONFIG_MIPS */++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)+ compiler->last_flags = 0;+ compiler->last_return = -1;+ compiler->logical_local_size = 0;+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */++#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT)+ if (!compiler_initialized) {+ init_compiler();+ compiler_initialized = 1;+ }+#endif++ return compiler;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ struct sljit_memory_fragment *curr;+ void *allocator_data = compiler->allocator_data;+ SLJIT_UNUSED_ARG(allocator_data);++ buf = compiler->buf;+ while (buf) {+ curr = buf;+ buf = buf->next;+ SLJIT_FREE(curr, allocator_data);+ }++ buf = compiler->abuf;+ while (buf) {+ curr = buf;+ buf = buf->next;+ SLJIT_FREE(curr, allocator_data);+ }++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ SLJIT_FREE(compiler->cpool, allocator_data);+#endif+ SLJIT_FREE(compiler, allocator_data);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)+{+ if (compiler->error == SLJIT_SUCCESS)+ compiler->error = SLJIT_ERR_ALLOC_FAILED;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)+{+ SLJIT_UNUSED_ARG(exec_allocator_data);++ SLJIT_FREE_EXEC(SLJIT_CODE_TO_PTR(code), exec_allocator_data);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)+{+ if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) {+ jump->flags &= (sljit_uw)~JUMP_ADDR;+ jump->u.label = label;+ }+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)+{+ if (SLJIT_LIKELY(!!jump)) {+ jump->flags |= JUMP_ADDR;+ jump->u.target = target;+ }+}++#define SLJIT_CURRENT_FLAGS_ALL \+ (SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE)++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_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)+ compiler->status_flags_state = current_flags;+#endif++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->last_flags = 0;+ if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_ALL)) == 0) {+ compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_32 | SLJIT_SET_Z));+ }+#endif+}++/* --------------------------------------------------------------------- */+/* Private functions */+/* --------------------------------------------------------------------- */++static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size)+{+ sljit_u8 *ret;+ struct sljit_memory_fragment *new_frag;++ SLJIT_ASSERT(size <= 256);+ if (compiler->buf->used_size + size <= (BUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {+ ret = compiler->buf->memory + compiler->buf->used_size;+ compiler->buf->used_size += size;+ return ret;+ }+ new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, compiler->allocator_data);+ PTR_FAIL_IF_NULL(new_frag);+ new_frag->next = compiler->buf;+ compiler->buf = new_frag;+ new_frag->used_size = size;+ return new_frag->memory;+}++static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size)+{+ sljit_u8 *ret;+ struct sljit_memory_fragment *new_frag;++ SLJIT_ASSERT(size <= 256);+ if (compiler->abuf->used_size + size <= (ABUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {+ ret = compiler->abuf->memory + compiler->abuf->used_size;+ compiler->abuf->used_size += size;+ return ret;+ }+ new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, compiler->allocator_data);+ PTR_FAIL_IF_NULL(new_frag);+ new_frag->next = compiler->abuf;+ compiler->abuf = new_frag;+ new_frag->used_size = size;+ return new_frag->memory;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)+{+ CHECK_ERROR_PTR();++#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+ if (size <= 0 || size > 128)+ return NULL;+ size = (size + 7) & ~7;+#else+ if (size <= 0 || size > 64)+ return NULL;+ size = (size + 3) & ~3;+#endif+ return ensure_abuf(compiler, (sljit_uw)size);+}++static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf = compiler->buf;+ struct sljit_memory_fragment *prev = NULL;+ struct sljit_memory_fragment *tmp;++ do {+ tmp = buf->next;+ buf->next = prev;+ prev = buf;+ buf = tmp;+ } while (buf != NULL);++ compiler->buf = prev;+}++static SLJIT_INLINE void* allocate_executable_memory(sljit_uw size, sljit_s32 options,+ void *exec_allocator_data, sljit_sw *executable_offset)+{+ void *code;+ struct sljit_generate_code_buffer *buffer;++ if (SLJIT_LIKELY(!(options & SLJIT_GENERATE_CODE_BUFFER))) {+ code = SLJIT_MALLOC_EXEC(size, exec_allocator_data);+ *executable_offset = SLJIT_EXEC_OFFSET(code);+ return code;+ }++ buffer = (struct sljit_generate_code_buffer*)exec_allocator_data;++ if (size <= buffer->size) {+ *executable_offset = buffer->executable_offset;+ return buffer->buffer;+ }++ return NULL;+}++#define SLJIT_MAX_ADDRESS ~(sljit_uw)0++#define SLJIT_GET_NEXT_SIZE(ptr) (ptr != NULL) ? ((ptr)->size) : SLJIT_MAX_ADDRESS+#define SLJIT_GET_NEXT_ADDRESS(ptr) (ptr != NULL) ? ((ptr)->addr) : SLJIT_MAX_ADDRESS++#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)++#define SLJIT_NEXT_DEFINE_TYPES \+ sljit_uw next_label_size; \+ sljit_uw next_jump_addr; \+ sljit_uw next_const_addr; \+ sljit_uw next_min_addr++#define SLJIT_NEXT_INIT_TYPES() \+ next_label_size = SLJIT_GET_NEXT_SIZE(label); \+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); \+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);++#define SLJIT_GET_NEXT_MIN() \+ next_min_addr = sljit_get_next_min(next_label_size, next_jump_addr, next_const_addr);++static SLJIT_INLINE sljit_uw sljit_get_next_min(sljit_uw next_label_size,+ sljit_uw next_jump_addr, sljit_uw next_const_addr)+{+ sljit_uw result = next_jump_addr;++ SLJIT_ASSERT(result == SLJIT_MAX_ADDRESS || result != next_const_addr);++ if (next_const_addr < result)+ result = next_const_addr;++ if (next_label_size < result)+ result = next_label_size;++ return result;+}++#endif /* !SLJIT_CONFIG_X86 */++static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ SLJIT_UNUSED_ARG(args);+ SLJIT_UNUSED_ARG(local_size);++ compiler->options = options;+ compiler->scratches = scratches;+ compiler->saveds = saveds;+ compiler->fscratches = fscratches;+ compiler->fsaveds = fsaveds;+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->last_return = args & SLJIT_ARG_MASK;+ compiler->logical_local_size = local_size;+#endif+}++static SLJIT_INLINE void set_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(args);+ SLJIT_UNUSED_ARG(local_size);++ compiler->options = options;+ compiler->scratches = scratches;+ compiler->saveds = saveds;+ compiler->fscratches = fscratches;+ compiler->fsaveds = fsaveds;+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->last_return = args & SLJIT_ARG_MASK;+ compiler->logical_local_size = local_size;+#endif+}++static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler)+{+ label->next = NULL;+ label->u.index = compiler->label_count++;+ label->size = compiler->size;+ if (compiler->last_label != NULL)+ compiler->last_label->next = label;+ else+ compiler->labels = label;+ compiler->last_label = label;+}++static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_u32 flags)+{+ jump->next = NULL;+ jump->flags = flags;+ jump->u.label = NULL;+ if (compiler->last_jump != NULL)+ compiler->last_jump->next = jump;+ else+ compiler->jumps = jump;+ compiler->last_jump = jump;+}++static SLJIT_INLINE void set_mov_addr(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_uw offset)+{+ jump->next = NULL;+ jump->addr = compiler->size - offset;+ jump->flags = JUMP_MOV_ADDR;+ jump->u.label = NULL;+ if (compiler->last_jump != NULL)+ compiler->last_jump->next = jump;+ else+ compiler->jumps = jump;+ compiler->last_jump = jump;+}++static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_compiler *compiler)+{+ const_->next = NULL;+ const_->addr = compiler->size;+ if (compiler->last_const != NULL)+ compiler->last_const->next = const_;+ else+ compiler->consts = const_;+ compiler->last_const = const_;+}++#define ADDRESSING_DEPENDS_ON(exp, reg) \+ (((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)++static sljit_s32 function_check_arguments(sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches)+{+ sljit_s32 word_arg_count, scratch_arg_end, saved_arg_count, float_arg_count, curr_type;++ curr_type = (arg_types & SLJIT_ARG_FULL_MASK);++ if (curr_type >= SLJIT_ARG_TYPE_F64) {+ if (curr_type > SLJIT_ARG_TYPE_F32 || fscratches == 0)+ return 0;+ } else if (curr_type >= SLJIT_ARG_TYPE_W) {+ if (scratches == 0)+ return 0;+ }++ arg_types >>= SLJIT_ARG_SHIFT;++ word_arg_count = 0;+ scratch_arg_end = 0;+ saved_arg_count = 0;+ float_arg_count = 0;+ while (arg_types != 0) {+ if (word_arg_count + float_arg_count >= 4)+ return 0;++ curr_type = (arg_types & SLJIT_ARG_MASK);++ if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {+ if (saveds == -1 || curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_P)+ return 0;++ word_arg_count++;+ scratch_arg_end = word_arg_count;+ } else {+ if (curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_F32)+ return 0;++ if (curr_type < SLJIT_ARG_TYPE_F64) {+ word_arg_count++;+ saved_arg_count++;+ } else+ float_arg_count++;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ if (saveds == -1)+ return (word_arg_count <= scratches && float_arg_count <= fscratches);++ return (saved_arg_count <= saveds && scratch_arg_end <= scratches && float_arg_count <= fscratches);+}++#define FUNCTION_CHECK_IS_REG(r) \+ (((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \+ || ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0) \+ || ((r) >= SLJIT_TMP_REGISTER_BASE && (r) < (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS)))++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+#define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8)+#else+#define CHECK_IF_VIRTUAL_REGISTER(p) 0+#endif++static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (compiler->scratches == -1)+ return 0;++ if (!(p & SLJIT_MEM))+ return 0;++ if (p == SLJIT_MEM1(SLJIT_SP))+ return (i >= 0 && i < compiler->logical_local_size);++ if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK)))+ return 0;++ if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK))+ return 0;++ if (p & OFFS_REG_MASK) {+ if (!(p & REG_MASK))+ return 0;++ if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p))))+ return 0;++ if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p)))+ return 0;++ if ((i & ~0x3) != 0)+ return 0;+ }++ return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0;+}++#define FUNCTION_CHECK_SRC_MEM(p, i) \+ CHECK_ARGUMENT(function_check_src_mem(compiler, p, i));++static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (compiler->scratches == -1)+ return 0;++ if (FUNCTION_CHECK_IS_REG(p))+ return (i == 0);++ if (p == SLJIT_IMM)+ return 1;++ return function_check_src_mem(compiler, p, i);+}++#define FUNCTION_CHECK_SRC(p, i) \+ CHECK_ARGUMENT(function_check_src(compiler, p, i));++static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (compiler->scratches == -1)+ return 0;++ if (FUNCTION_CHECK_IS_REG(p))+ return (i == 0);++ return function_check_src_mem(compiler, p, i);+}++#define FUNCTION_CHECK_DST(p, i) \+ CHECK_ARGUMENT(function_check_dst(compiler, p, i));++#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)++#define FUNCTION_CHECK_IS_FREG(fr, is_32) \+ function_check_is_freg(compiler, (fr), (is_32))++static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32);++#define FUNCTION_FCHECK(p, i, is_32) \+ CHECK_ARGUMENT(function_fcheck(compiler, (p), (i), (is_32)));++static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 is_32)+{+ if (compiler->scratches == -1)+ return 0;++ if (FUNCTION_CHECK_IS_FREG(p, is_32))+ return (i == 0);++ return function_check_src_mem(compiler, p, i);+}++#else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */+#define FUNCTION_CHECK_IS_FREG(fr, is_32) \+ function_check_is_freg(compiler, (fr))++static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr)+{+ if (compiler->scratches == -1)+ return 0;++ return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches))+ || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0)+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));+}++#define FUNCTION_FCHECK(p, i, is_32) \+ CHECK_ARGUMENT(function_fcheck(compiler, (p), (i)));++static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (compiler->scratches == -1)+ return 0;++ if ((p >= SLJIT_FR0 && p < (SLJIT_FR0 + compiler->fscratches))+ || (p > (SLJIT_FS0 - compiler->fsaveds) && p <= SLJIT_FS0)+ || (p >= SLJIT_TMP_FREGISTER_BASE && p < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)))+ return (i == 0);++ return function_check_src_mem(compiler, p, i);+}++#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */++#endif /* SLJIT_ARGUMENT_CHECKS */++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)++SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)+{+ compiler->verbose = verbose;+}++#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#ifdef _WIN64+#ifdef __GNUC__+# define SLJIT_PRINT_D "ll"+#else+# define SLJIT_PRINT_D "I64"+#endif+#else+# define SLJIT_PRINT_D "l"+#endif+#else+# define SLJIT_PRINT_D ""+#endif++static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r)+{+ if (r < (SLJIT_R0 + compiler->scratches))+ fprintf(compiler->verbose, "r%d", r - SLJIT_R0);+ else if (r < SLJIT_SP)+ fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r);+ else if (r == SLJIT_SP)+ fprintf(compiler->verbose, "sp");+ else+ fprintf(compiler->verbose, "t%d", r - SLJIT_TMP_REGISTER_BASE);+}++static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r)+{+#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (r >= SLJIT_F64_SECOND(SLJIT_FR0)) {+ fprintf(compiler->verbose, "^");+ r -= SLJIT_F64_SECOND(0);+ }+#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */++ if (r < (SLJIT_FR0 + compiler->fscratches))+ fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0);+ else if (r < SLJIT_TMP_FREGISTER_BASE)+ fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r);+ else+ fprintf(compiler->verbose, "ft%d", r - SLJIT_TMP_FREGISTER_BASE);+}++static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if ((p) == SLJIT_IMM)+ fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i));+ else if ((p) & SLJIT_MEM) {+ if ((p) & REG_MASK) {+ fputc('[', compiler->verbose);+ sljit_verbose_reg(compiler, (p) & REG_MASK);+ if ((p) & OFFS_REG_MASK) {+ fprintf(compiler->verbose, " + ");+ sljit_verbose_reg(compiler, OFFS_REG(p));+ if (i)+ fprintf(compiler->verbose, " * %d", 1 << (i));+ }+ else if (i)+ fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));+ fputc(']', compiler->verbose);+ }+ else+ fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));+ } else+ sljit_verbose_reg(compiler, p);+}++static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if ((p) & SLJIT_MEM) {+ if ((p) & REG_MASK) {+ fputc('[', compiler->verbose);+ sljit_verbose_reg(compiler, (p) & REG_MASK);+ if ((p) & OFFS_REG_MASK) {+ fprintf(compiler->verbose, " + ");+ sljit_verbose_reg(compiler, OFFS_REG(p));+ if (i)+ fprintf(compiler->verbose, "%d", 1 << (i));+ }+ else if (i)+ fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));+ fputc(']', compiler->verbose);+ }+ else+ fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));+ }+ else+ sljit_verbose_freg(compiler, p);+}++static const char* op0_names[] = {+ "breakpoint", "nop", "lmul.uw", "lmul.sw",+ "divmod.u", "divmod.s", "div.u", "div.s",+ "endbr", "skip_frames_before_return"+};++static const char* op1_names[] = {+ "mov", "mov", "mov", "mov",+ "mov", "mov", "mov", "mov",+ "mov", "clz", "ctz", "rev",+ "rev", "rev", "rev", "rev"+};++static const char* op1_types[] = {+ "", ".u8", ".s8", ".u16",+ ".s16", ".u32", ".s32", "32",+ ".p", "", "", "",+ ".u16", ".s16", ".u32", ".s32"+};++static const char* op2_names[] = {+ "add", "addc", "sub", "subc",+ "mul", "and", "or", "xor",+ "shl", "mshl", "lshr", "mlshr",+ "ashr", "mashr", "rotl", "rotr"+};++static const char* op2r_names[] = {+ "muladd"+};++static const char* op_src_dst_names[] = {+ "fast_return", "skip_frames_before_fast_return",+ "prefetch_l1", "prefetch_l2",+ "prefetch_l3", "prefetch_once",+ "fast_enter", "get_return_address"+};++static const char* fop1_names[] = {+ "mov", "conv", "conv", "conv",+ "conv", "conv", "conv", "conv",+ "cmp", "neg", "abs",+};++static const char* fop1_conv_types[] = {+ "sw", "s32", "sw", "s32",+ "uw", "u32"+};++static const char* fop2_names[] = {+ "add", "sub", "mul", "div"+};++static const char* fop2r_names[] = {+ "copysign"+};++static const char* simd_op2_names[] = {+ "and", "or", "xor"+};++static const char* jump_names[] = {+ "equal", "not_equal",+ "less", "greater_equal",+ "greater", "less_equal",+ "sig_less", "sig_greater_equal",+ "sig_greater", "sig_less_equal",+ "overflow", "not_overflow",+ "carry", "not_carry",+ "atomic_stored", "atomic_not_stored",+ "f_equal", "f_not_equal",+ "f_less", "f_greater_equal",+ "f_greater", "f_less_equal",+ "unordered", "ordered",+ "ordered_equal", "unordered_or_not_equal",+ "ordered_less", "unordered_or_greater_equal",+ "ordered_greater", "unordered_or_less_equal",+ "unordered_or_equal", "ordered_not_equal",+ "unordered_or_less", "ordered_greater_equal",+ "unordered_or_greater", "ordered_less_equal",+ "jump", "fast_call",+ "call", "call_reg_arg"+};++static const char* call_arg_names[] = {+ "void", "w", "32", "p", "f64", "f32"+};++#endif /* SLJIT_VERBOSE */++/* --------------------------------------------------------------------- */+/* Arch dependent */+/* --------------------------------------------------------------------- */++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)++#define SLJIT_SKIP_CHECKS(compiler) (compiler)->skip_checks = 1++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ struct sljit_jump *jump;+#endif++ SLJIT_UNUSED_ARG(compiler);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(compiler->size > 0);+ jump = compiler->jumps;+ while (jump) {+ /* All jumps have target. */+ CHECK_ARGUMENT((jump->flags & JUMP_ADDR) || jump->u.label != NULL);+ jump = jump->next;+ }+#endif+ CHECK_RETURN_OK;+}++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+#define SLJIT_ENTER_CPU_SPECIFIC_OPTIONS (SLJIT_ENTER_USE_VEX)+#else /* !SLJIT_CONFIG_X86 */+#define SLJIT_ENTER_CPU_SPECIFIC_OPTIONS (0)+#endif /* !SLJIT_CONFIG_X86 */++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ SLJIT_UNUSED_ARG(compiler);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ if (options & SLJIT_ENTER_REG_ARG) {+ CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG | SLJIT_ENTER_CPU_SPECIFIC_OPTIONS)));+ } else {+ CHECK_ARGUMENT((options & ~SLJIT_ENTER_CPU_SPECIFIC_OPTIONS) == 0);+ }+ CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);+ CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);+ CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);+ CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) <= SLJIT_ARG_TYPE_F32);+ CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches));++ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " enter ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);++ arg_types >>= SLJIT_ARG_SHIFT;+ if (arg_types) {+ fprintf(compiler->verbose, "], args[");+ do {+ fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],+ (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");+ arg_types >>= SLJIT_ARG_SHIFT;+ if (arg_types)+ fprintf(compiler->verbose, ",");+ } while (arg_types);+ }++ fprintf(compiler->verbose, "],");++ if (options & SLJIT_ENTER_REG_ARG) {+ if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)+ fprintf(compiler->verbose, " opt:reg_arg(%d),", SLJIT_KEPT_SAVEDS_COUNT(options));+ else+ fprintf(compiler->verbose, " opt:reg_arg,");+ }++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+ if (options & SLJIT_ENTER_USE_VEX) {+ fprintf(compiler->verbose, " opt:use_vex,");+ }+#endif /* !SLJIT_CONFIG_X86 */++ fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",+ scratches, saveds, fscratches, fsaveds, local_size);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ SLJIT_UNUSED_ARG(compiler);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ if (options & SLJIT_ENTER_REG_ARG) {+ CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG | SLJIT_ENTER_CPU_SPECIFIC_OPTIONS)));+ } else {+ CHECK_ARGUMENT((options & ~SLJIT_ENTER_CPU_SPECIFIC_OPTIONS) == 0);+ }+ CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);+ CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);+ CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);+ CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);+ CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches));++ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " set_context ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);++ arg_types >>= SLJIT_ARG_SHIFT;+ if (arg_types) {+ fprintf(compiler->verbose, "], args[");+ do {+ fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],+ (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");+ arg_types >>= SLJIT_ARG_SHIFT;+ if (arg_types)+ fprintf(compiler->verbose, ",");+ } while (arg_types);+ }++ fprintf(compiler->verbose, "],");++ if (options & SLJIT_ENTER_REG_ARG) {+ if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)+ fprintf(compiler->verbose, " opt:reg_arg(%d),", SLJIT_KEPT_SAVEDS_COUNT(options));+ else+ fprintf(compiler->verbose, " opt:reg_arg,");+ }++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+ if (options & SLJIT_ENTER_USE_VEX) {+ fprintf(compiler->verbose, " opt:use_vex,");+ }+#endif /* !SLJIT_CONFIG_X86 */++ fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",+ scratches, saveds, fscratches, fsaveds, local_size);+ }+#endif+ CHECK_RETURN_OK;+}++#undef SLJIT_ENTER_CPU_SPECIFIC_OPTIONS++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_void(struct sljit_compiler *compiler)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(compiler->last_return == SLJIT_ARG_TYPE_RET_VOID);+#endif++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " return_void\n");+ }+#endif+ CHECK_RETURN_OK;+}++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);++ switch (compiler->last_return) {+ case SLJIT_ARG_TYPE_W:+ CHECK_ARGUMENT(op >= SLJIT_MOV && op <= SLJIT_MOV_S32);+ break;+ case SLJIT_ARG_TYPE_32:+ CHECK_ARGUMENT(op == SLJIT_MOV32 || (op >= SLJIT_MOV32_U8 && op <= SLJIT_MOV32_S16));+ break;+ case SLJIT_ARG_TYPE_P:+ CHECK_ARGUMENT(op == SLJIT_MOV_P);+ break;+ case SLJIT_ARG_TYPE_F64:+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(op == SLJIT_MOV_F64);+ break;+ case SLJIT_ARG_TYPE_F32:+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(op == SLJIT_MOV_F32);+ break;+ default:+ /* Context not initialized, void, etc. */+ CHECK_ARGUMENT(0);+ break;+ }++ if (GET_OPCODE(op) < SLJIT_MOV_F64) {+ FUNCTION_CHECK_SRC(src, srcw);+ } else {+ FUNCTION_FCHECK(src, srcw, op & SLJIT_32);+ }+ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (GET_OPCODE(op) < SLJIT_MOV_F64) {+ fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32",+ op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);+ sljit_verbose_param(compiler, src, srcw);+ } else {+ fprintf(compiler->verbose, " return%s ", !(op & SLJIT_32) ? ".f64" : ".f32");+ sljit_verbose_fparam(compiler, src, srcw);+ }+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ FUNCTION_CHECK_SRC(src, srcw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " return_to ");+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++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_LMUL_SW)+ || ((op & ~SLJIT_32) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_32) <= SLJIT_DIV_SW)+ || (op >= SLJIT_ENDBR && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN));+ CHECK_ARGUMENT(GET_OPCODE(op) < SLJIT_LMUL_UW || GET_OPCODE(op) >= SLJIT_ENDBR || compiler->scratches >= 2);+ if ((GET_OPCODE(op) >= SLJIT_LMUL_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN)+ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose))+ {+ fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);+ if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) {+ fprintf(compiler->verbose, (op & SLJIT_32) ? "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_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_REV_S32);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ case SLJIT_MOV_P:+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ /* Nothing allowed */+ CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ break;+ default:+ /* Only SLJIT_32 is allowed. */+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ break;+ }++ FUNCTION_CHECK_DST(dst, dstw);+ FUNCTION_CHECK_SRC(src, srcw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE],+ !(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);++ sljit_verbose_param(compiler, dst, dstw);+ 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_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 mem_reg)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC));+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOV_P);+ CHECK_ARGUMENT(GET_OPCODE(op) != SLJIT_MOV_S8 && GET_OPCODE(op) != SLJIT_MOV_S16 && GET_OPCODE(op) != SLJIT_MOV_S32);++ /* All arguments must be valid registers. */+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg));++ if (op == SLJIT_MOV32_U8 || op == SLJIT_MOV32_U16) {+ /* Only SLJIT_32 is allowed. */+ CHECK_ARGUMENT(!(op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z)));+ } else {+ /* Nothing allowed. */+ CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ }++ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " atomic_load%s%s ", !(op & SLJIT_32) ? "" : "32",+ op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);+ sljit_verbose_reg(compiler, dst_reg);+ fprintf(compiler->verbose, ", [");+ sljit_verbose_reg(compiler, mem_reg);+ fprintf(compiler->verbose, "]\n");+ }+#endif /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src_reg,+ sljit_s32 mem_reg,+ sljit_s32 temp_reg)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC));+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOV_P);+ CHECK_ARGUMENT(GET_OPCODE(op) != SLJIT_MOV_S8 && GET_OPCODE(op) != SLJIT_MOV_S16 && GET_OPCODE(op) != SLJIT_MOV_S32);++ /* All arguments must be valid registers. */+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src_reg));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(temp_reg) && src_reg != temp_reg);++ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_ATOMIC_STORED);++ if (GET_OPCODE(op) == SLJIT_MOV_U8 || GET_OPCODE(op) == SLJIT_MOV_U16) {+ /* Only SLJIT_32, SLJIT_ATOMIC_STORED are allowed. */+ CHECK_ARGUMENT(!(op & SLJIT_SET_Z));+ } else {+ /* Only SLJIT_ATOMIC_STORED is allowed. */+ CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z)));+ }++ compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32);+#endif /* SLJIT_ARGUMENT_CHECKS */+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " atomic_store%s%s%s ", !(op & SLJIT_32) ? "" : "32",+ op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & VARIABLE_FLAG_MASK) ? "" : ".stored");+ sljit_verbose_reg(compiler, src_reg);+ fprintf(compiler->verbose, ", [");+ sljit_verbose_reg(compiler, mem_reg);+ fprintf(compiler->verbose, "], ");+ sljit_verbose_reg(compiler, temp_reg);+ fprintf(compiler->verbose, "\n");+ }+#endif /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 unset,+ 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;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ROTR);++ switch (GET_OPCODE(op)) {+ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ case SLJIT_SHL:+ case SLJIT_MSHL:+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ 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_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_32) == (compiler->last_flags & SLJIT_32));+ break;+ case SLJIT_ROTL:+ case SLJIT_ROTR:+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ break;+ default:+ SLJIT_UNREACHABLE();+ break;+ }++ if (unset) {+ CHECK_ARGUMENT(HAS_FLAGS(op));+ } else {+ FUNCTION_CHECK_DST(dst, dstw);+ }+ FUNCTION_CHECK_SRC(src1, src1w);+ FUNCTION_CHECK_SRC(src2, src2w);+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",+ !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",+ !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);+ if (unset)+ fprintf(compiler->verbose, "unset");+ else+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT((op | SLJIT_32) == SLJIT_MULADD32);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));+ 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, " %s%s ", op2r_names[GET_OPCODE(op) - SLJIT_OP2R_BASE], !(op & SLJIT_32) ? "" : "32");++ sljit_verbose_reg(compiler, dst_reg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_LSHR+ || GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR);+ CHECK_ARGUMENT((op & ~(0xff | SLJIT_32 | SLJIT_SHIFT_INTO_NON_ZERO)) == 0);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src1_reg));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg));+ FUNCTION_CHECK_SRC(src3, src3w);+ CHECK_ARGUMENT(dst_reg != src2_reg);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s.into%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",+ (op & SLJIT_SHIFT_INTO_NON_ZERO) ? ".nz" : "");++ sljit_verbose_reg(compiler, dst_reg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_reg(compiler, src1_reg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_reg(compiler, src2_reg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src3, src3w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE);+ FUNCTION_CHECK_SRC(src, srcw);++ if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN) {+ CHECK_ARGUMENT(src != SLJIT_IMM);+ compiler->last_flags = 0;+ } else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE) {+ CHECK_ARGUMENT(src & SLJIT_MEM);+ }+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]);+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(op >= SLJIT_FAST_ENTER && op <= SLJIT_GET_RETURN_ADDRESS);+ FUNCTION_CHECK_DST(dst, dstw);++ if (op == SLJIT_FAST_ENTER)+ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]);+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(reg);+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ if (type == SLJIT_GP_REGISTER) {+ CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS)+ || (reg >= SLJIT_TMP_REGISTER_BASE && reg < (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS)));+ } else {+ CHECK_ARGUMENT(type == SLJIT_FLOAT_REGISTER || ((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6)));+ CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS)+ || (reg >= SLJIT_TMP_FREGISTER_BASE && reg < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)));+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ sljit_u32 i;+#endif++ SLJIT_UNUSED_ARG(compiler);++#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)+ CHECK_ARGUMENT((size == 2 && (((sljit_sw)instruction) & 0x1) == 0)+ || (size == 4 && (((sljit_sw)instruction) & 0x3) == 0));+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+ CHECK_ARGUMENT(size == 2 || size == 4 || size == 6);+#else+ 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_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_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ 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, op & SLJIT_32);+ FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ 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_32) ? ".f32.from.f64" : ".f64.from.f32");+ else+ fprintf(compiler->verbose, " %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],+ (op & SLJIT_32) ? ".f32" : ".f64");++ sljit_verbose_fparam(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++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_32);+#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_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_F_EQUAL && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_LESS_EQUAL));+ FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);+ FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_32) ? ".f32" : ".f64");+ if (op & VARIABLE_FLAG_MASK) {+ fprintf(compiler->verbose, ".%s", jump_names[GET_FLAG_TYPE(op)]);+ }+ fprintf(compiler->verbose, " ");+ sljit_verbose_fparam(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++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;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ FUNCTION_FCHECK(src, srcw, op & SLJIT_32);+ FUNCTION_CHECK_DST(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],+ fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64],+ (op & SLJIT_32) ? ".f32" : ".f64");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_w(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;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ FUNCTION_CHECK_SRC(src, srcw);+ FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);+#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_32) ? ".f32" : ".f64",+ fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64]);+ sljit_verbose_fparam(compiler, dst, dstw);+ 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_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 (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ 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, op & SLJIT_32);+ FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);+ FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_32) ? ".f32" : ".f64");+ sljit_verbose_fparam(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_COPYSIGN_F64);+ FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);+ FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, op & SLJIT_32));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s ", fop2r_names[GET_OPCODE(op) - SLJIT_FOP2R_BASE], (op & SLJIT_32) ? ".f32" : ".f64");+ sljit_verbose_freg(compiler, dst_freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+ SLJIT_UNUSED_ARG(value);++ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 1));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " fset32 ");+ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", %f\n", value);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ SLJIT_UNUSED_ARG(value);++ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " fset64 ");+ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", %f\n", value);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_COPY_TO_F64 && GET_OPCODE(op) <= SLJIT_COPY_FROM_F64);+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, op & SLJIT_32));++#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));+#else /* !SLJIT_64BIT_ARCHITECTURE */+ switch (op) {+ case SLJIT_COPY32_TO_F32:+ case SLJIT_COPY32_FROM_F32:+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));+ break;+ case SLJIT_COPY_TO_F64:+ case SLJIT_COPY_FROM_F64:+ if (reg & REG_PAIR_MASK) {+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg)));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg)));++ if (op == SLJIT_COPY_TO_F64)+ break;++ CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg));+ break;+ }++ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));+ break;+ }+#endif /* SLJIT_64BIT_ARCHITECTURE */+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " copy%s_%s_f%s ", (op & SLJIT_32) ? "32" : "",+ GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? "to" : "from", (op & SLJIT_32) ? "32" : "64");++ sljit_verbose_freg(compiler, freg);++ if (reg & REG_PAIR_MASK) {+ fprintf(compiler->verbose, ", {");+ sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg));+ fprintf(compiler->verbose, ", ");+ sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg));+ fprintf(compiler->verbose, "}\n");+ } else {+ fprintf(compiler->verbose, ", ");+ sljit_verbose_reg(compiler, reg);+ fprintf(compiler->verbose, "\n");+ }+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compiler *compiler)+{+ 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");+#endif+ CHECK_RETURN_OK;+}++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \+ || (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)+#define CHECK_UNORDERED(type, last_flags) \+ ((((type) & 0xfe) == SLJIT_ORDERED) && \+ ((last_flags) & 0xff) >= SLJIT_UNORDERED && ((last_flags) & 0xff) <= SLJIT_ORDERED_LESS_EQUAL)+#else+#define CHECK_UNORDERED(type, last_flags) 0+#endif+#endif /* SLJIT_ARGUMENT_CHECKS */++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;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL);++ if ((type & 0xff) < SLJIT_JUMP) {+ if ((type & 0xff) <= SLJIT_NOT_ZERO)+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);+ else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {+ CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);+ compiler->last_flags = 0;+ } else+ CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff)+ || CHECK_UNORDERED(type, compiler->last_flags));+ }+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose))+ fprintf(compiler->verbose, " jump%s %s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",+ jump_names[type & 0xff]);+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN)));+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);+ CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));++ if (type & SLJIT_CALL_RETURN) {+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);++ if (compiler->options & SLJIT_ENTER_REG_ARG) {+ CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);+ } else {+ CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);+ }+ }+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s%s ret[%s", jump_names[type & 0xff],+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",+ !(type & SLJIT_CALL_RETURN) ? "" : ".ret",+ call_arg_names[arg_types & SLJIT_ARG_MASK]);++ arg_types >>= SLJIT_ARG_SHIFT;+ if (arg_types) {+ fprintf(compiler->verbose, "], args[");+ do {+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);+ arg_types >>= SLJIT_ARG_SHIFT;+ if (arg_types)+ fprintf(compiler->verbose, ",");+ } while (arg_types);+ }+ fprintf(compiler->verbose, "]\n");+ }+#endif+ CHECK_RETURN_OK;+}++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_32)));+ 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_32) ? "32" : "",+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);+ sljit_verbose_param(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++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_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_F_EQUAL && (type & 0xff) <= SLJIT_ORDERED_LESS_EQUAL);+ FUNCTION_FCHECK(src1, src1w, type & SLJIT_32);+ FUNCTION_FCHECK(src2, src2w, type & SLJIT_32);+ 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_32) ? ".f32" : ".f64",+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);+ sljit_verbose_fparam(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src, sljit_sw srcw)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL);+ FUNCTION_CHECK_SRC(src, srcw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " ijump.%s ", jump_names[type]);+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN)));+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);+ CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));+ FUNCTION_CHECK_SRC(src, srcw);++ if (type & SLJIT_CALL_RETURN) {+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);++ if (compiler->options & SLJIT_ENTER_REG_ARG) {+ CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);+ } else {+ CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);+ }+ }+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff],+ !(type & SLJIT_CALL_RETURN) ? "" : ".ret",+ call_arg_names[arg_types & SLJIT_ARG_MASK]);++ arg_types >>= SLJIT_ARG_SHIFT;+ if (arg_types) {+ fprintf(compiler->verbose, "], args[");+ do {+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);+ arg_types >>= SLJIT_ARG_SHIFT;+ if (arg_types)+ fprintf(compiler->verbose, ",");+ } while (arg_types);+ }+ 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_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 >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL);+ CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32+ || (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));++ if (type <= SLJIT_NOT_ZERO)+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);+ else+ CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff)+ || CHECK_UNORDERED(type, compiler->last_flags));++ FUNCTION_CHECK_DST(dst, dstw);++ if (GET_OPCODE(op) >= SLJIT_ADD)+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " flags.%s%s%s ",+ GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],+ GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_32) ? "32" : ""),+ !(op & SLJIT_SET_Z) ? "" : ".z");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", %s\n", jump_names[type]);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ sljit_s32 cond = type & ~SLJIT_32;++ CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL);++ CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));+ FUNCTION_CHECK_SRC(src1, src1w);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg));++ if (cond <= SLJIT_NOT_ZERO)+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);+ else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {+ CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);+ compiler->last_flags = 0;+ } else+ CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)+ || CHECK_UNORDERED(cond, compiler->last_flags));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " select%s %s, ",+ !(type & SLJIT_32) ? "" : "32",+ jump_names[type & ~SLJIT_32]);+ sljit_verbose_reg(compiler, dst_reg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_reg(compiler, src2_reg);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ sljit_s32 cond = type & ~SLJIT_32;++ CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL);++ CHECK_ARGUMENT(compiler->fscratches != -1 && compiler->fsaveds != -1);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, type & SLJIT_32));+ FUNCTION_FCHECK(src1, src1w, type & SLJIT_32);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src2_freg, type & SLJIT_32));++ if (cond <= SLJIT_NOT_ZERO)+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);+ else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {+ CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);+ compiler->last_flags = 0;+ } else+ CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)+ || CHECK_UNORDERED(cond, compiler->last_flags));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " fselect%s %s, ",+ !(type & SLJIT_32) ? "" : "32",+ jump_names[type & ~SLJIT_32]);+ sljit_verbose_freg(compiler, dst_freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_freg(compiler, src2_freg);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ sljit_s32 allowed_flags;+#endif /* SLJIT_ARGUMENT_CHECKS */++ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ if (type & SLJIT_MEM_UNALIGNED) {+ CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));+ } else if (type & SLJIT_MEM_ALIGNED_16) {+ CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32));+ } else {+ CHECK_ARGUMENT((reg & REG_PAIR_MASK) || (type & SLJIT_MEM_ALIGNED_32));+ }++ allowed_flags = SLJIT_MEM_UNALIGNED;++ switch (type & 0xff) {+ case SLJIT_MOV_P:+ case SLJIT_MOV:+ allowed_flags |= SLJIT_MEM_ALIGNED_32;+ /* fallthrough */+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ allowed_flags |= SLJIT_MEM_ALIGNED_16;+ break;+ }++ CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | allowed_flags)) == 0);++ if (reg & REG_PAIR_MASK) {+ CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg)));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg)));+ CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg));+ } else {+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);+ CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) >= SLJIT_MOV_U8 && (type & 0xff) <= SLJIT_MOV_S16));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));+ }++ FUNCTION_CHECK_SRC_MEM(mem, memw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if ((type & 0xff) == SLJIT_MOV32)+ fprintf(compiler->verbose, " %s32",+ (type & SLJIT_MEM_STORE) ? "store" : "load");+ else+ fprintf(compiler->verbose, " %s%s%s",+ (type & SLJIT_MEM_STORE) ? "store" : "load",+ !(type & SLJIT_32) ? "" : "32", op1_types[(type & 0xff) - SLJIT_OP1_BASE]);++ if (type & SLJIT_MEM_UNALIGNED)+ printf(".unal");+ else if (type & SLJIT_MEM_ALIGNED_16)+ printf(".al16");+ else if (type & SLJIT_MEM_ALIGNED_32)+ printf(".al32");++ if (reg & REG_PAIR_MASK) {+ fprintf(compiler->verbose, " {");+ sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg));+ fprintf(compiler->verbose, ", ");+ sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg));+ fprintf(compiler->verbose, "}, ");+ } else {+ fprintf(compiler->verbose, " ");+ sljit_verbose_reg(compiler, reg);+ fprintf(compiler->verbose, ", ");+ }+ sljit_verbose_param(compiler, mem, memw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);+ CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0);+ CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);++ FUNCTION_CHECK_SRC_MEM(mem, memw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (type & SLJIT_MEM_SUPP)+ CHECK_RETURN_OK;+ if (sljit_emit_mem_update(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {+ fprintf(compiler->verbose, " # mem: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ if ((type & 0xff) == SLJIT_MOV32)+ fprintf(compiler->verbose, " %s32.%s ",+ (type & SLJIT_MEM_STORE) ? "store" : "load",+ (type & SLJIT_MEM_POST) ? "post" : "pre");+ else+ fprintf(compiler->verbose, " %s%s%s.%s ",+ (type & SLJIT_MEM_STORE) ? "store" : "load",+ !(type & SLJIT_32) ? "" : "32",+ op1_types[(type & 0xff) - SLJIT_OP1_BASE],+ (type & SLJIT_MEM_POST) ? "post" : "pre");++ sljit_verbose_reg(compiler, reg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, mem, memw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);++ if (type & SLJIT_MEM_UNALIGNED) {+ CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));+ } else if (type & SLJIT_MEM_ALIGNED_16) {+ CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32));+ } else {+ CHECK_ARGUMENT(type & SLJIT_MEM_ALIGNED_32);+ CHECK_ARGUMENT(!(type & SLJIT_32));+ }++ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32));+ FUNCTION_CHECK_SRC_MEM(mem, memw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s.%s",+ (type & SLJIT_MEM_STORE) ? "store" : "load",+ !(type & SLJIT_32) ? "f64" : "f32");++ if (type & SLJIT_MEM_UNALIGNED)+ printf(".unal");+ else if (type & SLJIT_MEM_ALIGNED_16)+ printf(".al16");+ else if (type & SLJIT_MEM_ALIGNED_32)+ printf(".al32");++ fprintf(compiler->verbose, " ");+ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, mem, memw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);+ CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0);+ FUNCTION_CHECK_SRC_MEM(mem, memw);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (type & SLJIT_MEM_SUPP)+ CHECK_RETURN_OK;+ if (sljit_emit_fmem_update(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {+ fprintf(compiler->verbose, " # fmem: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " %s.%s.%s ",+ (type & SLJIT_MEM_STORE) ? "store" : "load",+ !(type & SLJIT_32) ? "f64" : "f32",+ (type & SLJIT_MEM_POST) ? "post" : "pre");++ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, mem, memw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_STORE)) == 0);+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (srcdst & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));+ FUNCTION_FCHECK(srcdst, srcdstw, 0);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (type & SLJIT_SIMD_TEST)+ CHECK_RETURN_OK;+ if (sljit_emit_simd_mov(compiler, type | SLJIT_SIMD_TEST, freg, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) {+ fprintf(compiler->verbose, " # simd_mem: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " simd_%s.%d.%s%d",+ (type & SLJIT_SIMD_STORE) ? "store" : "load",+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));++ if ((type & 0x3f000000) == SLJIT_SIMD_MEM_UNALIGNED)+ fprintf(compiler->verbose, ".unal ");+ else+ fprintf(compiler->verbose, ".al%d ", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)));++ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, srcdst, srcdstw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0);+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));++ if (type & SLJIT_SIMD_FLOAT) {+ if (src == SLJIT_IMM) {+ CHECK_ARGUMENT(srcw == 0);+ } else {+ FUNCTION_FCHECK(src, srcw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);+ }+ } else if (src != SLJIT_IMM) {+ FUNCTION_CHECK_DST(src, srcw);+ }+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (type & SLJIT_SIMD_TEST)+ CHECK_RETURN_OK;+ if (sljit_emit_simd_replicate(compiler, type | SLJIT_SIMD_TEST, freg, src, srcw) == SLJIT_ERR_UNSUPPORTED) {+ fprintf(compiler->verbose, " # simd_dup: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " simd_replicate.%d.%s%d ",+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));++ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", ");+ if (type & SLJIT_SIMD_FLOAT)+ sljit_verbose_fparam(compiler, src, srcw);+ else+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO | SLJIT_SIMD_LANE_SIGNED | SLJIT_32)) == 0);+ CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO)) != (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO));+ CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_SIGNED)) != SLJIT_SIMD_LANE_SIGNED);+ CHECK_ARGUMENT(!(type & SLJIT_SIMD_FLOAT) || !(type & (SLJIT_SIMD_LANE_SIGNED | SLJIT_32)));+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));+ CHECK_ARGUMENT(!(type & SLJIT_32) || SLJIT_SIMD_GET_ELEM_SIZE(type) <= 2);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));+ CHECK_ARGUMENT(lane_index >= 0 && lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type))));++ if (type & SLJIT_SIMD_FLOAT) {+ FUNCTION_FCHECK(srcdst, srcdstw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);+ } else if ((type & SLJIT_SIMD_STORE) || srcdst != SLJIT_IMM) {+ FUNCTION_CHECK_DST(srcdst, srcdstw);+ }+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (type & SLJIT_SIMD_TEST)+ CHECK_RETURN_OK;+ if (sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_TEST, freg, lane_index, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) {+ fprintf(compiler->verbose, " # simd_move_lane: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " simd_%s_lane%s%s%s.%d.%s%d ",+ (type & SLJIT_SIMD_STORE) ? "store" : "load",+ (type & SLJIT_32) ? "32" : "",+ (type & SLJIT_SIMD_LANE_ZERO) ? "_z" : "",+ (type & SLJIT_SIMD_LANE_SIGNED) ? "_s" : "",+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));++ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, "[%d], ", lane_index);+ if (type & SLJIT_SIMD_FLOAT)+ sljit_verbose_fparam(compiler, srcdst, srcdstw);+ else+ sljit_verbose_param(compiler, srcdst, srcdstw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_s32 src_lane_index)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0);+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src, 0));+ CHECK_ARGUMENT(src_lane_index >= 0 && src_lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type))));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (type & SLJIT_SIMD_TEST)+ CHECK_RETURN_OK;+ if (sljit_emit_simd_lane_replicate(compiler, type | SLJIT_SIMD_TEST, freg, src, src_lane_index) == SLJIT_ERR_UNSUPPORTED) {+ fprintf(compiler->verbose, " # simd_lane_replicate: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " simd_lane_replicate.%d.%s%d ",+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));++ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_freg(compiler, src);+ fprintf(compiler->verbose, "[%d]\n", src_lane_index);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_EXTEND_SIGNED)) == 0);+ CHECK_ARGUMENT((type & (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT)) != (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT));+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_ELEM2_SIZE(type));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));+ FUNCTION_FCHECK(src, srcw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (type & SLJIT_SIMD_TEST)+ CHECK_RETURN_OK;+ if (sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_TEST, freg, src, srcw) == SLJIT_ERR_UNSUPPORTED) {+ fprintf(compiler->verbose, " # simd_extend: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " simd_load_extend%s.%d.%s%d.%s%d ",+ (type & SLJIT_SIMD_EXTEND_SIGNED) ? "_s" : "",+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",+ (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)),+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));++ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 dst, sljit_sw dstw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_32)) == SLJIT_SIMD_STORE);+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));+ FUNCTION_CHECK_DST(dst, dstw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (type & SLJIT_SIMD_TEST)+ CHECK_RETURN_OK;+ if (sljit_emit_simd_sign(compiler, type | SLJIT_SIMD_TEST, freg, dst, dstw) == SLJIT_ERR_UNSUPPORTED) {+ fprintf(compiler->verbose, " # simd_sign: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " simd_store_sign%s.%d.%s%d ",+ (type & SLJIT_32) ? "32" : "",+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));++ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) >= SLJIT_SIMD_OP2_AND && (type & SLJIT_SIMD_TYPE_MASK(0)) <= SLJIT_SIMD_OP2_XOR);+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, 0));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src1_freg, 0));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src2_freg, 0));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (type & SLJIT_SIMD_TEST)+ CHECK_RETURN_OK;+ if (sljit_emit_simd_op2(compiler, type | SLJIT_SIMD_TEST, dst_freg, src1_freg, src2_freg) == SLJIT_ERR_UNSUPPORTED) {+ fprintf(compiler->verbose, " # simd_op2: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " simd_%s.%d.%s%d ",+ simd_op2_names[SLJIT_SIMD_GET_OPCODE(type) - 1],+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));++ sljit_verbose_freg(compiler, dst_freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_freg(compiler, src1_freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_freg(compiler, src2_freg);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)+{+ /* Any offset is allowed. */+ SLJIT_UNUSED_ARG(offset);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ FUNCTION_CHECK_DST(dst, dstw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " local_base ");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset);+ }+#endif+ CHECK_RETURN_OK;+}++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);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " const ");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ FUNCTION_CHECK_DST(dst, dstw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " mov_addr ");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_VERBOSE */++#define SLJIT_SKIP_CHECKS(compiler)++#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */++#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \+ SLJIT_COMPILE_ASSERT(!(SLJIT_CONV_SW_FROM_F64 & 0x1) && !(SLJIT_CONV_F64_FROM_SW & 0x1) && !(SLJIT_CONV_F64_FROM_UW & 0x1), \+ invalid_float_opcodes); \+ 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_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_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw); \+ } \+ if ((GET_OPCODE(op) | 0x1) == SLJIT_CONV_F64_FROM_S32) { \+ CHECK(check_sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw)); \+ ADJUST_LOCAL_OFFSET(dst, dstw); \+ ADJUST_LOCAL_OFFSET(src, srcw); \+ return sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw); \+ } \+ CHECK(check_sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw)); \+ ADJUST_LOCAL_OFFSET(dst, dstw); \+ ADJUST_LOCAL_OFFSET(src, srcw); \+ return sljit_emit_fop1_conv_f64_from_uw(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);++#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6))++static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ SLJIT_SKIP_CHECKS(compiler);++ if (type & SLJIT_MEM_STORE)+ return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), mem, memw, reg, 0);+ return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), reg, 0, mem, memw);+}++#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) */++#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \+ && !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)++static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ SLJIT_SKIP_CHECKS(compiler);++ if (type & SLJIT_MEM_STORE)+ return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), mem, memw, freg, 0);+ return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), freg, 0, mem, memw);+}++#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM */++/* CPU description section */++#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)+#define SLJIT_CPUINFO_PART1 " 32bit ("+#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#define SLJIT_CPUINFO_PART1 " 64bit ("+#else+#error "Internal error: CPU type info missing"+#endif++#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#define SLJIT_CPUINFO_PART2 "little endian + "+#elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)+#define SLJIT_CPUINFO_PART2 "big endian + "+#else+#error "Internal error: CPU type info missing"+#endif++#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)+#define SLJIT_CPUINFO_PART3 "unaligned)"+#else+#define SLJIT_CPUINFO_PART3 "aligned)"+#endif++#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+# include "sljitNativeX86_common.c"+#elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+# include "sljitNativeARM_32.c"+#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+# include "sljitNativeARM_32.c"+#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+# include "sljitNativeARM_T2_32.c"+#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+# include "sljitNativeARM_64.c"+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+# include "sljitNativePPC_common.c"+#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+# include "sljitNativeMIPS_common.c"+#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)+# include "sljitNativeRISCV_common.c"+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+# include "sljitNativeS390X.c"+#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)+# include "sljitNativeLOONGARCH_64.c"+#endif++#include "sljitSerialize.c"++static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+ /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */+ 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_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P))+ return SLJIT_SUCCESS;+#endif++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);+}++#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \+ && !((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && defined __SOFTFP__)++static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ if (src == SLJIT_FR0)+ return SLJIT_SUCCESS;++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);+}++#endif /* !SLJIT_CONFIG_X86_32 && !(SLJIT_CONFIG_ARM_32 && __SOFTFP__) */++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));++ if (GET_OPCODE(op) < SLJIT_MOV_F64) {+ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));+ } else {+ FAIL_IF(emit_fmov_before_return(compiler, op, src, srcw));+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_return_void(compiler);+}++#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \+ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \+ && !(defined(SLJIT_CONFIG_LOONGARCH_64) && SLJIT_CONFIG_LOONGARCH_64)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_fop2(compiler, op, dst_freg, 0, src1, src1w, src2, src2w);+}++#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_S390X && !SLJIT_CONFIG_LOONGARCH_64 */++#if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \+ && !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \+ && !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)++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_s32 flags, tmp_src, condition;+ sljit_sw tmp_srcw;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));++ condition = type & 0xff;+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+ if ((condition == SLJIT_EQUAL || condition == SLJIT_NOT_EQUAL)) {+ if (src1 == SLJIT_IMM && !src1w) {+ src1 = src2;+ src1w = src2w;+ src2 = SLJIT_IMM;+ src2w = 0;+ }+ if (src2 == SLJIT_IMM && !src2w)+ return emit_cmp_to0(compiler, type, src1, src1w);+ }+#endif++ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM && src2 != SLJIT_IMM)) {+ /* Immediate is preferred as second argument by most architectures. */+ switch (condition) {+ case SLJIT_LESS:+ condition = SLJIT_GREATER;+ break;+ case SLJIT_GREATER_EQUAL:+ condition = SLJIT_LESS_EQUAL;+ break;+ case SLJIT_GREATER:+ condition = SLJIT_LESS;+ break;+ case SLJIT_LESS_EQUAL:+ condition = SLJIT_GREATER_EQUAL;+ break;+ case SLJIT_SIG_LESS:+ condition = SLJIT_SIG_GREATER;+ break;+ case SLJIT_SIG_GREATER_EQUAL:+ condition = SLJIT_SIG_LESS_EQUAL;+ break;+ case SLJIT_SIG_GREATER:+ condition = SLJIT_SIG_LESS;+ break;+ case SLJIT_SIG_LESS_EQUAL:+ condition = SLJIT_SIG_GREATER_EQUAL;+ break;+ }++ type = condition | (type & (SLJIT_32 | SLJIT_REWRITABLE_JUMP));+ tmp_src = src1;+ src1 = src2;+ src2 = tmp_src;+ tmp_srcw = src1w;+ src1w = src2w;+ src2w = tmp_srcw;+ }++ if (condition <= SLJIT_NOT_ZERO)+ flags = SLJIT_SET_Z;+ else+ flags = (condition & 0xfe) << VARIABLE_FLAG_SHIFT;++ SLJIT_SKIP_CHECKS(compiler);+ PTR_FAIL_IF(sljit_emit_op2u(compiler,+ SLJIT_SUB | flags | (type & SLJIT_32), src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_32)));+}++#endif /* !SLJIT_CONFIG_MIPS */++#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)+{+ switch (type) {+ case SLJIT_UNORDERED_OR_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ return 1;+ }++ return 0;+}++#endif /* SLJIT_CONFIG_ARM */++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));++ SLJIT_SKIP_CHECKS(compiler);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xfe) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w);++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, type);+}++#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \+ && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(reg);+ SLJIT_UNUSED_ARG(mem);+ SLJIT_UNUSED_ARG(memw);++ return SLJIT_ERR_UNSUPPORTED;+}++#endif /* !SLJIT_CONFIG_ARM && !SLJIT_CONFIG_PPC */++#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \+ && !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));++ return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);+}++#endif /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS */++#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(freg);+ SLJIT_UNUSED_ARG(mem);+ SLJIT_UNUSED_ARG(memw);++ return SLJIT_ERR_UNSUPPORTED;+}++#endif /* !SLJIT_CONFIG_ARM_64 && !SLJIT_CONFIG_PPC */++#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \+ && !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \+ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \+ && !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(freg);+ SLJIT_UNUSED_ARG(srcdst);+ SLJIT_UNUSED_ARG(srcdstw);++ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(freg);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);++ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(freg);+ SLJIT_UNUSED_ARG(lane_index);+ SLJIT_UNUSED_ARG(srcdst);+ SLJIT_UNUSED_ARG(srcdstw);++ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_s32 src_lane_index)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(freg);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(src_lane_index);++ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(freg);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);++ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(freg);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);++ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(dst_freg);+ SLJIT_UNUSED_ARG(src1_freg);+ SLJIT_UNUSED_ARG(src2_freg);++ return SLJIT_ERR_UNSUPPORTED;+}++#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM */++#if !(defined(SLJIT_CONFIG_X86) && SLJIT_CONFIG_X86) \+ && !(defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM) \+ && !(defined(SLJIT_CONFIG_S390X) && SLJIT_CONFIG_S390X) \+ && !(defined(SLJIT_CONFIG_LOONGARCH) && SLJIT_CONFIG_LOONGARCH)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler,+ sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 mem_reg)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNUSED_ARG(dst_reg);+ SLJIT_UNUSED_ARG(mem_reg);++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));++ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler,+ sljit_s32 op,+ sljit_s32 src_reg,+ sljit_s32 mem_reg,+ sljit_s32 temp_reg)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNUSED_ARG(src_reg);+ SLJIT_UNUSED_ARG(mem_reg);+ SLJIT_UNUSED_ARG(temp_reg);++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));++ return SLJIT_ERR_UNSUPPORTED;+}++#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM && !SLJIT_CONFIG_S390X && !SLJIT_CONFIG_LOONGARCH */++#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)++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));++ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);++ SLJIT_SKIP_CHECKS(compiler);++ if (offset != 0)+ 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);+}++#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_64 */ #endif /* !SLJIT_CONFIG_UNSUPPORTED */
src/c/pcre2/src/sljit/sljitLir.h view
@@ -36,1555 +36,2428 @@ Advantages: - The execution can be continued from any LIR instruction. In other words, it is possible to jump to any label from anywhere, even from- a code fragment, which is compiled later, if both compiled code- shares the same context. See sljit_emit_enter for more details- - Supports self modifying code: target of (conditional) jump and call- instructions and some constant values can be dynamically modified- during runtime- - although it is not suggested to do it frequently- - can be used for inline caching: save an important value once- in the instruction stream- - since this feature limits the optimization possibilities, a- special flag must be passed at compile time when these- instructions are emitted- - A fixed stack space can be allocated for local variables- - The compiler is thread-safe- - The compiler is highly configurable through preprocessor macros.- You can disable unneeded features (multithreading in single- threaded applications), and you can use your own system functions- (including memory allocators). See sljitConfig.h- Disadvantages:- - No automatic register allocation, and temporary results are- not stored on the stack. (hence the name comes)- In practice:- - This approach is very effective for interpreters- - One of the saved registers typically points to a stack interface- - It can jump to any exception handler anytime (even if it belongs- to another function)- - Hot paths can be modified during runtime reflecting the changes- of the fastest execution path of the dynamic language- - SLJIT supports complex memory addressing modes- - mainly position and context independent code (except some cases)-- For valgrind users:- - pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code"-*/--#if (defined SLJIT_HAVE_CONFIG_PRE && SLJIT_HAVE_CONFIG_PRE)-#include "sljitConfigPre.h"-#endif /* SLJIT_HAVE_CONFIG_PRE */--#include "sljitConfig.h"--/* The following header file defines useful macros for fine tuning-sljit based code generators. They are listed in the beginning-of sljitConfigInternal.h */--#include "sljitConfigInternal.h"--#if (defined SLJIT_HAVE_CONFIG_POST && SLJIT_HAVE_CONFIG_POST)-#include "sljitConfigPost.h"-#endif /* SLJIT_HAVE_CONFIG_POST */--#ifdef __cplusplus-extern "C" {-#endif--/* --------------------------------------------------------------------- */-/* Error codes */-/* --------------------------------------------------------------------- */--/* Indicates no error. */-#define SLJIT_SUCCESS 0-/* After the call of sljit_generate_code(), the error code of the compiler- is set to this value to avoid future sljit calls (in debug mode at least).- The complier should be freed after sljit_generate_code(). */-#define SLJIT_ERR_COMPILED 1-/* Cannot allocate non executable memory. */-#define SLJIT_ERR_ALLOC_FAILED 2-/* Cannot allocate executable memory.- Only for sljit_generate_code() */-#define SLJIT_ERR_EX_ALLOC_FAILED 3-/* Return value for SLJIT_CONFIG_UNSUPPORTED placeholder architecture. */-#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 */-/* --------------------------------------------------------------------- */--/*- Scratch (R) registers: registers whose may not preserve their values- across function calls.-- Saved (S) registers: registers whose preserve their values across- function calls.-- The scratch and saved register sets are overlap. The last scratch register- is the first saved register, the one before the last is the second saved- register, and so on.-- If an architecture provides two scratch and three saved registers,- its scratch and saved register sets are the following:-- 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-- 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 >= 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: 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 scratch 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.-- 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 S1 register- is not available at all.-*/--/* Scratch registers. */-#define SLJIT_R0 1-#define SLJIT_R1 2-#define SLJIT_R2 3-/* Note: on x86-32, R3 - R6 (same as S3 - S6) are emulated (they- are allocated on the stack). These registers are called virtual- and cannot be used for memory addressing (cannot be part of- any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such- limitation on other CPUs. See sljit_get_register_index(). */-#define SLJIT_R3 4-#define SLJIT_R4 5-#define SLJIT_R5 6-#define SLJIT_R6 7-#define SLJIT_R7 8-#define SLJIT_R8 9-#define SLJIT_R9 10-/* All R registers provided by the architecture can be accessed by SLJIT_R(i)- The i parameter must be >= 0 and < SLJIT_NUMBER_OF_REGISTERS. */-#define SLJIT_R(i) (1 + (i))--/* Saved registers. */-#define SLJIT_S0 (SLJIT_NUMBER_OF_REGISTERS)-#define SLJIT_S1 (SLJIT_NUMBER_OF_REGISTERS - 1)-#define SLJIT_S2 (SLJIT_NUMBER_OF_REGISTERS - 2)-/* Note: on x86-32, S3 - S6 (same as R3 - R6) are emulated (they- are allocated on the stack). These registers are called virtual- and cannot be used for memory addressing (cannot be part of- any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such- limitation on other CPUs. See sljit_get_register_index(). */-#define SLJIT_S3 (SLJIT_NUMBER_OF_REGISTERS - 3)-#define SLJIT_S4 (SLJIT_NUMBER_OF_REGISTERS - 4)-#define SLJIT_S5 (SLJIT_NUMBER_OF_REGISTERS - 5)-#define SLJIT_S6 (SLJIT_NUMBER_OF_REGISTERS - 6)-#define SLJIT_S7 (SLJIT_NUMBER_OF_REGISTERS - 7)-#define SLJIT_S8 (SLJIT_NUMBER_OF_REGISTERS - 8)-#define SLJIT_S9 (SLJIT_NUMBER_OF_REGISTERS - 9)-/* All S registers provided by the architecture can be accessed by SLJIT_S(i)- The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_REGISTERS. */-#define SLJIT_S(i) (SLJIT_NUMBER_OF_REGISTERS - (i))--/* Registers >= SLJIT_FIRST_SAVED_REG are saved registers. */-#define SLJIT_FIRST_SAVED_REG (SLJIT_S0 - SLJIT_NUMBER_OF_SAVED_REGISTERS + 1)--/* The SLJIT_SP provides direct access to the linear stack space allocated by- sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP).- The immediate offset is extended by the relative stack offset automatically.- The sljit_get_local_base can be used to obtain the absolute offset. */-#define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1)--/* Return with machine word. */--#define SLJIT_RETURN_REG SLJIT_R0--/* --------------------------------------------------------------------- */-/* Floating point registers */-/* --------------------------------------------------------------------- */--/* 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. */--/* Floating point scratch registers. */-#define SLJIT_FR0 1-#define SLJIT_FR1 2-#define SLJIT_FR2 3-#define SLJIT_FR3 4-#define SLJIT_FR4 5-#define SLJIT_FR5 6-/* All FR registers provided by the architecture can be accessed by SLJIT_FR(i)- The i parameter must be >= 0 and < SLJIT_NUMBER_OF_FLOAT_REGISTERS. */-#define SLJIT_FR(i) (1 + (i))--/* Floating point saved registers. */-#define SLJIT_FS0 (SLJIT_NUMBER_OF_FLOAT_REGISTERS)-#define SLJIT_FS1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1)-#define SLJIT_FS2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2)-#define SLJIT_FS3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 3)-#define SLJIT_FS4 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 4)-#define SLJIT_FS5 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 5)-/* All S registers provided by the architecture can be accessed by SLJIT_FS(i)- The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS. */-#define SLJIT_FS(i) (SLJIT_NUMBER_OF_FLOAT_REGISTERS - (i))--/* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */-#define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1)--/* --------------------------------------------------------------------- */-/* Argument type definitions */-/* --------------------------------------------------------------------- */--/* The following argument type definitions are used by sljit_emit_enter,- sljit_set_context, sljit_emit_call, and sljit_emit_icall functions.-- As for sljit_emit_call and sljit_emit_icall, the first integer argument- must be placed into SLJIT_R0, the second one into SLJIT_R1, and so on.- Similarly the first floating point argument must be placed into SLJIT_FR0,- the second one into SLJIT_FR1, and so on.-- As for sljit_emit_enter, the integer arguments can be stored in scratch- or saved registers. The first integer argument without _R postfix is- stored in SLJIT_S0, the next one in SLJIT_S1, and so on. The integer- arguments with _R postfix are placed into scratch registers. The index- of the scratch register is the count of the previous integer arguments- starting from SLJIT_R0. The floating point arguments are always placed- into SLJIT_FR0, SLJIT_FR1, and so on.-- Note: if a function is called by sljit_emit_call/sljit_emit_icall and- an argument is stored in a scratch register by sljit_emit_enter,- that argument uses the same scratch register index for both- integer and floating point arguments.-- Example function definition:- sljit_f32 SLJIT_FUNC example_c_callback(void *arg_a,- sljit_f64 arg_b, sljit_u32 arg_c, sljit_f32 arg_d);-- Argument type definition:- SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_F32)- | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_P, 1) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F64, 2)- | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_32, 3) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F32, 4)-- Short form of argument type definition:- SLJIT_ARGS4(32, P, F64, 32, F32)-- Argument passing:- arg_a must be placed in SLJIT_R0- arg_c must be placed in SLJIT_R1- arg_b must be placed in SLJIT_FR0- arg_d must be placed in SLJIT_FR1-- Examples for argument processing by sljit_emit_enter:- SLJIT_ARGS4(VOID, P, 32_R, F32, W)- Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_FR0, SLJIT_S1-- SLJIT_ARGS4(VOID, W, W_R, W, W_R)- Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_S1, SLJIT_R3-- SLJIT_ARGS4(VOID, F64, W, F32, W_R)- Arguments are placed into: SLJIT_FR0, SLJIT_S0, SLJIT_FR1, SLJIT_R1-- Note: it is recommended to pass the scratch arguments first- followed by the saved arguments:-- SLJIT_ARGS4(VOID, W_R, W_R, W, W)- Arguments are placed into: SLJIT_R0, SLJIT_R1, SLJIT_S0, SLJIT_S1-*/--/* The following flag is only allowed for the integer arguments of- sljit_emit_enter. When the flag is set, the integer argument is- stored in a scratch register instead of a saved register. */-#define SLJIT_ARG_TYPE_SCRATCH_REG 0x8--/* Void result, can only be used by SLJIT_ARG_RETURN. */-#define SLJIT_ARG_TYPE_VOID 0-/* Machine word sized integer argument or result. */-#define SLJIT_ARG_TYPE_W 1-#define SLJIT_ARG_TYPE_W_R (SLJIT_ARG_TYPE_W | SLJIT_ARG_TYPE_SCRATCH_REG)-/* 32 bit integer argument or result. */-#define SLJIT_ARG_TYPE_32 2-#define SLJIT_ARG_TYPE_32_R (SLJIT_ARG_TYPE_32 | SLJIT_ARG_TYPE_SCRATCH_REG)-/* Pointer sized integer argument or result. */-#define SLJIT_ARG_TYPE_P 3-#define SLJIT_ARG_TYPE_P_R (SLJIT_ARG_TYPE_P | SLJIT_ARG_TYPE_SCRATCH_REG)-/* 64 bit floating point argument or result. */-#define SLJIT_ARG_TYPE_F64 4-/* 32 bit floating point argument or result. */-#define SLJIT_ARG_TYPE_F32 5--#define SLJIT_ARG_SHIFT 4-#define SLJIT_ARG_RETURN(type) (type)-#define SLJIT_ARG_VALUE(type, idx) ((type) << ((idx) * SLJIT_ARG_SHIFT))--/* Simplified argument list definitions.-- The following definition:- SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_W) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F32, 1)-- can be shortened to:- SLJIT_ARGS1(W, F32)-*/--#define SLJIT_ARG_TO_TYPE(type) SLJIT_ARG_TYPE_ ## type--#define SLJIT_ARGS0(ret) \- SLJIT_ARG_RETURN(SLJIT_ARG_TO_TYPE(ret))--#define SLJIT_ARGS1(ret, arg1) \- (SLJIT_ARGS0(ret) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg1), 1))--#define SLJIT_ARGS2(ret, arg1, arg2) \- (SLJIT_ARGS1(ret, arg1) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg2), 2))--#define SLJIT_ARGS3(ret, arg1, arg2, arg3) \- (SLJIT_ARGS2(ret, arg1, arg2) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg3), 3))--#define SLJIT_ARGS4(ret, arg1, arg2, arg3, arg4) \- (SLJIT_ARGS3(ret, arg1, arg2, arg3) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg4), 4))--/* --------------------------------------------------------------------- */-/* Main structures and functions */-/* --------------------------------------------------------------------- */--/*- The following structures are private, and can be changed in the- future. Keeping them here allows code inlining.-*/--struct sljit_memory_fragment {- struct sljit_memory_fragment *next;- sljit_uw used_size;- /* Must be aligned to sljit_sw. */- sljit_u8 memory[1];-};--struct sljit_label {- struct sljit_label *next;- sljit_uw addr;- /* The maximum size difference. */- sljit_uw size;-};--struct sljit_jump {- struct sljit_jump *next;- sljit_uw addr;- sljit_uw flags;- union {- sljit_uw target;- struct sljit_label *label;- } u;-};--struct sljit_put_label {- struct sljit_put_label *next;- struct sljit_label *label;- sljit_uw addr;- sljit_uw flags;-};--struct sljit_const {- struct sljit_const *next;- sljit_uw addr;-};--struct sljit_compiler {- sljit_s32 error;- sljit_s32 options;-- struct sljit_label *labels;- struct sljit_jump *jumps;- struct sljit_put_label *put_labels;- struct sljit_const *consts;- struct sljit_label *last_label;- struct sljit_jump *last_jump;- struct sljit_const *last_const;- struct sljit_put_label *last_put_label;-- void *allocator_data;- void *exec_allocator_data;- struct sljit_memory_fragment *buf;- struct sljit_memory_fragment *abuf;-- /* Used scratch registers. */- sljit_s32 scratches;- /* Used saved registers. */- sljit_s32 saveds;- /* Used float scratch registers. */- sljit_s32 fscratches;- /* Used float saved registers. */- sljit_s32 fsaveds;- /* Local stack size. */- sljit_s32 local_size;- /* Code size. */- sljit_uw size;- /* Relative offset of the executable mapping from the writable mapping. */- sljit_sw executable_offset;- /* Executable size for statistical purposes. */- sljit_uw executable_size;--#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)- sljit_s32 status_flags_state;-#endif--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- sljit_s32 args_size;- sljit_s32 locals_offset;- sljit_s32 scratches_offset;-#endif--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- sljit_s32 mode32;-#endif--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- /* Constant pool handling. */- sljit_uw *cpool;- sljit_u8 *cpool_unique;- sljit_uw cpool_diff;- sljit_uw cpool_fill;- /* Other members. */- /* Contains pointer, "ldr pc, [...]" pairs. */- sljit_uw patches;-#endif--#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;-#endif /* SLJIT_CONFIG_ARM_V5 || SLJIT_CONFIG_ARM_V7 */--#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)- sljit_uw args_size;-#endif--#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)- sljit_u32 imm;-#endif--#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)- sljit_s32 delay_slot;- sljit_s32 cache_arg;- sljit_sw cache_argw;-#endif--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- sljit_uw args_size;-#endif--#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- sljit_s32 delay_slot;- sljit_s32 cache_arg;- sljit_sw cache_argw;-#endif--#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)- /* Need to allocate register save area to make calls. */- sljit_s32 mode;-#endif--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- FILE* verbose;-#endif--#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;- /* Return value type set by entry functions. */- sljit_s32 last_return;- /* Local size passed to entry functions. */- sljit_s32 logical_local_size;-#endif--#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \- || (defined SLJIT_DEBUG && SLJIT_DEBUG) \- || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)- /* Trust arguments when the API function is called. */- sljit_s32 skip_checks;-#endif-};--/* --------------------------------------------------------------------- */-/* Main functions */-/* --------------------------------------------------------------------- */--/* Creates an sljit compiler. The allocator_data is required by some- custom memory managers. This pointer is passed to SLJIT_MALLOC- and SLJIT_FREE macros. Most allocators (including the default- one) ignores this value, and it is recommended to pass NULL- as a dummy value for allocator_data. The exec_allocator_data- has the same purpose but this one is passed to SLJIT_MALLOC_EXEC /- SLJIT_MALLOC_FREE functions.-- Returns NULL if failed. */-SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data);--/* Frees everything except the compiled machine code. */-SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler);--/* Returns the current error code. If an error is occurred, future sljit- calls which uses the same compiler argument returns early with the same- 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_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- the compiler behaves as if the allocation failure happened- during an sljit function call. This can greatly simplify error- checking, since only the compiler status needs to be checked- after the compilation. */-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler);--/*- Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit,- and <= 128 bytes on 64 bit architectures. The memory area is owned by the- compiler, and freed by sljit_free_compiler. The returned pointer is- sizeof(sljit_sw) aligned. Excellent for allocating small blocks during- the compiling, and no need to worry about freeing them. The size is- enough to contain at most 16 pointers. If the size is outside of the range,- the function will return with NULL. However, this return value does not- 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_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, void *exec_allocator_data);--/*- 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] Has zero register (setting a memory location to zero is efficient). */-#define SLJIT_HAS_ZERO_REGISTER 2-/* [Emulated] Count leading zero is supported. */-#define SLJIT_HAS_CLZ 3-/* [Emulated] Conditional move is supported. */-#define SLJIT_HAS_CMOV 4-/* [Emulated] Conditional move is supported. */-#define SLJIT_HAS_PREFETCH 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. */--/*- The executable code is a function from the viewpoint of the C- language. The function calls must obey to the ABI (Application- Binary Interface) of the platform, which specify the purpose of- machine registers and stack handling among other things. The- sljit_emit_enter function emits the necessary instructions for- setting up a new context for the executable code and moves function- arguments to the saved registers. Furthermore the options argument- can be used to pass configuration options to the compiler. The- available options are listed before sljit_emit_enter.-- The function argument list is the combination of SLJIT_ARGx- (SLJIT_DEF_ARG1) macros. Currently maximum 4 arguments are- supported. The first integer argument is loaded into SLJIT_S0,- the second one is loaded into SLJIT_S1, and so on. Similarly,- the first floating point argument is loaded into SLJIT_FR0,- the second one is loaded into SLJIT_FR1, and so on. Furthermore- the register set used by the function must be declared as well.- The number of scratch and saved registers used by the function- must be passed to sljit_emit_enter. Only R registers between R0- and "scratches" argument can be used later. E.g. if "scratches"- is set to 2, the scratch register set will be limited to SLJIT_R0- and SLJIT_R1. The S registers and the floating point registers- ("fscratches" and "fsaveds") are specified in a similar manner.- The sljit_emit_enter is also capable of allocating a stack space- for local variables. The "local_size" argument contains the size- in bytes of this local area and its staring address is stored- in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and- SLJIT_SP + local_size (exclusive) can be modified freely until- the function returns. The stack space is not initialized.-- Note: the following conditions must met:- 0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS- 0 <= saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS- scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS- 0 <= fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS- 0 <= fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS- fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS-- Note: the compiler can use saved registers as scratch registers,- but the opposite is not supported-- Note: every call of sljit_emit_enter and sljit_set_context- overwrites the previous context.-*/--/* The compiled function uses cdecl calling- * convention instead of SLJIT_FUNC. */-#define SLJIT_ENTER_CDECL 0x00000001--/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */-#define SLJIT_MAX_LOCAL_SIZE 65536--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size);--/* 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- functions (such as sljit_emit_return) requres this context to be able to generate- the appropriate code. However, some code fragments (like inline cache) may have- no normal entry point so their context is unknown for the compiler. Their context- can be provided to the compiler by the sljit_set_context function.-- Note: every call of sljit_emit_enter and sljit_set_context overwrites- the previous context. */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size);--/* Return from machine code. The sljit_emit_return_void function does not return with- any value. The sljit_emit_return function returns with a single value which stores- the result of a data move instruction. The instruction is specified by the op- argument, and must be between SLJIT_MOV and SLJIT_MOV_P (see sljit_emit_op1). */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler);--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw);--/* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL).- Both sljit_emit_fast_enter and SLJIT_FAST_RETURN operations preserve the- values of all registers and stack frame. The return address is stored in the- dst argument of sljit_emit_fast_enter, and this return address can be passed- to SLJIT_FAST_RETURN to continue the execution after the fast call.-- Fast calls are cheap operations (usually only a single call instruction is- emitted) but they do not preserve any registers. However the callee function- can freely use / update any registers and stack values which can be- efficiently exploited by various optimizations. Registers can be saved- manually by the callee function if needed.-- Although returning to different address by SLJIT_FAST_RETURN is possible,- this address usually cannot be predicted by the return address predictor of- modern CPUs which may reduce performance. Furthermore certain security- enhancement technologies such as Intel Control-flow Enforcement Technology- (CET) may disallow returning to a different address.-- Flags: - (does not modify flags). */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);--/*- Source and destination operands for arithmetical instructions- imm - a simple immediate value (cannot be used as a destination)- reg - any of the registers (immediate argument must be 0)- [imm] - absolute immediate memory address- [reg+imm] - indirect memory address- [reg+(reg<<imm)] - indirect indexed memory address (shift must be between 0 and 3)- useful for (byte, half, int, sljit_sw) array access- (fully supported by both x86 and ARM architectures, and cheap operation on others)-*/--/*- IMPORTANT NOTE: memory access MUST be naturally aligned unless- SLJIT_UNALIGNED macro is defined and its value is 1.-- length | alignment- ---------+------------ byte | 1 byte (any physical_address is accepted)- half | 2 byte (physical_address & 0x1 == 0)- int | 4 byte (physical_address & 0x3 == 0)- word | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1- | 8 byte if SLJIT_64BIT_ARCHITECTURE is defined and its value is 1- pointer | size of sljit_p type (4 byte on 32 bit machines, 4 or 8 byte- | on 64 bit machines)-- Note: Different architectures have different addressing limitations.- A single instruction is enough for the following addressing- modes. Other adrressing modes are emulated by instruction- sequences. This information could help to improve those code- generators which focuses only a few architectures.-- x86: [reg+imm], -2^32+1 <= imm <= 2^32-1 (full address space on x86-32)- [reg+(reg<<imm)] is supported- [imm], -2^32+1 <= imm <= 2^32-1 is supported- Write-back is not supported- arm: [reg+imm], -4095 <= imm <= 4095 or -255 <= imm <= 255 for signed- bytes, any halfs or floating point values)- [reg+(reg<<imm)] is supported- Write-back is supported- arm-t2: [reg+imm], -255 <= imm <= 4095- [reg+(reg<<imm)] is supported- Write back is supported only for [reg+imm], where -255 <= imm <= 255- arm64: [reg+imm], -256 <= imm <= 255, 0 <= aligned imm <= 4095 * alignment- [reg+(reg<<imm)] is supported- Write back is supported only for [reg+imm], where -256 <= imm <= 255- ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit- signed load on 64 bit requires immediates divisible by 4.- [reg+imm] is not supported for signed 8 bit values.- [reg+reg] is supported- Write-back is supported except for one instruction: 32 bit signed- load with [reg+imm] addressing mode on 64 bit.- mips: [reg+imm], -65536 <= imm <= 65535- sparc: [reg+imm], -4096 <= imm <= 4095- [reg+reg] is supported- s390x: [reg+imm], -2^19 <= imm < 2^19- [reg+reg] is supported- Write-back is not supported-*/--/* Macros for specifying operand types. */-#define SLJIT_MEM 0x80-#define SLJIT_MEM0() (SLJIT_MEM)-#define SLJIT_MEM1(r1) (SLJIT_MEM | (r1))-#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 8))-#define SLJIT_IMM 0x40--/* Sets 32 bit operation mode 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 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 converted to a 64 bit value by SLJIT_MOV_S32- (sign extension) or SLJIT_MOV_U32 (zero extension).-- As for floating-point operations, this option sets 32 bit single- precision mode. Similar to the integer operations, all register arguments- must be the result of those operations where this option was also set.-- 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_32) */-#define SLJIT_32 0x100--/* Many CPUs (x86, ARM, PPC) have status flags which can be set according- to the result of an operation. Other CPUs (MIPS) do 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 has 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 need 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- the instruction does not set flags (See: SLJIT_KEEP_FLAGS).- - flag combinations: '|' means 'logical or'. */--/* Starting index of opcodes for sljit_emit_op0. */-#define SLJIT_OP0_BASE 0--/* 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: - (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_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_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_DIVMOD_UW (SLJIT_OP0_BASE + 4)-#define SLJIT_DIVMOD_U32 (SLJIT_DIVMOD_UW | SLJIT_32)-/* 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_DIVMOD_SW (SLJIT_OP0_BASE + 5)-#define SLJIT_DIVMOD_S32 (SLJIT_DIVMOD_SW | SLJIT_32)-/* 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. */-#define SLJIT_DIV_UW (SLJIT_OP0_BASE + 6)-#define SLJIT_DIV_U32 (SLJIT_DIV_UW | SLJIT_32)-/* 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. */-#define SLJIT_DIV_SW (SLJIT_OP0_BASE + 7)-#define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_32)-/* Flags: - (does not modify flags)- ENDBR32 instruction for x86-32 and ENDBR64 instruction for x86-64- when Intel Control-flow Enforcement Technology (CET) is enabled.- No instruction for other architectures. */-#define SLJIT_ENDBR (SLJIT_OP0_BASE + 8)-/* Flags: - (may destroy flags)- Skip stack frames before return. */-#define SLJIT_SKIP_FRAMES_BEFORE_RETURN (SLJIT_OP0_BASE + 9)--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--/* The MOV instruction transfers 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-*/--/* Flags: - (does not modify flags) */-#define SLJIT_MOV (SLJIT_OP1_BASE + 0)-/* Flags: - (does not modify flags) */-#define SLJIT_MOV_U8 (SLJIT_OP1_BASE + 1)-#define SLJIT_MOV32_U8 (SLJIT_MOV_U8 | SLJIT_32)-/* Flags: - (does not modify flags) */-#define SLJIT_MOV_S8 (SLJIT_OP1_BASE + 2)-#define SLJIT_MOV32_S8 (SLJIT_MOV_S8 | SLJIT_32)-/* Flags: - (does not modify flags) */-#define SLJIT_MOV_U16 (SLJIT_OP1_BASE + 3)-#define SLJIT_MOV32_U16 (SLJIT_MOV_U16 | SLJIT_32)-/* Flags: - (does not modify flags) */-#define SLJIT_MOV_S16 (SLJIT_OP1_BASE + 4)-#define SLJIT_MOV32_S16 (SLJIT_MOV_S16 | SLJIT_32)-/* 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_OP1_BASE + 7)-/* Flags: - (does not modify flags)- Note: load a pointer sized data, useful on x32 (a 32 bit mode on x86-64- where all x64 features are available, e.g. 16 register) or similar- compiling modes */-#define SLJIT_MOV_P (SLJIT_OP1_BASE + 8)-/* Flags: Z- Note: immediate source argument is not supported */-#define SLJIT_NOT (SLJIT_OP1_BASE + 9)-#define SLJIT_NOT32 (SLJIT_NOT | SLJIT_32)-/* Count leading zeroes- Flags: - (may destroy flags)- Note: immediate source argument is not supported */-#define SLJIT_CLZ (SLJIT_OP1_BASE + 10)-#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_32)--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: Z | OVERFLOW | CARRY */-#define SLJIT_ADD (SLJIT_OP2_BASE + 0)-#define SLJIT_ADD32 (SLJIT_ADD | SLJIT_32)-/* Flags: CARRY */-#define SLJIT_ADDC (SLJIT_OP2_BASE + 1)-#define SLJIT_ADDC32 (SLJIT_ADDC | SLJIT_32)-/* 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_SUB32 (SLJIT_SUB | SLJIT_32)-/* Flags: CARRY */-#define SLJIT_SUBC (SLJIT_OP2_BASE + 3)-#define SLJIT_SUBC32 (SLJIT_SUBC | SLJIT_32)-/* Note: integer mul- Flags: OVERFLOW */-#define SLJIT_MUL (SLJIT_OP2_BASE + 4)-#define SLJIT_MUL32 (SLJIT_MUL | SLJIT_32)-/* Flags: Z */-#define SLJIT_AND (SLJIT_OP2_BASE + 5)-#define SLJIT_AND32 (SLJIT_AND | SLJIT_32)-/* Flags: Z */-#define SLJIT_OR (SLJIT_OP2_BASE + 6)-#define SLJIT_OR32 (SLJIT_OR | SLJIT_32)-/* Flags: Z */-#define SLJIT_XOR (SLJIT_OP2_BASE + 7)-#define SLJIT_XOR32 (SLJIT_XOR | SLJIT_32)-/* 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_SHL32 (SLJIT_SHL | SLJIT_32)-/* 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_LSHR32 (SLJIT_LSHR | SLJIT_32)-/* 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_ASHR32 (SLJIT_ASHR | SLJIT_32)--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);--/* The sljit_emit_op2u function is the same as sljit_emit_op2 except the result is discarded. */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w);--/* Starting index of opcodes for sljit_emit_op2. */-#define SLJIT_OP_SRC_BASE 128--/* Note: src cannot be an immedate value- Flags: - (does not modify flags) */-#define SLJIT_FAST_RETURN (SLJIT_OP_SRC_BASE + 0)-/* Skip stack frames before fast return.- Note: src cannot be an immedate value- Flags: may destroy flags. */-#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN (SLJIT_OP_SRC_BASE + 1)-/* Prefetch value into the level 1 data cache- Note: if the target CPU does not support data prefetch,- no instructions are emitted.- Note: this instruction never fails, even if the memory address is invalid.- Flags: - (does not modify flags) */-#define SLJIT_PREFETCH_L1 (SLJIT_OP_SRC_BASE + 2)-/* Prefetch value into the level 2 data cache- Note: same as SLJIT_PREFETCH_L1 if the target CPU- does not support this instruction form.- Note: this instruction never fails, even if the memory address is invalid.- Flags: - (does not modify flags) */-#define SLJIT_PREFETCH_L2 (SLJIT_OP_SRC_BASE + 3)-/* Prefetch value into the level 3 data cache- Note: same as SLJIT_PREFETCH_L2 if the target CPU- does not support this instruction form.- Note: this instruction never fails, even if the memory address is invalid.- Flags: - (does not modify flags) */-#define SLJIT_PREFETCH_L3 (SLJIT_OP_SRC_BASE + 4)-/* Prefetch a value which is only used once (and can be discarded afterwards)- Note: same as SLJIT_PREFETCH_L1 if the target CPU- does not support this instruction form.- Note: this instruction never fails, even if the memory address is invalid.- Flags: - (does not modify flags) */-#define SLJIT_PREFETCH_ONCE (SLJIT_OP_SRC_BASE + 5)--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw);--/* Starting index of opcodes for sljit_emit_fop1. */-#define SLJIT_FOP1_BASE 160--/* Flags: - (does not modify flags) */-#define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0)-#define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_32)-/* 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: - (may destroy flags) */-#define SLJIT_CONV_F64_FROM_F32 (SLJIT_FOP1_BASE + 1)-#define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_32)-/* Flags: - (may destroy flags) */-#define SLJIT_CONV_SW_FROM_F64 (SLJIT_FOP1_BASE + 2)-#define SLJIT_CONV_SW_FROM_F32 (SLJIT_CONV_SW_FROM_F64 | SLJIT_32)-/* Flags: - (may destroy flags) */-#define SLJIT_CONV_S32_FROM_F64 (SLJIT_FOP1_BASE + 3)-#define SLJIT_CONV_S32_FROM_F32 (SLJIT_CONV_S32_FROM_F64 | SLJIT_32)-/* Flags: - (may destroy flags) */-#define SLJIT_CONV_F64_FROM_SW (SLJIT_FOP1_BASE + 4)-#define SLJIT_CONV_F32_FROM_SW (SLJIT_CONV_F64_FROM_SW | SLJIT_32)-/* Flags: - (may destroy flags) */-#define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5)-#define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_32)-/* Note: dst is the left and src is the right operand for SLJIT_CMPD.- 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_32)-/* Flags: - (may destroy flags) */-#define SLJIT_NEG_F64 (SLJIT_FOP1_BASE + 7)-#define SLJIT_NEG_F32 (SLJIT_NEG_F64 | SLJIT_32)-/* Flags: - (may destroy flags) */-#define SLJIT_ABS_F64 (SLJIT_FOP1_BASE + 8)-#define SLJIT_ABS_F32 (SLJIT_ABS_F64 | SLJIT_32)--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 192--/* Flags: - (may destroy flags) */-#define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0)-#define SLJIT_ADD_F32 (SLJIT_ADD_F64 | SLJIT_32)-/* Flags: - (may destroy flags) */-#define SLJIT_SUB_F64 (SLJIT_FOP2_BASE + 1)-#define SLJIT_SUB_F32 (SLJIT_SUB_F64 | SLJIT_32)-/* Flags: - (may destroy flags) */-#define SLJIT_MUL_F64 (SLJIT_FOP2_BASE + 2)-#define SLJIT_MUL_F32 (SLJIT_MUL_F64 | SLJIT_32)-/* Flags: - (may destroy flags) */-#define SLJIT_DIV_F64 (SLJIT_FOP2_BASE + 3)-#define SLJIT_DIV_F32 (SLJIT_DIV_F64 | SLJIT_32)--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. */--SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler);--/* Invert (negate) conditional type: xor (^) with 0x1 */--/* Integer comparison types. */-#define SLJIT_EQUAL 0-#define SLJIT_ZERO SLJIT_EQUAL-#define SLJIT_NOT_EQUAL 1-#define SLJIT_NOT_ZERO SLJIT_NOT_EQUAL--#define SLJIT_LESS 2-#define SLJIT_SET_LESS SLJIT_SET(SLJIT_LESS)-#define SLJIT_GREATER_EQUAL 3-#define SLJIT_SET_GREATER_EQUAL SLJIT_SET(SLJIT_GREATER_EQUAL)-#define SLJIT_GREATER 4-#define SLJIT_SET_GREATER SLJIT_SET(SLJIT_GREATER)-#define SLJIT_LESS_EQUAL 5-#define SLJIT_SET_LESS_EQUAL SLJIT_SET(SLJIT_LESS_EQUAL)-#define SLJIT_SIG_LESS 6-#define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS)-#define SLJIT_SIG_GREATER_EQUAL 7-#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_GREATER_EQUAL)-#define SLJIT_SIG_GREATER 8-#define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER)-#define SLJIT_SIG_LESS_EQUAL 9-#define SLJIT_SET_SIG_LESS_EQUAL SLJIT_SET(SLJIT_SIG_LESS_EQUAL)--#define SLJIT_OVERFLOW 10-#define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW)-#define SLJIT_NOT_OVERFLOW 11--/* Unlike other flags, sljit_emit_jump may destroy this flag. */-#define SLJIT_CARRY 12-#define SLJIT_SET_CARRY SLJIT_SET(SLJIT_CARRY)-#define SLJIT_NOT_CARRY 13--/* Floating point comparison types. */-#define SLJIT_EQUAL_F64 14-#define SLJIT_EQUAL_F32 (SLJIT_EQUAL_F64 | SLJIT_32)-#define SLJIT_SET_EQUAL_F SLJIT_SET(SLJIT_EQUAL_F64)-#define SLJIT_NOT_EQUAL_F64 15-#define SLJIT_NOT_EQUAL_F32 (SLJIT_NOT_EQUAL_F64 | SLJIT_32)-#define SLJIT_SET_NOT_EQUAL_F SLJIT_SET(SLJIT_NOT_EQUAL_F64)-#define SLJIT_LESS_F64 16-#define SLJIT_LESS_F32 (SLJIT_LESS_F64 | SLJIT_32)-#define SLJIT_SET_LESS_F SLJIT_SET(SLJIT_LESS_F64)-#define SLJIT_GREATER_EQUAL_F64 17-#define SLJIT_GREATER_EQUAL_F32 (SLJIT_GREATER_EQUAL_F64 | SLJIT_32)-#define SLJIT_SET_GREATER_EQUAL_F SLJIT_SET(SLJIT_GREATER_EQUAL_F64)-#define SLJIT_GREATER_F64 18-#define SLJIT_GREATER_F32 (SLJIT_GREATER_F64 | SLJIT_32)-#define SLJIT_SET_GREATER_F SLJIT_SET(SLJIT_GREATER_F64)-#define SLJIT_LESS_EQUAL_F64 19-#define SLJIT_LESS_EQUAL_F32 (SLJIT_LESS_EQUAL_F64 | SLJIT_32)-#define SLJIT_SET_LESS_EQUAL_F SLJIT_SET(SLJIT_LESS_EQUAL_F64)-#define SLJIT_UNORDERED_F64 20-#define SLJIT_UNORDERED_F32 (SLJIT_UNORDERED_F64 | SLJIT_32)-#define SLJIT_SET_UNORDERED_F SLJIT_SET(SLJIT_UNORDERED_F64)-#define SLJIT_ORDERED_F64 21-#define SLJIT_ORDERED_F32 (SLJIT_ORDERED_F64 | SLJIT_32)-#define SLJIT_SET_ORDERED_F SLJIT_SET(SLJIT_ORDERED_F64)--/* Unconditional jump types. */-#define SLJIT_JUMP 22- /* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */-#define SLJIT_FAST_CALL 23- /* Called function must be declared with the SLJIT_FUNC attribute. */-#define SLJIT_CALL 24- /* Called function must be declared with cdecl attribute.- This is the default attribute for C functions. */-#define SLJIT_CALL_CDECL 25--/* The target can be changed during runtime (see: sljit_set_jump_addr). */-#define SLJIT_REWRITABLE_JUMP 0x1000-/* When this flag is passed, the execution of the current function ends and- the called function returns to the caller of the current function. The- stack usage is reduced before the call, but it is not necessarily reduced- to zero. In the latter case the compiler needs to allocate space for some- arguments and the return register must be kept as well.-- This feature is highly experimental and not supported on SPARC platform- at the moment. */-#define SLJIT_CALL_RETURN 0x2000--/* Emit a jump instruction. The destination is not set, only the type of the jump.- type must be between SLJIT_EQUAL and SLJIT_FAST_CALL- type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP-- Flags: does not modify flags. */-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type);--/* Emit a C compiler (ABI) compatible function call.- type must be SLJIT_CALL or SLJIT_CALL_CDECL- type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and SLJIT_CALL_RETURN- arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros-- Flags: destroy all flags. */-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types);--/* Basic arithmetic comparison. In most architectures it is implemented as- an compare operation followed by a sljit_emit_jump. However some- architectures (i.e: ARM64 or MIPS) may employ special optimizations here.- 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: 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_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_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);-/* Set the destination address of the jump to this label. */-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);--/* Emit an indirect jump or fast call.- Direct form: set src to SLJIT_IMM() and srcw to the address- Indirect form: any other valid addressing mode- type must be between SLJIT_JUMP and SLJIT_FAST_CALL-- Flags: does not modify flags. */-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw);--/* Emit a C compiler (ABI) compatible function call.- Direct form: set src to SLJIT_IMM() and srcw to the address- Indirect form: any other valid addressing mode- type must be SLJIT_CALL or SLJIT_CALL_CDECL- type can be combined (or'ed) with SLJIT_CALL_RETURN- arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros-- Flags: destroy all flags. */-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, 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_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_MOV32:- Set dst to the value represented by the type (0 or 1).- Flags: - (does not modify flags)- If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR- 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 access.-- type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64- dst_reg must be a valid register and it can be combined- with SLJIT_32 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);--/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */--/* When SLJIT_MEM_SUPP is passed, no instructions are emitted.- Instead the function returns with SLJIT_SUCCESS if the instruction- form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag- allows runtime checking of available instruction forms. */-#define SLJIT_MEM_SUPP 0x0200-/* Memory load operation. This is the default. */-#define SLJIT_MEM_LOAD 0x0000-/* Memory store operation. */-#define SLJIT_MEM_STORE 0x0400-/* Base register is updated before the memory access. */-#define SLJIT_MEM_PRE 0x0800-/* Base register is updated after the memory access. */-#define SLJIT_MEM_POST 0x1000--/* Emit a single memory load or store with update instruction. When the- requested instruction form is not supported by the CPU, it returns- with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This- allows specializing tight loops based on the supported instruction- forms (see SLJIT_MEM_SUPP flag).-- type must be between SLJIT_MOV and SLJIT_MOV_P and can be- combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE- or SLJIT_MEM_POST must be specified.- reg is the source or destination register, and must be- different from the base register of the mem operand- mem must be a SLJIT_MEM1() or SLJIT_MEM2() operand-- Flags: - (does not modify flags) */-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 reg,- sljit_s32 mem, sljit_sw memw);--/* Same as sljit_emit_mem except the followings:-- type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be- combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE- or SLJIT_MEM_POST must be specified.- freg is the source or destination floating point register */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 freg,- sljit_s32 mem, sljit_sw memw);--/* Copies the base address of SLJIT_SP + offset to dst. The offset can be- anything to negate the effect of relative addressing. For example if an- array of sljit_sw values is stored on the stack from offset 0x40, and R0- contains the offset of an array item plus 0x120, this item can be- overwritten by two SLJIT instructions:-- sljit_get_local_base(compiler, SLJIT_R1, 0, 0x40 - 0x120);- sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_IMM, 0x5);-- 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);--/* Store a value that can be changed runtime (see: sljit_get_const_addr / sljit_set_const)- Flags: - (does not modify flags) */-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value);--/* Store the value of a label (see: sljit_set_put_label)- Flags: - (does not modify flags) */-SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);--/* Set the value stored by put_label to this label. */-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label);--/* After the code generation the address for label, jump and const instructions- are computed. Since these structures are freed by sljit_free_compiler, the- addresses must be preserved by the user program elsewere. */-static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; }-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 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 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 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)--#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)--/* The sljit_stack structure and its manipulation functions provides- an implementation for a top-down stack. The stack top is stored- in the end field of the sljit_stack structure and the stack goes- down to the min_start field, so the memory region reserved for- this stack is between min_start (inclusive) and end (exclusive)- fields. However the application can only use the region between- start (inclusive) and end (exclusive) fields. The sljit_stack_resize- function can be used to extend this region up to min_start.-- This feature uses the "address space reserve" feature of modern- operating systems. Instead of allocating a large memory block- applications can allocate a small memory region and extend it- later without moving the content of the memory area. Therefore- after a successful resize by sljit_stack_resize all pointers into- this region are still valid.-- Note:- this structure may not be supported by all operating systems.- end and max_limit fields are aligned to PAGE_SIZE bytes (usually- 4 Kbyte or more).- stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more. */--struct sljit_stack {- /* User data, anything can be stored here.- Initialized to the same value as the end field. */- sljit_u8 *top;-/* These members are read only. */- /* End address of the stack */- sljit_u8 *end;- /* Current start address of the stack. */- sljit_u8 *start;- /* Lowest start address of the stack. */- sljit_u8 *min_start;-};--/* Allocates a new stack. Returns NULL if unsuccessful.- Note: see sljit_create_compiler for the explanation of allocator_data. */-SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data);-SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data);--/* Can be used to increase (extend) or decrease (shrink) the stack- memory area. Returns with new_start if successful and NULL otherwise.- It always fails if new_start is less than min_start or greater or equal- than end fields. The fields of the stack are not changed if the returned- value is NULL (the current memory content is never lost). */-SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start);--#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */--#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)--/* Get the entry address of a given function (signed, unsigned result). */-#define SLJIT_FUNC_ADDR(func_name) ((sljit_sw)func_name)-#define SLJIT_FUNC_UADDR(func_name) ((sljit_uw)func_name)--#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */--/* All JIT related code should be placed in the same context (library, binary, etc.). */--/* Get the entry address of a given function (signed, unsigned result). */-#define SLJIT_FUNC_ADDR(func_name) (*(sljit_sw*)(void*)func_name)-#define SLJIT_FUNC_UADDR(func_name) (*(sljit_uw*)(void*)func_name)--/* For powerpc64, the function pointers point to a context descriptor. */-struct sljit_function_context {- sljit_uw addr;- sljit_uw r2;- sljit_uw r11;-};--/* Fill the context arguments using the addr and the function.- If func_ptr is NULL, it will not be set to the address of context- If addr is NULL, the function address also comes from the func pointer. */-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func);--#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 */-/* --------------------------------------------------------------------- */--/* The following function is a helper function for sljit_emit_op_custom.- It returns with the real machine register index ( >=0 ) of any SLJIT_R,- SLJIT_S and SLJIT_SP registers.-- Note: it returns with -1 for virtual registers (only on x86-32). */--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_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.- The size parameter must match to the instruction size of the target- architecture:-- x86: 0 < size <= 15. The instruction argument can be byte aligned.- Thumb2: if size == 2, the instruction argument must be 2 byte aligned.- 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_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size);--/* Flags were set by a 32 bit operation. */-#define SLJIT_CURRENT_FLAGS_32 SLJIT_32--/* Flags were set by an ADD or ADDC operations. */-#define SLJIT_CURRENT_FLAGS_ADD 0x01-/* Flags were set by a SUB, SUBC, or NEG operation. */-#define SLJIT_CURRENT_FLAGS_SUB 0x02--/* Flags were set by sljit_emit_op2u with SLJIT_SUB opcode.- Must be combined with SLJIT_CURRENT_FLAGS_SUB. */-#define SLJIT_CURRENT_FLAGS_COMPARE 0x04--/* Define the currently available CPU status flags. It is usually used after- an sljit_emit_label or sljit_emit_op_custom operations to define which CPU- status flags are available.-- The current_flags must be a valid combination of SLJIT_SET_* and- SLJIT_CURRENT_FLAGS_* constants. */--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,- sljit_s32 current_flags);+ a code fragment, which is compiled later, as long as the compiling+ context is the same. See sljit_emit_enter for more details.+ - Supports self modifying code: target of any jump and call+ instructions and some constant values can be dynamically modified+ during runtime. See SLJIT_REWRITABLE_JUMP.+ - although it is not suggested to do it frequently+ - can be used for inline caching: save an important value once+ in the instruction stream+ - A fixed stack space can be allocated for local variables+ - The compiler is thread-safe+ - The compiler is highly configurable through preprocessor macros.+ You can disable unneeded features (multithreading in single+ threaded applications), and you can use your own system functions+ (including memory allocators). See sljitConfig.h.+ Disadvantages:+ - The compiler is more like a platform independent assembler, so+ there is no built-in variable management. Registers and stack must+ be managed manually (the name of the compiler refers to this).+ In practice:+ - This approach is very effective for interpreters+ - One of the saved registers typically points to a stack interface+ - It can jump to any exception handler anytime (even if it belongs+ to another function)+ - Hot paths can be modified during runtime reflecting the changes+ of the fastest execution path of the dynamic language+ - SLJIT supports complex memory addressing modes+ - mainly position and context independent code (except some cases)++ For valgrind users:+ - pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code"+*/++#if (defined SLJIT_HAVE_CONFIG_PRE && SLJIT_HAVE_CONFIG_PRE)+#include "sljitConfigPre.h"+#endif /* SLJIT_HAVE_CONFIG_PRE */++#include "sljitConfigCPU.h"+#include "sljitConfig.h"++/* The following header file defines useful macros for fine tuning+SLJIT based code generators. They are listed in the beginning+of sljitConfigInternal.h */++#include "sljitConfigInternal.h"++#if (defined SLJIT_HAVE_CONFIG_POST && SLJIT_HAVE_CONFIG_POST)+#include "sljitConfigPost.h"+#endif /* SLJIT_HAVE_CONFIG_POST */++#ifdef __cplusplus+extern "C" {+#endif++/* Version numbers. */+#define SLJIT_MAJOR_VERSION 0+#define SLJIT_MINOR_VERSION 95++/* --------------------------------------------------------------------- */+/* Error codes */+/* --------------------------------------------------------------------- */++/* Indicates no error. */+#define SLJIT_SUCCESS 0+/* After the call of sljit_generate_code(), the error code of the compiler+ is set to this value to avoid further code generation.+ The complier should be freed after sljit_generate_code(). */+#define SLJIT_ERR_COMPILED 1+/* Cannot allocate non-executable memory. */+#define SLJIT_ERR_ALLOC_FAILED 2+/* Cannot allocate executable memory.+ Only sljit_generate_code() returns with this error code. */+#define SLJIT_ERR_EX_ALLOC_FAILED 3+/* Unsupported instruction form. */+#define SLJIT_ERR_UNSUPPORTED 4+/* An invalid argument is passed to any SLJIT function. */+#define SLJIT_ERR_BAD_ARGUMENT 5++/* --------------------------------------------------------------------- */+/* Registers */+/* --------------------------------------------------------------------- */++/*+ Scratch (R) registers: registers which may not preserve their values+ across function calls.++ Saved (S) registers: registers which preserve their values across+ function calls.++ The scratch and saved register sets overlap. The last scratch register+ is the first saved register, the one before the last is the second saved+ register, and so on.++ For example, in an architecture with only five registers (A-E), if two+ are scratch and three saved registers, they will be defined as follows:++ A | R0 | | R0 always represent scratch register A+ B | R1 | | R1 always represent scratch register B+ C | [R2] | S2 | R2 and S2 represent the same physical register C+ D | [R3] | S1 | R3 and S1 represent the same physical register D+ E | [R4] | S0 | R4 and S0 represent the same physical register E++ Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS will be 2 and+ SLJIT_NUMBER_OF_SAVED_REGISTERS will be 3.++ Note: For 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: saved registers can+ be used as extra scratch registers. For example, building in the+ previous example, four registers can be specified as scratch registers+ and the fifth one as saved register, allowing any user code which requires+ four scratch registers to run unmodified. The SLJIT compiler automatically+ saves the content of the two extra scratch register on the stack. Scratch+ registers can also be preserved by saving their value on the stack but+ that needs to be done manually.++ Note: To emphasize that registers assigned to R2-R4 are saved+ registers, they are enclosed by square brackets.++ Note: sljit_emit_enter and sljit_set_context define whether a register+ is S or R register. E.g: if in the previous example 3 scratches and+ 1 saved are mapped by sljit_emit_enter, the allowed register set+ will be: R0-R2 and S0. Although S2 is mapped to the same register+ than R2, it is not available in that configuration. Furthermore+ the S1 register cannot be used at all.+*/++/* Scratch registers. */+#define SLJIT_R0 1+#define SLJIT_R1 2+#define SLJIT_R2 3+/* Note: on x86-32, R3 - R6 (same as S3 - S6) are emulated (they+ are allocated on the stack). These registers are called virtual+ and cannot be used for memory addressing (cannot be part of+ any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such+ limitation on other CPUs. See sljit_get_register_index(). */+#define SLJIT_R3 4+#define SLJIT_R4 5+#define SLJIT_R5 6+#define SLJIT_R6 7+#define SLJIT_R7 8+#define SLJIT_R8 9+#define SLJIT_R9 10+/* All R registers provided by the architecture can be accessed by SLJIT_R(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_REGISTERS. */+#define SLJIT_R(i) (1 + (i))++/* Saved registers. */+#define SLJIT_S0 (SLJIT_NUMBER_OF_REGISTERS)+#define SLJIT_S1 (SLJIT_NUMBER_OF_REGISTERS - 1)+#define SLJIT_S2 (SLJIT_NUMBER_OF_REGISTERS - 2)+/* Note: on x86-32, S3 - S6 (same as R3 - R6) are emulated (they+ are allocated on the stack). These registers are called virtual+ and cannot be used for memory addressing (cannot be part of+ any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such+ limitation on other CPUs. See sljit_get_register_index(). */+#define SLJIT_S3 (SLJIT_NUMBER_OF_REGISTERS - 3)+#define SLJIT_S4 (SLJIT_NUMBER_OF_REGISTERS - 4)+#define SLJIT_S5 (SLJIT_NUMBER_OF_REGISTERS - 5)+#define SLJIT_S6 (SLJIT_NUMBER_OF_REGISTERS - 6)+#define SLJIT_S7 (SLJIT_NUMBER_OF_REGISTERS - 7)+#define SLJIT_S8 (SLJIT_NUMBER_OF_REGISTERS - 8)+#define SLJIT_S9 (SLJIT_NUMBER_OF_REGISTERS - 9)+/* All S registers provided by the architecture can be accessed by SLJIT_S(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_REGISTERS. */+#define SLJIT_S(i) (SLJIT_NUMBER_OF_REGISTERS - (i))++/* Registers >= SLJIT_FIRST_SAVED_REG are saved registers. */+#define SLJIT_FIRST_SAVED_REG (SLJIT_S0 - SLJIT_NUMBER_OF_SAVED_REGISTERS + 1)++/* The SLJIT_SP provides direct access to the linear stack space allocated by+ sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP).+ The immediate offset is extended by the relative stack offset automatically.+ sljit_get_local_base can be used to obtain the real address of a value. */+#define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1)++/* Return with machine word. */++#define SLJIT_RETURN_REG SLJIT_R0++/* --------------------------------------------------------------------- */+/* Floating point registers */+/* --------------------------------------------------------------------- */++/* Each floating point register can store a 32 or a 64 bit precision+ value. The FR and FS register sets overlap in the same way as R+ and S register sets. See above. */++/* Floating point scratch registers. */+#define SLJIT_FR0 1+#define SLJIT_FR1 2+#define SLJIT_FR2 3+#define SLJIT_FR3 4+#define SLJIT_FR4 5+#define SLJIT_FR5 6+#define SLJIT_FR6 7+#define SLJIT_FR7 8+#define SLJIT_FR8 9+#define SLJIT_FR9 10+/* All FR registers provided by the architecture can be accessed by SLJIT_FR(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_FLOAT_REGISTERS. */+#define SLJIT_FR(i) (1 + (i))++/* Floating point saved registers. */+#define SLJIT_FS0 (SLJIT_NUMBER_OF_FLOAT_REGISTERS)+#define SLJIT_FS1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1)+#define SLJIT_FS2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2)+#define SLJIT_FS3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 3)+#define SLJIT_FS4 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 4)+#define SLJIT_FS5 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 5)+#define SLJIT_FS6 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 6)+#define SLJIT_FS7 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 7)+#define SLJIT_FS8 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 8)+#define SLJIT_FS9 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 9)+/* All S registers provided by the architecture can be accessed by SLJIT_FS(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS. */+#define SLJIT_FS(i) (SLJIT_NUMBER_OF_FLOAT_REGISTERS - (i))++/* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */+#define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1)++/* Return with floating point arg. */++#define SLJIT_RETURN_FREG SLJIT_FR0++/* --------------------------------------------------------------------- */+/* Argument type definitions */+/* --------------------------------------------------------------------- */++/* The following argument type definitions are used by sljit_emit_enter,+ sljit_set_context, sljit_emit_call, and sljit_emit_icall functions.++ For sljit_emit_call and sljit_emit_icall, the first integer argument+ must be placed into SLJIT_R0, the second one into SLJIT_R1, and so on.+ Similarly the first floating point argument must be placed into SLJIT_FR0,+ the second one into SLJIT_FR1, and so on.++ For sljit_emit_enter, the integer arguments can be stored in scratch+ or saved registers. Scratch registers are identified by a _R suffix.++ If only saved registers are used, then the allocation mirrors what is+ done for the "call" functions but using saved registers, meaning that+ the first integer argument goes to SLJIT_S0, the second one goes into+ SLJIT_S1, and so on.++ If scratch registers are used, then the way the integer registers are+ allocated changes so that SLJIT_S0, SLJIT_S1, etc; will be assigned+ only for the arguments not using scratch registers, while SLJIT_R<n>+ will be used for the ones using scratch registers.++ Furthermore, the index (shown as "n" above) that will be used for the+ scratch register depends on how many previous integer registers+ (scratch or saved) were used already, starting with SLJIT_R0.+ Eventhough some indexes will be likely skipped, they still need to be+ accounted for in the scratches parameter of sljit_emit_enter. See below+ for some examples.++ The floating point arguments always use scratch registers (but not the+ _R suffix like the integer arguments) and must use SLJIT_FR0, SLJIT_FR1,+ just like in the "call" functions.++ Note: the mapping for scratch registers is part of the compiler context+ and therefore a new context after sljit_emit_call/sljit_emit_icall+ could remove access to some scratch registers that were used as+ arguments.++ Example function definition:+ sljit_f32 SLJIT_FUNC example_c_callback(void *arg_a,+ sljit_f64 arg_b, sljit_u32 arg_c, sljit_f32 arg_d);++ Argument type definition:+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_F32)+ | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_P, 1) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F64, 2)+ | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_32, 3) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F32, 4)++ Short form of argument type definition:+ SLJIT_ARGS4(F32, P, F64, 32, F32)++ Argument passing:+ arg_a must be placed in SLJIT_R0+ arg_b must be placed in SLJIT_FR0+ arg_c must be placed in SLJIT_R1+ arg_d must be placed in SLJIT_FR1++ Examples for argument processing by sljit_emit_enter:+ SLJIT_ARGS4V(P, 32_R, F32, W)+ Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_FR0, SLJIT_S1+ The type of the result is void.++ SLJIT_ARGS4(F32, W, W_R, W, W_R)+ Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_S1, SLJIT_R3+ The type of the result is sljit_f32.++ SLJIT_ARGS4(P, W, F32, P_R)+ Arguments are placed into: SLJIT_FR0, SLJIT_S0, SLJIT_FR1, SLJIT_R1+ The type of the result is pointer.++ Note: it is recommended to pass the scratch arguments first+ followed by the saved arguments:++ SLJIT_ARGS4(W, W_R, W_R, W, W)+ Arguments are placed into: SLJIT_R0, SLJIT_R1, SLJIT_S0, SLJIT_S1+ The type of the result is sljit_sw / sljit_uw.+*/++/* The following flag is only allowed for the integer arguments of+ sljit_emit_enter. When the flag is set, the integer argument is+ stored in a scratch register instead of a saved register. */+#define SLJIT_ARG_TYPE_SCRATCH_REG 0x8++/* No return value, only supported by SLJIT_ARG_RETURN. */+#define SLJIT_ARG_TYPE_RET_VOID 0+/* Machine word sized integer argument or result. */+#define SLJIT_ARG_TYPE_W 1+#define SLJIT_ARG_TYPE_W_R (SLJIT_ARG_TYPE_W | SLJIT_ARG_TYPE_SCRATCH_REG)+/* 32 bit integer argument or result. */+#define SLJIT_ARG_TYPE_32 2+#define SLJIT_ARG_TYPE_32_R (SLJIT_ARG_TYPE_32 | SLJIT_ARG_TYPE_SCRATCH_REG)+/* Pointer sized integer argument or result. */+#define SLJIT_ARG_TYPE_P 3+#define SLJIT_ARG_TYPE_P_R (SLJIT_ARG_TYPE_P | SLJIT_ARG_TYPE_SCRATCH_REG)+/* 64 bit floating point argument or result. */+#define SLJIT_ARG_TYPE_F64 4+/* 32 bit floating point argument or result. */+#define SLJIT_ARG_TYPE_F32 5++#define SLJIT_ARG_SHIFT 4+#define SLJIT_ARG_RETURN(type) (type)+#define SLJIT_ARG_VALUE(type, idx) ((type) << ((idx) * SLJIT_ARG_SHIFT))++/* Simplified argument list definitions.++ The following definition:+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_W) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F32, 1)++ can be shortened to:+ SLJIT_ARGS1(W, F32)++ Another example where no value is returned:+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_RET_VOID) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W_R, 1)++ can be shortened to:+ SLJIT_ARGS1V(W_R)+*/++#define SLJIT_ARG_TO_TYPE(type) SLJIT_ARG_TYPE_ ## type++#define SLJIT_ARGS0(ret) \+ SLJIT_ARG_RETURN(SLJIT_ARG_TO_TYPE(ret))+#define SLJIT_ARGS0V() \+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_RET_VOID)++#define SLJIT_ARGS1(ret, arg1) \+ (SLJIT_ARGS0(ret) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg1), 1))+#define SLJIT_ARGS1V(arg1) \+ (SLJIT_ARGS0V() | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg1), 1))++#define SLJIT_ARGS2(ret, arg1, arg2) \+ (SLJIT_ARGS1(ret, arg1) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg2), 2))+#define SLJIT_ARGS2V(arg1, arg2) \+ (SLJIT_ARGS1V(arg1) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg2), 2))++#define SLJIT_ARGS3(ret, arg1, arg2, arg3) \+ (SLJIT_ARGS2(ret, arg1, arg2) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg3), 3))+#define SLJIT_ARGS3V(arg1, arg2, arg3) \+ (SLJIT_ARGS2V(arg1, arg2) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg3), 3))++#define SLJIT_ARGS4(ret, arg1, arg2, arg3, arg4) \+ (SLJIT_ARGS3(ret, arg1, arg2, arg3) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg4), 4))+#define SLJIT_ARGS4V(arg1, arg2, arg3, arg4) \+ (SLJIT_ARGS3V(arg1, arg2, arg3) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg4), 4))++/* --------------------------------------------------------------------- */+/* Main structures and functions */+/* --------------------------------------------------------------------- */++/*+ The following structures are private, and can be changed in the+ future. Keeping them here allows code inlining.+*/++struct sljit_memory_fragment {+ struct sljit_memory_fragment *next;+ sljit_uw used_size;+ /* Must be aligned to sljit_sw. */+ sljit_u8 memory[1];+};++struct sljit_label {+ struct sljit_label *next;+ union {+ sljit_uw index;+ sljit_uw addr;+ } u;+ /* The maximum size difference. */+ sljit_uw size;+};++struct sljit_jump {+ struct sljit_jump *next;+ sljit_uw addr;+ /* Architecture dependent flags. */+ sljit_uw flags;+ union {+ sljit_uw target;+ struct sljit_label *label;+ } u;+};++struct sljit_const {+ struct sljit_const *next;+ sljit_uw addr;+};++struct sljit_generate_code_buffer {+ void *buffer;+ sljit_uw size;+ sljit_sw executable_offset;+};++struct sljit_compiler {+ sljit_s32 error;+ sljit_s32 options;++ struct sljit_label *labels;+ struct sljit_jump *jumps;+ struct sljit_const *consts;+ struct sljit_label *last_label;+ struct sljit_jump *last_jump;+ struct sljit_const *last_const;++ void *allocator_data;+ void *user_data;+ struct sljit_memory_fragment *buf;+ struct sljit_memory_fragment *abuf;++ /* Number of labels created by the compiler. */+ sljit_uw label_count;+ /* Available scratch registers. */+ sljit_s32 scratches;+ /* Available saved registers. */+ sljit_s32 saveds;+ /* Available float scratch registers. */+ sljit_s32 fscratches;+ /* Available float saved registers. */+ sljit_s32 fsaveds;+ /* Local stack size. */+ sljit_s32 local_size;+ /* Maximum code size. */+ sljit_uw size;+ /* Relative offset of the executable mapping from the writable mapping. */+ sljit_sw executable_offset;+ /* Executable size for statistical purposes. */+ sljit_uw executable_size;++#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)+ sljit_s32 status_flags_state;+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 args_size;+#endif /* SLJIT_CONFIG_X86_32 */++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ /* Temporary fields. */+ sljit_s32 mode32;+#endif /* SLJIT_CONFIG_X86_64 */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ /* Constant pool handling. */+ sljit_uw *cpool;+ sljit_u8 *cpool_unique;+ sljit_uw cpool_diff;+ sljit_uw cpool_fill;+ /* Other members. */+ /* Contains pointer, "ldr pc, [...]" pairs. */+ sljit_uw patches;+#endif /* SLJIT_CONFIG_ARM_V6 */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ /* Temporary fields. */+ sljit_uw shift_imm;+#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V6 */++#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)+ sljit_uw args_size;+#endif /* SLJIT_CONFIG_ARM_32 && __SOFTFP__ */++#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+ /* Temporary fields. */+ sljit_u32 imm;+#endif /* SLJIT_CONFIG_PPC */++#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+ sljit_s32 delay_slot;+ /* Temporary fields. */+ sljit_s32 cache_arg;+ sljit_sw cache_argw;+#endif /* SLJIT_CONFIG_MIPS */++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ sljit_uw args_size;+#endif /* SLJIT_CONFIG_MIPS_32 */++#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)+ /* Temporary fields. */+ sljit_s32 cache_arg;+ sljit_sw cache_argw;+#endif /* SLJIT_CONFIG_RISCV */++#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+ /* Need to allocate register save area to make calls. */+ /* Temporary fields. */+ sljit_s32 mode;+#endif /* SLJIT_CONFIG_S390X */++#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)+ /* Temporary fields. */+ sljit_s32 cache_arg;+ sljit_sw cache_argw;+#endif /* SLJIT_CONFIG_LOONGARCH */++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ FILE* verbose;+#endif /* SLJIT_VERBOSE */++#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;+ /* Return value type set by entry functions. */+ sljit_s32 last_return;+ /* Local size passed to entry functions. */+ sljit_s32 logical_local_size;+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ /* Trust arguments when an API function is called.+ Used internally for calling API functions. */+ sljit_s32 skip_checks;+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG || SLJIT_VERBOSE */+};++/* --------------------------------------------------------------------- */+/* Main functions */+/* --------------------------------------------------------------------- */++/* Creates an SLJIT compiler. The allocator_data is required by some+ custom memory managers. This pointer is passed to SLJIT_MALLOC+ and SLJIT_FREE macros. Most allocators (including the default+ one) ignores this value, and it is recommended to pass NULL+ as a dummy value for allocator_data.++ Returns NULL if failed. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data);++/* Frees everything except the compiled machine code. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler);++/* Returns the current error code. If an error occurres, future calls+ which uses the same compiler argument returns early with the same+ error code. Thus there is no need for checking the error after every+ call, it is enough to do it after the code is compiled. Removing+ these checks increases the performance of the compiling process. */+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+ the compiler behaves as if the allocation failure happened+ during an SLJIT function call. This can greatly simplify error+ checking, since it is enough to check the compiler status+ after the code is compiled. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler);++/* Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit,+ and <= 128 bytes on 64 bit architectures. The memory area is owned by the+ compiler, and freed by sljit_free_compiler. The returned pointer is+ sizeof(sljit_sw) aligned. Excellent for allocating small blocks during+ compiling, and no need to worry about freeing them. The size is enough+ to contain at most 16 pointers. If the size is outside of the range,+ the function will return with NULL. However, this return value does not+ 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_s32 size);++/* Returns the allocator data passed to sljit_create_compiler. */+static SLJIT_INLINE void* sljit_compiler_get_allocator_data(struct sljit_compiler *compiler) { return compiler->allocator_data; }+/* Sets/get the user data for a compiler. */+static SLJIT_INLINE void sljit_compiler_set_user_data(struct sljit_compiler *compiler, void *user_data) { compiler->user_data = user_data; }+static SLJIT_INLINE void* sljit_compiler_get_user_data(struct sljit_compiler *compiler) { return compiler->user_data; }++#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++/* Option bits for sljit_generate_code. */++/* The exec_allocator_data points to a pre-allocated+ buffer which type is sljit_generate_code_buffer. */+#define SLJIT_GENERATE_CODE_BUFFER 0x1++/* Create executable code from the instruction stream. This is the final step+ of the code generation, and no more instructions can be emitted after this call.++ options is the combination of SLJIT_GENERATE_CODE_* bits+ exec_allocator_data is passed to SLJIT_MALLOC_EXEC and+ SLJIT_MALLOC_FREE functions */++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data);++/* Free executable code. */++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data);++/* 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. The return value is one, if a+ feature is fully supported, and it is two, if partially supported.++ 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 when a feature is emulated, specialized code paths may 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] Has zero register (setting a memory location to zero is efficient). */+#define SLJIT_HAS_ZERO_REGISTER 2+/* [Emulated] Count leading zero is supported. */+#define SLJIT_HAS_CLZ 3+/* [Emulated] Count trailing zero is supported. */+#define SLJIT_HAS_CTZ 4+/* [Emulated] Reverse the order of bytes is supported. */+#define SLJIT_HAS_REV 5+/* [Emulated] Rotate left/right is supported. */+#define SLJIT_HAS_ROT 6+/* [Emulated] Conditional move is supported. */+#define SLJIT_HAS_CMOV 7+/* [Emulated] Prefetch instruction is available (emulated as a nop). */+#define SLJIT_HAS_PREFETCH 8+/* [Emulated] Copy from/to f32 operation is available (see sljit_emit_fcopy). */+#define SLJIT_HAS_COPY_F32 9+/* [Emulated] Copy from/to f64 operation is available (see sljit_emit_fcopy). */+#define SLJIT_HAS_COPY_F64 10+/* [Not emulated] The 64 bit floating point registers can be used as+ two separate 32 bit floating point registers (e.g. ARM32). The+ second 32 bit part can be accessed by SLJIT_F64_SECOND. */+#define SLJIT_HAS_F64_AS_F32_PAIR 11+/* [Not emulated] Some SIMD operations are supported by the compiler. */+#define SLJIT_HAS_SIMD 12+/* [Not emulated] SIMD registers are mapped to a pair of double precision+ floating point registers. E.g. passing either SLJIT_FR0 or SLJIT_FR1 to+ a simd operation represents the same 128 bit register, and both SLJIT_FR0+ and SLJIT_FR1 are overwritten. */+#define SLJIT_SIMD_REGS_ARE_PAIRS 13+/* [Not emulated] Atomic support is available (fine-grained). */+#define SLJIT_HAS_ATOMIC 14++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+/* [Not emulated] AVX support is available on x86. */+#define SLJIT_HAS_AVX 100+/* [Not emulated] AVX2 support is available on x86. */+#define SLJIT_HAS_AVX2 101+#endif++#if (defined SLJIT_CONFIG_LOONGARCH)+/* [Not emulated] LASX support is available on LoongArch */+#define SLJIT_HAS_LASX 201+#endif++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type);++/* If type is between SLJIT_ORDERED_EQUAL and SLJIT_ORDERED_LESS_EQUAL,+ sljit_cmp_info returns with:+ zero - if the cpu supports the floating point comparison type+ one - if the comparison requires two machine instructions+ two - if the comparison requires more than two machine instructions++ When the result is non-zero, it is recommended to avoid+ using the specified comparison type if it is easy to do so.++ Otherwise it returns zero. */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type);++/* The following functions generate machine code. If there is no+ error, they return with SLJIT_SUCCESS, otherwise they return+ with an error code. */++/*+ The executable code is a function from the viewpoint of the C+ language. The function calls must conform to the ABI (Application+ Binary Interface) of the platform, which specify the purpose of+ machine registers and stack handling among other things. The+ sljit_emit_enter function emits the necessary instructions for+ setting up a new context for the executable code. This is often+ called as function prologue. Furthermore the options argument+ can be used to pass configuration options to the compiler. The+ available options are listed before sljit_emit_enter.++ The function argument list is specified by the SLJIT_ARGSx+ (SLJIT_ARGS0 .. SLJIT_ARGS4) macros. Currently maximum four+ arguments are supported. See the description of SLJIT_ARGSx+ macros about argument passing. Furthermore the register set+ used by the function must be declared as well. The number of+ scratch and saved registers available to the function must+ be passed to sljit_emit_enter. Only R registers between R0+ and "scratches" argument can be used later. E.g. if "scratches"+ is set to two, the scratch register set will be limited to+ SLJIT_R0 and SLJIT_R1. The S registers and the floating point+ registers ("fscratches" and "fsaveds") are specified in a+ similar manner. The sljit_emit_enter is also capable of+ allocating a stack space for local data. The "local_size"+ argument contains the size in bytes of this local area, and+ it can be accessed using SLJIT_MEM1(SLJIT_SP). The memory+ area between SLJIT_SP (inclusive) and SLJIT_SP + local_size+ (exclusive) can be modified freely until the function returns.+ The stack space is not initialized to zero.++ Note: the following conditions must met:+ 0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS+ 0 <= saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS+ scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS+ 0 <= fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS+ 0 <= fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS+ fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS++ Note: the compiler can use saved registers as scratch registers,+ but the opposite is not supported++ Note: every call of sljit_emit_enter and sljit_set_context+ overwrites the previous context.+*/++/* Saved registers between SLJIT_S0 and SLJIT_S(n - 1) (inclusive)+ are not saved / restored on function enter / return. Instead,+ these registers can be used to pass / return data (such as+ global / local context pointers) across function calls. The+ value of n must be between 1 and 3. This option is only+ supported by SLJIT_ENTER_REG_ARG calling convention. */+#define SLJIT_ENTER_KEEP(n) (n)++/* The compiled function uses an SLJIT specific register argument+ calling convention. This is a lightweight function call type where+ both the caller and the called functions must be compiled by+ SLJIT. The type argument of the call must be SLJIT_CALL_REG_ARG+ and all arguments must be stored in scratch registers. */+#define SLJIT_ENTER_REG_ARG 0x00000004++/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */+#define SLJIT_MAX_LOCAL_SIZE 1048576++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+/* Use VEX prefix for all SIMD operations on x86. */+#define SLJIT_ENTER_USE_VEX 0x00010000+#endif /* !SLJIT_CONFIG_X86 */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size);++/* The SLJIT compiler has a current context (which contains the local+ stack space size, number of used registers, etc.) which is initialized+ by sljit_emit_enter. Several functions (such as sljit_emit_return)+ requires this context to be able to generate the appropriate code.+ However, some code fragments (compiled separately) may have no+ normal entry point so their context is unknown to the compiler.++ sljit_set_context and sljit_emit_enter have the same arguments,+ but sljit_set_context does not generate any machine code.++ Note: every call of sljit_emit_enter and sljit_set_context overwrites+ the previous context. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size);++/* Return to the caller function. The sljit_emit_return_void function+ does not return with any value. The sljit_emit_return function returns+ with a single value loaded from its source operand. The load operation+ can be between SLJIT_MOV and SLJIT_MOV_P (see sljit_emit_op1) and+ SLJIT_MOV_F32/SLJIT_MOV_F64 (see sljit_emit_fop1) depending on the+ return value specified by sljit_emit_enter/sljit_set_context. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler);++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw);++/* Restores the saved registers and free the stack area, then the execution+ continues from the address specified by the source operand. This+ operation is similar to sljit_emit_return, but it ignores the return+ address. The code where the exection continues should use the same context+ as the caller function (see sljit_set_context). A word (pointer) value+ can be passed in the SLJIT_RETURN_REG register. This function can be used+ to jump to exception handlers. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw);++/*+ Source and destination operands for arithmetical instructions+ imm - a simple immediate value (cannot be used as a destination)+ reg - any of the available registers (immediate argument must be 0)+ [imm] - absolute memory address+ [reg+imm] - indirect memory address+ [reg+(reg<<imm)] - indirect indexed memory address (shift must be between 0 and 3)+ useful for accessing arrays (fully supported by both x86 and+ ARM architectures, and cheap operation on others)+*/++/*+ IMPORTANT NOTE: memory accesses MUST be naturally aligned unless+ SLJIT_UNALIGNED macro is defined and its value is 1.++ length | alignment+ ---------+-----------+ byte | 1 byte (any physical_address is accepted)+ half | 2 byte (physical_address & 0x1 == 0)+ int | 4 byte (physical_address & 0x3 == 0)+ word | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1+ | 8 byte if SLJIT_64BIT_ARCHITECTURE is defined and its value is 1+ pointer | size of sljit_up type (4 byte on 32 bit machines, 4 or 8 byte+ | on 64 bit machines)++ Note: Different architectures have different addressing limitations.+ A single instruction is enough for the following addressing+ modes. Other addressing modes are emulated by instruction+ sequences. This information could help to improve those code+ generators which focuses only a few architectures.++ x86: [reg+imm], -2^32+1 <= imm <= 2^32-1 (full address space on x86-32)+ [reg+(reg<<imm)] is supported+ [imm], -2^32+1 <= imm <= 2^32-1 is supported+ Write-back is not supported+ arm: [reg+imm], -4095 <= imm <= 4095 or -255 <= imm <= 255 for signed+ bytes, any halfs or floating point values)+ [reg+(reg<<imm)] is supported+ Write-back is supported+ arm-t2: [reg+imm], -255 <= imm <= 4095+ [reg+(reg<<imm)] is supported+ Write back is supported only for [reg+imm], where -255 <= imm <= 255+ arm64: [reg+imm], -256 <= imm <= 255, 0 <= aligned imm <= 4095 * alignment+ [reg+(reg<<imm)] is supported+ Write back is supported only for [reg+imm], where -256 <= imm <= 255+ ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit+ signed load on 64 bit requires immediates divisible by 4.+ [reg+imm] is not supported for signed 8 bit values.+ [reg+reg] is supported+ Write-back is supported except for one instruction: 32 bit signed+ load with [reg+imm] addressing mode on 64 bit.+ mips: [reg+imm], -65536 <= imm <= 65535+ Write-back is not supported+ riscv: [reg+imm], -2048 <= imm <= 2047+ Write-back is not supported+ s390x: [reg+imm], -2^19 <= imm < 2^19+ [reg+reg] is supported+ Write-back is not supported+ loongarch: [reg+imm], -2048 <= imm <= 2047+ [reg+reg] is supported+ Write-back is not supported+*/++/* Macros for specifying operand types. */+#define SLJIT_MEM 0x80+#define SLJIT_MEM0() (SLJIT_MEM)+#define SLJIT_MEM1(r1) (SLJIT_MEM | (r1))+#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 8))+#define SLJIT_IMM 0x7f+#define SLJIT_REG_PAIR(r1, r2) ((r1) | ((r2) << 8))++/* Macros for checking operand types (only for valid arguments). */+#define SLJIT_IS_REG(arg) ((arg) > 0 && (arg) < SLJIT_IMM)+#define SLJIT_IS_MEM(arg) ((arg) & SLJIT_MEM)+#define SLJIT_IS_MEM0(arg) ((arg) == SLJIT_MEM)+#define SLJIT_IS_MEM1(arg) ((arg) > SLJIT_MEM && (arg) < (SLJIT_MEM << 1))+#define SLJIT_IS_MEM2(arg) (((arg) & SLJIT_MEM) && (arg) >= (SLJIT_MEM << 1))+#define SLJIT_IS_IMM(arg) ((arg) == SLJIT_IMM)+#define SLJIT_IS_REG_PAIR(arg) (!((arg) & SLJIT_MEM) && (arg) >= (SLJIT_MEM << 1))++/* Macros for extracting registers from operands. */+/* Support operands which contains a single register or+ constructed using SLJIT_MEM1, SLJIT_MEM2, or SLJIT_REG_PAIR. */+#define SLJIT_EXTRACT_REG(arg) ((arg) & 0x7f)+/* Support operands which constructed using SLJIT_MEM2, or SLJIT_REG_PAIR. */+#define SLJIT_EXTRACT_SECOND_REG(arg) ((arg) >> 8)++/* Sets 32 bit operation mode 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 bits 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 which source register can hold+ any 32 or 64 bit value, and it is converted to a 32 bit compatible format+ first. When the source and destination registers are the same, this+ conversion is free (no instructions are emitted) on most CPUs. A 32 bit+ value can also be converted to a 64 bit value by SLJIT_MOV_S32+ (sign extension) or SLJIT_MOV_U32 (zero extension).++ As for floating-point operations, this option sets 32 bit single+ precision mode. Similar to the integer operations, all register arguments+ must be the result of those operations where this option was also set.++ 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_32) */+#define SLJIT_32 0x100++/* Many CPUs (x86, ARM, PPC) have status flag bits which can be set according+ to the result of an operation. Other CPUs (MIPS) do not have status+ flag bits, 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 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.++ Note: the logical or operation can be used to set flags.++ 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.++ Certain instructions (e.g. SLJIT_MOV) does not modify flags, so+ status flags are unchanged.++ Example:++ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z, ...)+ sljit_op1(..., SLJIT_MOV, ...)+ Zero flag is set according to the result of SLJIT_ADD.++ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z, ...)+ sljit_op2(..., SLJIT_ADD, ...)+ Zero flag has unknown value.++ These flags can be used for code optimization. E.g. a fast loop can be+ implemented by decreasing a counter register and set the zero flag+ using a single instruction. The zero register can be used by a+ conditional jump to restart the loop. A single comparison can set a+ zero and less flags to check if a value is less, equal, or greater+ than another value.++ Motivation: although some CPUs can set a large number of flag bits,+ usually their values are ignored or only a few of them are used. Emulating+ a large number of flags on systems without a flag register is complicated+ so SLJIT instructions must specify the flag they want to use and only+ that flag is computed. The last arithmetic instruction can be repeated if+ multiple flags need to be checked.+*/++/* Set Zero status flag. */+#define SLJIT_SET_Z 0x0200+/* Set the variable status flag if condition is true.+ See comparison types (e.g. SLJIT_SET_LESS, SLJIT_SET_F_EQUAL). */+#define SLJIT_SET(condition) ((condition) << 10)++/* Starting index of opcodes for sljit_emit_op0. */+#define SLJIT_OP0_BASE 0++/* 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: - (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_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_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_DIVMOD_UW (SLJIT_OP0_BASE + 4)+#define SLJIT_DIVMOD_U32 (SLJIT_DIVMOD_UW | SLJIT_32)+/* 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_DIVMOD_SW (SLJIT_OP0_BASE + 5)+#define SLJIT_DIVMOD_S32 (SLJIT_DIVMOD_SW | SLJIT_32)+/* 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. */+#define SLJIT_DIV_UW (SLJIT_OP0_BASE + 6)+#define SLJIT_DIV_U32 (SLJIT_DIV_UW | SLJIT_32)+/* 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. */+#define SLJIT_DIV_SW (SLJIT_OP0_BASE + 7)+#define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_32)+/* Flags: - (does not modify flags)+ ENDBR32 instruction for x86-32 and ENDBR64 instruction for x86-64+ when Intel Control-flow Enforcement Technology (CET) is enabled.+ No instructions are emitted for other architectures. */+#define SLJIT_ENDBR (SLJIT_OP0_BASE + 8)+/* Flags: - (may destroy flags)+ Skip stack frames before return when Intel Control-flow+ Enforcement Technology (CET) is enabled. No instructions+ are emitted for other architectures. */+#define SLJIT_SKIP_FRAMES_BEFORE_RETURN (SLJIT_OP0_BASE + 9)++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++/* The MOV instruction transfers 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_up) data transfer+*/++/* Flags: - (does not modify flags) */+#define SLJIT_MOV (SLJIT_OP1_BASE + 0)+/* Flags: - (does not modify flags) */+#define SLJIT_MOV_U8 (SLJIT_OP1_BASE + 1)+#define SLJIT_MOV32_U8 (SLJIT_MOV_U8 | SLJIT_32)+/* Flags: - (does not modify flags) */+#define SLJIT_MOV_S8 (SLJIT_OP1_BASE + 2)+#define SLJIT_MOV32_S8 (SLJIT_MOV_S8 | SLJIT_32)+/* Flags: - (does not modify flags) */+#define SLJIT_MOV_U16 (SLJIT_OP1_BASE + 3)+#define SLJIT_MOV32_U16 (SLJIT_MOV_U16 | SLJIT_32)+/* Flags: - (does not modify flags) */+#define SLJIT_MOV_S16 (SLJIT_OP1_BASE + 4)+#define SLJIT_MOV32_S16 (SLJIT_MOV_S16 | SLJIT_32)+/* 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_OP1_BASE + 7)+/* Flags: - (does not modify flags)+ Note: loads a pointer sized data, useful on x32 mode (a 64 bit mode+ on x86-64 which uses 32 bit pointers) or similar compiling modes */+#define SLJIT_MOV_P (SLJIT_OP1_BASE + 8)+/* Count leading zeroes+ Flags: - (may destroy flags)+ Note: immediate source argument is not supported */+#define SLJIT_CLZ (SLJIT_OP1_BASE + 9)+#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_32)+/* Count trailing zeroes+ Flags: - (may destroy flags)+ Note: immediate source argument is not supported */+#define SLJIT_CTZ (SLJIT_OP1_BASE + 10)+#define SLJIT_CTZ32 (SLJIT_CTZ | SLJIT_32)+/* Reverse the order of bytes+ Flags: - (may destroy flags)+ Note: converts between little and big endian formats+ Note: immediate source argument is not supported */+#define SLJIT_REV (SLJIT_OP1_BASE + 11)+#define SLJIT_REV32 (SLJIT_REV | SLJIT_32)+/* Reverse the order of bytes in the lower 16 bit and extend as unsigned+ Flags: - (may destroy flags)+ Note: converts between little and big endian formats+ Note: immediate source argument is not supported */+#define SLJIT_REV_U16 (SLJIT_OP1_BASE + 12)+#define SLJIT_REV32_U16 (SLJIT_REV_U16 | SLJIT_32)+/* Reverse the order of bytes in the lower 16 bit and extend as signed+ Flags: - (may destroy flags)+ Note: converts between little and big endian formats+ Note: immediate source argument is not supported */+#define SLJIT_REV_S16 (SLJIT_OP1_BASE + 13)+#define SLJIT_REV32_S16 (SLJIT_REV_S16 | SLJIT_32)+/* Reverse the order of bytes in the lower 32 bit and extend as unsigned+ Flags: - (may destroy flags)+ Note: converts between little and big endian formats+ Note: immediate source argument is not supported */+#define SLJIT_REV_U32 (SLJIT_OP1_BASE + 14)+/* Reverse the order of bytes in the lower 32 bit and extend as signed+ Flags: - (may destroy flags)+ Note: converts between little and big endian formats+ Note: immediate source argument is not supported */+#define SLJIT_REV_S32 (SLJIT_OP1_BASE + 15)++/* The following unary operations are supported by using sljit_emit_op2:+ - binary not: SLJIT_XOR with immedate -1 as src1 or src2+ - negate: SLJIT_SUB with immedate 0 as src1+ Note: these operations are optimized by the compiler if the+ target CPU has specialized instruction forms for them. */++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 64++/* Flags: Z | OVERFLOW | CARRY */+#define SLJIT_ADD (SLJIT_OP2_BASE + 0)+#define SLJIT_ADD32 (SLJIT_ADD | SLJIT_32)+/* Flags: CARRY */+#define SLJIT_ADDC (SLJIT_OP2_BASE + 1)+#define SLJIT_ADDC32 (SLJIT_ADDC | SLJIT_32)+/* Flags: Z | LESS | GREATER_EQUAL | GREATER | LESS_EQUAL+ SIG_LESS | SIG_GREATER_EQUAL | SIG_GREATER+ SIG_LESS_EQUAL | OVERFLOW | CARRY */+#define SLJIT_SUB (SLJIT_OP2_BASE + 2)+#define SLJIT_SUB32 (SLJIT_SUB | SLJIT_32)+/* Flags: CARRY */+#define SLJIT_SUBC (SLJIT_OP2_BASE + 3)+#define SLJIT_SUBC32 (SLJIT_SUBC | SLJIT_32)+/* Note: integer mul+ Flags: OVERFLOW */+#define SLJIT_MUL (SLJIT_OP2_BASE + 4)+#define SLJIT_MUL32 (SLJIT_MUL | SLJIT_32)+/* Flags: Z */+#define SLJIT_AND (SLJIT_OP2_BASE + 5)+#define SLJIT_AND32 (SLJIT_AND | SLJIT_32)+/* Flags: Z */+#define SLJIT_OR (SLJIT_OP2_BASE + 6)+#define SLJIT_OR32 (SLJIT_OR | SLJIT_32)+/* Flags: Z */+#define SLJIT_XOR (SLJIT_OP2_BASE + 7)+#define SLJIT_XOR32 (SLJIT_XOR | SLJIT_32)+/* 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_SHL32 (SLJIT_SHL | SLJIT_32)+/* Flags: Z+ Same as SLJIT_SHL, except the the second operand is+ always masked by the length of the shift operation. */+#define SLJIT_MSHL (SLJIT_OP2_BASE + 9)+#define SLJIT_MSHL32 (SLJIT_MSHL | SLJIT_32)+/* 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 + 10)+#define SLJIT_LSHR32 (SLJIT_LSHR | SLJIT_32)+/* Flags: Z+ Same as SLJIT_LSHR, except the the second operand is+ always masked by the length of the shift operation. */+#define SLJIT_MLSHR (SLJIT_OP2_BASE + 11)+#define SLJIT_MLSHR32 (SLJIT_MLSHR | SLJIT_32)+/* 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 + 12)+#define SLJIT_ASHR32 (SLJIT_ASHR | SLJIT_32)+/* Flags: Z+ Same as SLJIT_ASHR, except the the second operand is+ always masked by the length of the shift operation. */+#define SLJIT_MASHR (SLJIT_OP2_BASE + 13)+#define SLJIT_MASHR32 (SLJIT_MASHR | SLJIT_32)+/* Flags: - (may destroy flags)+ Let bit_length be the length of the rotate operation: 32 or 64.+ The second operand is always masked by (bit_length - 1). */+#define SLJIT_ROTL (SLJIT_OP2_BASE + 14)+#define SLJIT_ROTL32 (SLJIT_ROTL | SLJIT_32)+/* Flags: - (may destroy flags)+ Let bit_length be the length of the rotate operation: 32 or 64.+ The second operand is always masked by (bit_length - 1). */+#define SLJIT_ROTR (SLJIT_OP2_BASE + 15)+#define SLJIT_ROTR32 (SLJIT_ROTR | SLJIT_32)++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);++/* The sljit_emit_op2u function is the same as sljit_emit_op2+ except the result is discarded. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++/* Starting index of opcodes for sljit_emit_op2r. */+#define SLJIT_OP2R_BASE 96++/* Flags: - (may destroy flags) */+#define SLJIT_MULADD (SLJIT_OP2R_BASE + 0)+#define SLJIT_MULADD32 (SLJIT_MULADD | SLJIT_32)++/* Similar to sljit_emit_fop2, except the destination is always a register. */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++/* Emit a left or right shift operation, where the bits shifted+ in comes from a separate source operand. All operands are+ interpreted as unsigned integers.++ In the followings the value_mask variable is 31 for 32 bit+ operations and word_size - 1 otherwise.++ op must be one of the following operations:+ SLJIT_SHL or SLJIT_SHL32:+ dst_reg = src1_reg << src3_reg+ dst_reg |= ((src2_reg >> 1) >> (src3 ^ value_mask))+ SLJIT_MSHL or SLJIT_MSHL32:+ src3 &= value_mask+ perform the SLJIT_SHL or SLJIT_SHL32 operation+ SLJIT_LSHR or SLJIT_LSHR32:+ dst_reg = src1_reg >> src3_reg+ dst_reg |= ((src2_reg << 1) << (src3 ^ value_mask))+ SLJIT_MLSHR or SLJIT_MLSHR32:+ src3 &= value_mask+ perform the SLJIT_LSHR or SLJIT_LSHR32 operation++ op can be combined (or'ed) with SLJIT_SHIFT_INTO_NON_ZERO++ dst_reg specifies the destination register, where dst_reg+ and src2_reg cannot be the same registers+ src1_reg specifies the source register+ src2_reg specifies the register which is shifted into src1_reg+ src3 / src3w contains the shift amount++ Note: a rotate operation is performed if src1_reg and+ src2_reg are the same registers++ Flags: - (may destroy flags) */++/* The src3 operand contains a non-zero value. Improves+ the generated code on certain architectures, which+ provides a small performance improvement. */+#define SLJIT_SHIFT_INTO_NON_ZERO 0x200++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w);++/* Starting index of opcodes for sljit_emit_op_src+ and sljit_emit_op_dst. */+#define SLJIT_OP_SRC_DST_BASE 112++/* Fast return, see SLJIT_FAST_CALL for more details.+ Note: src cannot be an immedate value+ Flags: - (does not modify flags) */+#define SLJIT_FAST_RETURN (SLJIT_OP_SRC_DST_BASE + 0)+/* Skip stack frames before fast return.+ Note: src cannot be an immedate value+ Flags: may destroy flags. */+#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN (SLJIT_OP_SRC_DST_BASE + 1)+/* Prefetch value into the level 1 data cache+ Note: if the target CPU does not support data prefetch,+ no instructions are emitted.+ Note: this instruction never fails, even if the memory address is invalid.+ Flags: - (does not modify flags) */+#define SLJIT_PREFETCH_L1 (SLJIT_OP_SRC_DST_BASE + 2)+/* Prefetch value into the level 2 data cache+ Note: same as SLJIT_PREFETCH_L1 if the target CPU+ does not support this instruction form.+ Note: this instruction never fails, even if the memory address is invalid.+ Flags: - (does not modify flags) */+#define SLJIT_PREFETCH_L2 (SLJIT_OP_SRC_DST_BASE + 3)+/* Prefetch value into the level 3 data cache+ Note: same as SLJIT_PREFETCH_L2 if the target CPU+ does not support this instruction form.+ Note: this instruction never fails, even if the memory address is invalid.+ Flags: - (does not modify flags) */+#define SLJIT_PREFETCH_L3 (SLJIT_OP_SRC_DST_BASE + 4)+/* Prefetch a value which is only used once (and can be discarded afterwards)+ Note: same as SLJIT_PREFETCH_L1 if the target CPU+ does not support this instruction form.+ Note: this instruction never fails, even if the memory address is invalid.+ Flags: - (does not modify flags) */+#define SLJIT_PREFETCH_ONCE (SLJIT_OP_SRC_DST_BASE + 5)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw);++/* Fast enter, see SLJIT_FAST_CALL for more details.+ Flags: - (does not modify flags) */+#define SLJIT_FAST_ENTER (SLJIT_OP_SRC_DST_BASE + 6)++/* Copies the return address into dst. The return address is the+ address where the execution continues after the called function+ returns (see: sljit_emit_return / sljit_emit_return_void).+ Flags: - (does not modify flags) */+#define SLJIT_GET_RETURN_ADDRESS (SLJIT_OP_SRC_DST_BASE + 7)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw);++/* Starting index of opcodes for sljit_emit_fop1. */+#define SLJIT_FOP1_BASE 144++/* Flags: - (does not modify flags) */+#define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0)+#define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_32)+/* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE]+ SRC/DST TYPE can be: F64, F32, S32, SW+ Rounding mode when the destination is SW or S32: round towards zero. */+/* Flags: - (may destroy flags) */+#define SLJIT_CONV_F64_FROM_F32 (SLJIT_FOP1_BASE + 1)+#define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_CONV_SW_FROM_F64 (SLJIT_FOP1_BASE + 2)+#define SLJIT_CONV_SW_FROM_F32 (SLJIT_CONV_SW_FROM_F64 | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_CONV_S32_FROM_F64 (SLJIT_FOP1_BASE + 3)+#define SLJIT_CONV_S32_FROM_F32 (SLJIT_CONV_S32_FROM_F64 | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_CONV_F64_FROM_SW (SLJIT_FOP1_BASE + 4)+#define SLJIT_CONV_F32_FROM_SW (SLJIT_CONV_F64_FROM_SW | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5)+#define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_CONV_F64_FROM_UW (SLJIT_FOP1_BASE + 6)+#define SLJIT_CONV_F32_FROM_UW (SLJIT_CONV_F64_FROM_UW | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_CONV_F64_FROM_U32 (SLJIT_FOP1_BASE + 7)+#define SLJIT_CONV_F32_FROM_U32 (SLJIT_CONV_F64_FROM_U32 | SLJIT_32)+/* Note: dst is the left and src is the right operand for SLJIT_CMP_F32/64.+ Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */+#define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 8)+#define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_NEG_F64 (SLJIT_FOP1_BASE + 9)+#define SLJIT_NEG_F32 (SLJIT_NEG_F64 | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_ABS_F64 (SLJIT_FOP1_BASE + 10)+#define SLJIT_ABS_F32 (SLJIT_ABS_F64 | SLJIT_32)++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 176++/* Flags: - (may destroy flags) */+#define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0)+#define SLJIT_ADD_F32 (SLJIT_ADD_F64 | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_SUB_F64 (SLJIT_FOP2_BASE + 1)+#define SLJIT_SUB_F32 (SLJIT_SUB_F64 | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_MUL_F64 (SLJIT_FOP2_BASE + 2)+#define SLJIT_MUL_F32 (SLJIT_MUL_F64 | SLJIT_32)+/* Flags: - (may destroy flags) */+#define SLJIT_DIV_F64 (SLJIT_FOP2_BASE + 3)+#define SLJIT_DIV_F32 (SLJIT_DIV_F64 | SLJIT_32)++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);++/* Starting index of opcodes for sljit_emit_fop2r. */+#define SLJIT_FOP2R_BASE 192++/* Flags: - (may destroy flags) */+#define SLJIT_COPYSIGN_F64 (SLJIT_FOP2R_BASE + 0)+#define SLJIT_COPYSIGN_F32 (SLJIT_COPYSIGN_F64 | SLJIT_32)++/* Similar to sljit_emit_fop2, except the destination is always a register. */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++/* Sets a floating point register to an immediate value. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value);+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value);++/* The following opcodes are used by sljit_emit_fcopy(). */++/* 64 bit: copy a 64 bit value from an integer register into a+ 64 bit floating point register without any modifications.+ 32 bit: copy a 32 bit register or register pair into a 64 bit+ floating point register without any modifications. The+ register, or the first register of the register pair+ replaces the high order 32 bit of the floating point+ register. If a register pair is passed, the low+ order 32 bit is replaced by the second register.+ Otherwise, the low order 32 bit is unchanged. */+#define SLJIT_COPY_TO_F64 1+/* Copy a 32 bit value from an integer register into a 32 bit+ floating point register without any modifications. */+#define SLJIT_COPY32_TO_F32 (SLJIT_COPY_TO_F64 | SLJIT_32)+/* 64 bit: copy the value of a 64 bit floating point register into+ an integer register without any modifications.+ 32 bit: copy a 64 bit floating point register into a 32 bit register+ or a 32 bit register pair without any modifications. The+ high order 32 bit of the floating point register is copied+ into the register, or the first register of the register+ pair. If a register pair is passed, the low order 32 bit+ is copied into the second register. */+#define SLJIT_COPY_FROM_F64 2+/* Copy the value of a 32 bit floating point register into an integer+ register without any modifications. The register should be processed+ with 32 bit operations later. */+#define SLJIT_COPY32_FROM_F32 (SLJIT_COPY_FROM_F64 | SLJIT_32)++/* Special data copy which involves floating point registers.++ op must be between SLJIT_COPY_TO_F64 and SLJIT_COPY32_FROM_F32+ freg must be a floating point register+ reg must be a register or register pair */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg);++/* Label and jump instructions. */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler);++/* The SLJIT_FAST_CALL is a calling method for creating lightweight function+ calls. This type of calls preserve the values of all registers and stack+ frame. Unlike normal function calls, the enter and return operations must+ be performed by the SLJIT_FAST_ENTER and SLJIT_FAST_RETURN operations+ respectively. The return address is stored in the dst argument of the+ SLJIT_FAST_ENTER operation, and this return address should be passed as+ the src argument for the SLJIT_FAST_RETURN operation to return from the+ called function.++ Fast calls are cheap operations (usually only a single call instruction is+ emitted) but they do not preserve any registers. However the callee function+ can freely use / update any registers and the locals area which can be+ efficiently exploited by various optimizations. Registers can be saved+ and restored manually if needed.++ Although returning to different address by SLJIT_FAST_RETURN is possible,+ this address usually cannot be predicted by the return address predictor of+ modern CPUs which may reduce performance. Furthermore certain security+ enhancement technologies such as Intel Control-flow Enforcement Technology+ (CET) may disallow returning to a different address (indirect jumps+ can be used instead, see SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN). */++/* Invert (negate) conditional type: xor (^) with 0x1 */++/* Integer comparison types. */+#define SLJIT_EQUAL 0+#define SLJIT_ZERO SLJIT_EQUAL+#define SLJIT_NOT_EQUAL 1+#define SLJIT_NOT_ZERO SLJIT_NOT_EQUAL++#define SLJIT_LESS 2+#define SLJIT_SET_LESS SLJIT_SET(SLJIT_LESS)+#define SLJIT_GREATER_EQUAL 3+#define SLJIT_SET_GREATER_EQUAL SLJIT_SET(SLJIT_LESS)+#define SLJIT_GREATER 4+#define SLJIT_SET_GREATER SLJIT_SET(SLJIT_GREATER)+#define SLJIT_LESS_EQUAL 5+#define SLJIT_SET_LESS_EQUAL SLJIT_SET(SLJIT_GREATER)+#define SLJIT_SIG_LESS 6+#define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS)+#define SLJIT_SIG_GREATER_EQUAL 7+#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_LESS)+#define SLJIT_SIG_GREATER 8+#define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER)+#define SLJIT_SIG_LESS_EQUAL 9+#define SLJIT_SET_SIG_LESS_EQUAL SLJIT_SET(SLJIT_SIG_GREATER)++#define SLJIT_OVERFLOW 10+#define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW)+#define SLJIT_NOT_OVERFLOW 11++/* Unlike other flags, sljit_emit_jump may destroy the carry flag. */+#define SLJIT_CARRY 12+#define SLJIT_SET_CARRY SLJIT_SET(SLJIT_CARRY)+#define SLJIT_NOT_CARRY 13++#define SLJIT_ATOMIC_STORED 14+#define SLJIT_SET_ATOMIC_STORED SLJIT_SET(SLJIT_ATOMIC_STORED)+#define SLJIT_ATOMIC_NOT_STORED 15++/* Basic floating point comparison types.++ Note: when the comparison result is unordered, their behaviour is unspecified. */++#define SLJIT_F_EQUAL 16+#define SLJIT_SET_F_EQUAL SLJIT_SET(SLJIT_F_EQUAL)+#define SLJIT_F_NOT_EQUAL 17+#define SLJIT_SET_F_NOT_EQUAL SLJIT_SET(SLJIT_F_EQUAL)+#define SLJIT_F_LESS 18+#define SLJIT_SET_F_LESS SLJIT_SET(SLJIT_F_LESS)+#define SLJIT_F_GREATER_EQUAL 19+#define SLJIT_SET_F_GREATER_EQUAL SLJIT_SET(SLJIT_F_LESS)+#define SLJIT_F_GREATER 20+#define SLJIT_SET_F_GREATER SLJIT_SET(SLJIT_F_GREATER)+#define SLJIT_F_LESS_EQUAL 21+#define SLJIT_SET_F_LESS_EQUAL SLJIT_SET(SLJIT_F_GREATER)++/* Jumps when either argument contains a NaN value. */+#define SLJIT_UNORDERED 22+#define SLJIT_SET_UNORDERED SLJIT_SET(SLJIT_UNORDERED)+/* Jumps when neither argument contains a NaN value. */+#define SLJIT_ORDERED 23+#define SLJIT_SET_ORDERED SLJIT_SET(SLJIT_UNORDERED)++/* Ordered / unordered floating point comparison types.++ Note: each comparison type has an ordered and unordered form. Some+ architectures supports only either of them (see: sljit_cmp_info). */++#define SLJIT_ORDERED_EQUAL 24+#define SLJIT_SET_ORDERED_EQUAL SLJIT_SET(SLJIT_ORDERED_EQUAL)+#define SLJIT_UNORDERED_OR_NOT_EQUAL 25+#define SLJIT_SET_UNORDERED_OR_NOT_EQUAL SLJIT_SET(SLJIT_ORDERED_EQUAL)+#define SLJIT_ORDERED_LESS 26+#define SLJIT_SET_ORDERED_LESS SLJIT_SET(SLJIT_ORDERED_LESS)+#define SLJIT_UNORDERED_OR_GREATER_EQUAL 27+#define SLJIT_SET_UNORDERED_OR_GREATER_EQUAL SLJIT_SET(SLJIT_ORDERED_LESS)+#define SLJIT_ORDERED_GREATER 28+#define SLJIT_SET_ORDERED_GREATER SLJIT_SET(SLJIT_ORDERED_GREATER)+#define SLJIT_UNORDERED_OR_LESS_EQUAL 29+#define SLJIT_SET_UNORDERED_OR_LESS_EQUAL SLJIT_SET(SLJIT_ORDERED_GREATER)++#define SLJIT_UNORDERED_OR_EQUAL 30+#define SLJIT_SET_UNORDERED_OR_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_EQUAL)+#define SLJIT_ORDERED_NOT_EQUAL 31+#define SLJIT_SET_ORDERED_NOT_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_EQUAL)+#define SLJIT_UNORDERED_OR_LESS 32+#define SLJIT_SET_UNORDERED_OR_LESS SLJIT_SET(SLJIT_UNORDERED_OR_LESS)+#define SLJIT_ORDERED_GREATER_EQUAL 33+#define SLJIT_SET_ORDERED_GREATER_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_LESS)+#define SLJIT_UNORDERED_OR_GREATER 34+#define SLJIT_SET_UNORDERED_OR_GREATER SLJIT_SET(SLJIT_UNORDERED_OR_GREATER)+#define SLJIT_ORDERED_LESS_EQUAL 35+#define SLJIT_SET_ORDERED_LESS_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_GREATER)++/* Unconditional jump types. */+#define SLJIT_JUMP 36+/* Fast calling method. See the description above. */+#define SLJIT_FAST_CALL 37+/* Default C calling convention. */+#define SLJIT_CALL 38+/* Called function must be compiled by SLJIT.+ See SLJIT_ENTER_REG_ARG option. */+#define SLJIT_CALL_REG_ARG 39++/* The target can be changed during runtime (see: sljit_set_jump_addr). */+#define SLJIT_REWRITABLE_JUMP 0x1000+/* When this flag is passed, the execution of the current function ends and+ the called function returns to the caller of the current function. The+ stack usage is reduced before the call, but it is not necessarily reduced+ to zero. In the latter case the compiler needs to allocate space for some+ arguments and the return address must be stored on the stack as well. */+#define SLJIT_CALL_RETURN 0x2000++/* Emit a jump instruction. The destination is not set, only the type of the jump.+ type must be between SLJIT_EQUAL and SLJIT_FAST_CALL+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP++ Flags: does not modify flags. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type);++/* Emit a C compiler (ABI) compatible function call.+ type must be SLJIT_CALL or SLJIT_CALL_REG_ARG+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and/or SLJIT_CALL_RETURN+ arg_types can be specified by SLJIT_ARGSx (SLJIT_ARG_RETURN / SLJIT_ARG_VALUE) macros++ Flags: destroy all flags. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types);++/* Basic arithmetic comparison. In most architectures it is implemented as+ a compare operation followed by a sljit_emit_jump. However some+ architectures (i.e: ARM64 or MIPS) may employ special optimizations+ here. It is suggested to use this comparison form when appropriate.+ type must be between SLJIT_EQUAL and SLJIT_SIG_LESS_EQUAL+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP++ 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+ a SLJIT_CMP_F32/64 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_F_EQUAL and SLJIT_ORDERED_LESS_EQUAL+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP+ Flags: destroy flags.+ Note: when an operand is NaN the behaviour depends on the comparison type. */+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);+/* Set the destination address of the jump to this label. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);++/* Emit an indirect jump or fast call.+ Direct form: set src to SLJIT_IMM() and srcw to the address+ Indirect form: any other valid addressing mode+ type must be between SLJIT_JUMP and SLJIT_FAST_CALL++ Flags: does not modify flags. */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw);++/* Emit a C compiler (ABI) compatible function call.+ Direct form: set src to SLJIT_IMM() and srcw to the address+ Indirect form: any other valid addressing mode+ type must be SLJIT_CALL or SLJIT_CALL_REG_ARG+ type can be combined (or'ed) with SLJIT_CALL_RETURN+ arg_types can be specified by SLJIT_ARGSx (SLJIT_ARG_RETURN / SLJIT_ARG_VALUE) macros++ Flags: destroy all flags. */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw);++/* Perform an operation using the conditional flags as the second argument.+ Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL.+ The value represented by the type is 1, if the condition represented+ by the type is fulfilled, and 0 otherwise.++ When op is SLJIT_MOV or SLJIT_MOV32:+ Set dst to the value represented by the type (0 or 1).+ Flags: - (does not modify flags)+ When op is SLJIT_AND, SLJIT_AND32, SLJIT_OR, SLJIT_OR32, SLJIT_XOR, or SLJIT_XOR32+ 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 select instruction which moves src1 to dst_reg,+ if the condition is satisfied, or src2_reg to dst_reg otherwise.++ type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL+ type can be combined (or'ed) with SLJIT_32 to move 32 bit+ register values instead of word sized ones+ dst_reg and src2_reg must be valid registers+ src1 must be valid operand++ Note: if src1 is a memory operand, its value+ might be loaded even if the condition is false.++ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg);++/* Emit a conditional floating point select instruction which moves+ src1 to dst_reg, if the condition is satisfied, or src2_reg to+ dst_reg otherwise.++ type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL+ type can be combined (or'ed) with SLJIT_32 to move 32 bit+ floating point values instead of 64 bit ones+ dst_freg and src2_freg must be valid floating point registers+ src1 must be valid operand++ Note: if src1 is a memory operand, its value+ might be loaded even if the condition is false.++ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg);++/* The following flags are used by sljit_emit_mem(), sljit_emit_mem_update(),+ sljit_emit_fmem(), and sljit_emit_fmem_update(). */++/* Memory load operation. This is the default. */+#define SLJIT_MEM_LOAD 0x000000+/* Memory store operation. */+#define SLJIT_MEM_STORE 0x000200++/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */++/* Load or stora data from an unaligned (byte aligned) address. */+#define SLJIT_MEM_UNALIGNED 0x000400+/* Load or stora data from a 16 bit aligned address. */+#define SLJIT_MEM_ALIGNED_16 0x000800+/* Load or stora data from a 32 bit aligned address. */+#define SLJIT_MEM_ALIGNED_32 0x001000++/* The following flags are used by sljit_emit_mem_update(),+ and sljit_emit_fmem_update(). */++/* Base register is updated before the memory access (default). */+#define SLJIT_MEM_PRE 0x000000+/* Base register is updated after the memory access. */+#define SLJIT_MEM_POST 0x000400++/* When SLJIT_MEM_SUPP is passed, no instructions are emitted.+ Instead the function returns with SLJIT_SUCCESS if the instruction+ form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag+ allows runtime checking of available instruction forms. */+#define SLJIT_MEM_SUPP 0x000800++/* The sljit_emit_mem emits instructions for various memory operations:++ When SLJIT_MEM_UNALIGNED / SLJIT_MEM_ALIGNED_16 /+ SLJIT_MEM_ALIGNED_32 is set in type argument:+ Emit instructions for unaligned memory loads or stores. When+ SLJIT_UNALIGNED is not defined, the only way to access unaligned+ memory data is using sljit_emit_mem. Otherwise all operations (e.g.+ sljit_emit_op1/2, or sljit_emit_fop1/2) supports unaligned access.+ In general, the performance of unaligned memory accesses are often+ lower than aligned and should be avoided.++ When a pair of registers is passed in reg argument:+ Emit instructions for moving data between a register pair and+ memory. The register pair can be specified by the SLJIT_REG_PAIR+ macro. The first register is loaded from or stored into the+ location specified by the mem/memw arguments, and the end address+ of this operation is the starting address of the data transfer+ between the second register and memory. The type argument must+ be SLJIT_MOV. The SLJIT_MEM_UNALIGNED / SLJIT_MEM_ALIGNED_*+ options are allowed for this operation.++ type must be between SLJIT_MOV and SLJIT_MOV_P and can be+ combined (or'ed) with SLJIT_MEM_* flags+ reg is a register or register pair, which is the source or+ destination of the operation+ mem must be a memory operand++ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw);++/* Emit a single memory load or store with update instruction.+ When the requested instruction form is not supported by the CPU,+ it returns with SLJIT_ERR_UNSUPPORTED instead of emulating the+ instruction. This allows specializing tight loops based on+ the supported instruction forms (see SLJIT_MEM_SUPP flag).+ Absolute address (SLJIT_MEM0) forms are never supported+ and the base (first) register specified by the mem argument+ must not be SLJIT_SP and must also be different from the+ register specified by the reg argument.++ type must be between SLJIT_MOV and SLJIT_MOV_P and can be+ combined (or'ed) with SLJIT_MEM_* flags+ reg is the source or destination register of the operation+ mem must be a memory operand++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw);++/* Same as sljit_emit_mem except the followings:++ Loading or storing a pair of registers is not supported.++ type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be+ combined (or'ed) with SLJIT_MEM_* flags.+ freg is the source or destination floating point register+ of the operation+ mem must be a memory operand++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw);++/* Same as sljit_emit_mem_update except the followings:++ type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be+ combined (or'ed) with SLJIT_MEM_* flags+ freg is the source or destination floating point register+ of the operation+ mem must be a memory operand++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw);++/* The following options are used by several simd operations. */++/* Load data into a simd register, this is the default */+#define SLJIT_SIMD_LOAD 0x000000+/* Store data from a simd register */+#define SLJIT_SIMD_STORE 0x000001+/* The simd register contains floating point values */+#define SLJIT_SIMD_FLOAT 0x000400+/* Tests whether the operation is available */+#define SLJIT_SIMD_TEST 0x000800+/* Move data to/from a 64 bit (8 byte) long SIMD register */+#define SLJIT_SIMD_REG_64 (3 << 12)+/* Move data to/from a 128 bit (16 byte) long SIMD register */+#define SLJIT_SIMD_REG_128 (4 << 12)+/* Move data to/from a 256 bit (32 byte) long SIMD register */+#define SLJIT_SIMD_REG_256 (5 << 12)+/* Move data to/from a 512 bit (64 byte) long SIMD register */+#define SLJIT_SIMD_REG_512 (6 << 12)+/* Element size is 8 bit long (this is the default), usually cannot be combined with SLJIT_SIMD_FLOAT */+#define SLJIT_SIMD_ELEM_8 (0 << 18)+/* Element size is 16 bit long, usually cannot be combined with SLJIT_SIMD_FLOAT */+#define SLJIT_SIMD_ELEM_16 (1 << 18)+/* Element size is 32 bit long */+#define SLJIT_SIMD_ELEM_32 (2 << 18)+/* Element size is 64 bit long */+#define SLJIT_SIMD_ELEM_64 (3 << 18)+/* Element size is 128 bit long */+#define SLJIT_SIMD_ELEM_128 (4 << 18)+/* Element size is 256 bit long */+#define SLJIT_SIMD_ELEM_256 (5 << 18)++/* The following options are used by sljit_emit_simd_mov(). */++/* Memory address is unaligned (this is the default) */+#define SLJIT_SIMD_MEM_UNALIGNED (0 << 24)+/* Memory address is 16 bit aligned */+#define SLJIT_SIMD_MEM_ALIGNED_16 (1 << 24)+/* Memory address is 32 bit aligned */+#define SLJIT_SIMD_MEM_ALIGNED_32 (2 << 24)+/* Memory address is 64 bit aligned */+#define SLJIT_SIMD_MEM_ALIGNED_64 (3 << 24)+/* Memory address is 128 bit aligned */+#define SLJIT_SIMD_MEM_ALIGNED_128 (4 << 24)+/* Memory address is 256 bit aligned */+#define SLJIT_SIMD_MEM_ALIGNED_256 (5 << 24)+/* Memory address is 512 bit aligned */+#define SLJIT_SIMD_MEM_ALIGNED_512 (6 << 24)++/* Moves data between a simd register and memory.++ If the operation is not supported, it returns with+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,+ it does not emit any instructions.++ type must be a combination of SLJIT_SIMD_* and+ SLJIT_SIMD_MEM_* options+ freg is the source or destination simd register+ of the operation+ srcdst must be a memory operand or a simd register++ Note:+ The alignment and element size must be+ less or equal than simd register size.++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 srcdst, sljit_sw srcdstw);++/* Replicates a scalar value to all lanes of a simd+ register.++ If the operation is not supported, it returns with+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,+ it does not emit any instructions.++ type must be a combination of SLJIT_SIMD_* options+ except SLJIT_SIMD_STORE.+ freg is the destination simd register of the operation+ src is the value which is replicated++ Note:+ The src == SLJIT_IMM and srcw == 0 can be used to+ clear a register even when SLJIT_SIMD_FLOAT is set.++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw);++/* The following options are used by sljit_emit_simd_lane_mov(). */++/* Clear all bits of the simd register before loading the lane. */+#define SLJIT_SIMD_LANE_ZERO 0x000002+/* Sign extend the integer value stored from the lane. */+#define SLJIT_SIMD_LANE_SIGNED 0x000004++/* Moves data between a simd register lane and a register or+ memory. If the srcdst argument is a register, it must be+ a floating point register when SLJIT_SIMD_FLOAT is specified,+ or a general purpose register otherwise.++ If the operation is not supported, it returns with+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,+ it does not emit any instructions.++ type must be a combination of SLJIT_SIMD_* options+ Further options:+ SLJIT_32 - when SLJIT_SIMD_FLOAT is not set+ SLJIT_SIMD_LANE_SIGNED - when SLJIT_SIMD_STORE+ is set and SLJIT_SIMD_FLOAT is not set+ SLJIT_SIMD_LANE_ZERO - when SLJIT_SIMD_LOAD+ is specified+ freg is the source or destination simd register+ of the operation+ lane_index is the index of the lane+ srcdst is the destination operand for loads, and+ source operand for stores++ Note:+ The elem size must be lower than register size.++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw);++/* Replicates a scalar value from a lane to all lanes+ of a simd register.++ If the operation is not supported, it returns with+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,+ it does not emit any instructions.++ type must be a combination of SLJIT_SIMD_* options+ except SLJIT_SIMD_STORE.+ freg is the destination simd register of the operation+ src is the simd register which lane is replicated+ src_lane_index is the lane index of the src register++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_s32 src_lane_index);++/* The following options are used by sljit_emit_simd_load_extend(). */++/* Sign extend the integer elements */+#define SLJIT_SIMD_EXTEND_SIGNED 0x000002+/* Extend data to 16 bit */+#define SLJIT_SIMD_EXTEND_16 (1 << 24)+/* Extend data to 32 bit */+#define SLJIT_SIMD_EXTEND_32 (2 << 24)+/* Extend data to 64 bit */+#define SLJIT_SIMD_EXTEND_64 (3 << 24)++/* Extend elements and stores them in a simd register.+ The extension operation increases the size of the+ elements (e.g. from 16 bit to 64 bit). For integer+ values, the extension can be signed or unsigned.++ If the operation is not supported, it returns with+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,+ it does not emit any instructions.++ type must be a combination of SLJIT_SIMD_*, and+ SLJIT_SIMD_EXTEND_* options except SLJIT_SIMD_STORE+ freg is the destination simd register of the operation+ src must be a memory operand or a simd register.+ In the latter case, the source elements are stored+ in the lower half of the register.++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw);++/* Extract the highest bit (usually the sign bit) from+ each elements of a vector.++ If the operation is not supported, it returns with+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,+ it does not emit any instructions.++ type must be a combination of SLJIT_SIMD_* and SLJIT_32+ options except SLJIT_SIMD_LOAD+ freg is the source simd register of the operation+ dst is the destination operand++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 dst, sljit_sw dstw);++/* The following options are used by sljit_emit_simd_op2(). */++/* Binary 'and' operation */+#define SLJIT_SIMD_OP2_AND 0x000001+/* Binary 'or' operation */+#define SLJIT_SIMD_OP2_OR 0x000002+/* Binary 'xor' operation */+#define SLJIT_SIMD_OP2_XOR 0x000003++/* Perform simd operations using simd registers.++ If the operation is not supported, it returns with+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,+ it does not emit any instructions.++ type must be a combination of SLJIT_SIMD_* and SLJIT_SIMD_OP2_+ options except SLJIT_SIMD_LOAD and SLJIT_SIMD_STORE+ dst_freg is the destination register of the operation+ src1_freg is the first source register of the operation+ src1_freg is the second source register of the operation++ Flags: - (does not modify flags) */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg);++/* The sljit_emit_atomic_load and sljit_emit_atomic_store operation pair+ can perform an atomic read-modify-write operation. First, an unsigned+ value must be loaded from memory using sljit_emit_atomic_load. Then,+ the updated value must be written back to the same memory location by+ sljit_emit_atomic_store. A thread can only perform a single atomic+ operation at a time.++ Note: atomic operations are experimental, and not implemented+ for all cpus.++ The following conditions must be satisfied, or the operation+ is undefined:+ - the address provided in mem_reg must be divisible by the size of+ the value (only naturally aligned updates are supported)+ - no memory writes are allowed between the load and store operations+ regardless of its target address (currently read operations are+ allowed, but this might change in the future)+ - the memory operation (op) and the base address (stored in mem_reg)+ passed to the load/store operations must be the same (the mem_reg+ can be a different register, only its value must be the same)+ - an store must always follow a load for the same transaction.++ op must be between SLJIT_MOV and SLJIT_MOV_P, excluding all+ signed loads such as SLJIT_MOV32_S16+ dst_reg is the register where the data will be loaded into+ mem_reg is the base address of the memory load (it cannot be+ SLJIT_SP or a virtual register on x86-32)++ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 mem_reg);++/* The sljit_emit_atomic_load and sljit_emit_atomic_store operations+ allows performing an atomic read-modify-write operation. See the+ description of sljit_emit_atomic_load.++ op must be between SLJIT_MOV and SLJIT_MOV_P, excluding all signed+ loads such as SLJIT_MOV32_S16+ src_reg is the register which value is stored into the memory+ mem_reg is the base address of the memory store (it cannot be+ SLJIT_SP or a virtual register on x86-32)+ temp_reg is a not preserved scratch register, which must be+ initialized with the value loaded into the dst_reg during the+ corresponding sljit_emit_atomic_load operation, or the operation+ is undefined++ Flags: ATOMIC_STORED is set if the operation is successful,+ otherwise the memory remains unchanged. */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src_reg,+ sljit_s32 mem_reg,+ sljit_s32 temp_reg);++/* Copies the base address of SLJIT_SP + offset to dst. The offset can+ represent the starting address of a value in the local data (stack).+ The offset is not limited by the local data limits, it can be any value.+ For example if an array of bytes are stored on the stack from+ offset 0x40, and R0 contains the offset of an array item plus 0x120,+ this item can be changed by two SLJIT instructions:++ sljit_get_local_base(compiler, SLJIT_R1, 0, 0x40 - 0x120);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_IMM, 0x5);++ 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);++/* Store a value that can be changed runtime (see: sljit_get_const_addr / sljit_set_const)+ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value);++/* Store the value of a label (see: sljit_set_label / sljit_set_target)+ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);++/* Provides the address of label, jump and const instructions after sljit_generate_code+ is called. The returned value is unspecified before the sljit_generate_code call.+ Since these structures are freed by sljit_free_compiler, the addresses must be+ preserved by the user program elsewere. */+static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->u.addr; }+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 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);++/* --------------------------------------------------------------------- */+/* CPU specific functions */+/* --------------------------------------------------------------------- */++/* Types for sljit_get_register_index */++/* General purpose (integer) registers. */+#define SLJIT_GP_REGISTER 0+/* Floating point registers. */+#define SLJIT_FLOAT_REGISTER 1++/* The following function is a helper function for sljit_emit_op_custom.+ It returns with the real machine register index ( >=0 ) of any registers.++ When type is SLJIT_GP_REGISTER:+ reg must be an SLJIT_R(i), SLJIT_S(i), or SLJIT_SP register++ When type is SLJIT_FLOAT_REGISTER:+ reg must be an SLJIT_FR(i) or SLJIT_FS(i) register++ When type is SLJIT_SIMD_REG_64 / 128 / 256 / 512 :+ reg must be an SLJIT_FR(i) or SLJIT_FS(i) register++ Note: it returns with -1 for unknown registers, such as virtual+ registers on x86-32 or unsupported simd registers. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, 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.+ The size parameter must match to the instruction size of the target+ architecture:++ x86: 0 < size <= 15, the instruction argument can be byte aligned.+ Thumb2: if size == 2, the instruction argument must be 2 byte aligned.+ if size == 4, the instruction argument must be 4 byte aligned.+ s390x: size can be 2, 4, or 6, the instruction argument can be byte aligned.+ Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size);++/* Flags were set by a 32 bit operation. */+#define SLJIT_CURRENT_FLAGS_32 SLJIT_32++/* Flags were set by an ADD or ADDC operations. */+#define SLJIT_CURRENT_FLAGS_ADD 0x01+/* Flags were set by a SUB, SUBC, or NEG operation. */+#define SLJIT_CURRENT_FLAGS_SUB 0x02++/* Flags were set by sljit_emit_op2u with SLJIT_SUB opcode.+ Must be combined with SLJIT_CURRENT_FLAGS_SUB. */+#define SLJIT_CURRENT_FLAGS_COMPARE 0x04++/* Define the currently available CPU status flags. It is usually used after+ an sljit_emit_label or sljit_emit_op_custom operations to define which CPU+ status flags are available.++ The current_flags must be a valid combination of SLJIT_SET_* and+ SLJIT_CURRENT_FLAGS_* constants. */++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,+ sljit_s32 current_flags);++/* --------------------------------------------------------------------- */+/* Serialization functions */+/* --------------------------------------------------------------------- */++/* Label/jump/const enumeration functions. The items in each group+ are enumerated in creation order. Serialization / deserialization+ preserves this order for each group. For example the fifth label+ after deserialization refers to the same machine code location as+ the fifth label before the serialization. */+static SLJIT_INLINE struct sljit_label *sljit_get_first_label(struct sljit_compiler *compiler) { return compiler->labels; }+static SLJIT_INLINE struct sljit_jump *sljit_get_first_jump(struct sljit_compiler *compiler) { return compiler->jumps; }+static SLJIT_INLINE struct sljit_const *sljit_get_first_const(struct sljit_compiler *compiler) { return compiler->consts; }++static SLJIT_INLINE struct sljit_label *sljit_get_next_label(struct sljit_label *label) { return label->next; }+static SLJIT_INLINE struct sljit_jump *sljit_get_next_jump(struct sljit_jump *jump) { return jump->next; }+static SLJIT_INLINE struct sljit_const *sljit_get_next_const(struct sljit_const *const_) { return const_->next; }++/* A number starting from 0 is assigned to each label, which+represents its creation index. The first label created by the+compiler has index 0, the second has index 1, the third has+index 2, and so on. The returned value is unspecified after+sljit_generate_code() is called. */+static SLJIT_INLINE sljit_uw sljit_get_label_index(struct sljit_label *label) { return label->u.index; }++/* The sljit_jump_has_label() and sljit_jump_has_target() functions+returns non-zero value if a label or target is set for the jump+respectively. Both may return with a zero value. The other two+functions return the value assigned to the jump. */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_label(struct sljit_jump *jump);+static SLJIT_INLINE struct sljit_label *sljit_jump_get_label(struct sljit_jump *jump) { return jump->u.label; }+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_target(struct sljit_jump *jump);+static SLJIT_INLINE sljit_uw sljit_jump_get_target(struct sljit_jump *jump) { return jump->u.target; }+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_is_mov_addr(struct sljit_jump *jump);++/* Option bits for sljit_serialize_compiler. */++/* When debugging is enabled, the serialized buffer contains+debugging information unless this option is specified. */+#define SLJIT_SERIALIZE_IGNORE_DEBUG 0x1++/* Serialize the internal structure of the compiler into a buffer.+If the serialization is successful, the returned value is a newly+allocated buffer which is allocated by the memory allocator assigned+to the compiler. Otherwise the returned value is NULL. Unlike+sljit_generate_code(), serialization does not modify the internal+state of the compiler, so the code generation can be continued.++ options must be the combination of SLJIT_SERIALIZE_* option bits+ size is an output argument, which is set to the byte size of+ the result buffer if the operation is successful++Notes:+ - This function is useful for ahead-of-time compilation (AOT).+ - The returned buffer must be freed later by the caller.+ The SLJIT_FREE() macro is suitable for this purpose:+ SLJIT_FREE(returned_buffer, sljit_get_allocator_data(compiler))+ - Memory allocated by sljit_alloc_memory() is not serialized.+ - The type of the returned buffer is sljit_uw* to emphasize that+ the buffer is word aligned. However, the 'size' output argument+ contains the byte size, so this value is always divisible by+ sizeof(sljit_uw).+*/+SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_uw *size);++/* Construct a new compiler instance from a buffer produced by+sljit_serialize_compiler(). If the operation is successful, the new+compiler instance is returned. Otherwise the returned value is NULL.++ buffer points to a word aligned memory data which was+ created by sljit_serialize_compiler()+ size is the byte size of the buffer+ options must be 0+ allocator_data specify an allocator specific data, see+ sljit_create_compiler() for further details++Notes:+ - Labels assigned to jumps are restored with their+ corresponding label in the label set created by+ the deserializer. Target addresses assigned to+ jumps are also restored. Uninitialized jumps+ remain uninitialized.+ - After the deserialization, sljit_generate_code() does+ not need to be the next operation on the returned+ compiler, the code generation can be continued.+ Even sljit_serialize_compiler() can be called again.+ - When debugging is enabled, a buffers without debug+ information cannot be deserialized.+*/+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit_uw* buffer, sljit_uw size,+ sljit_s32 options, void *allocator_data);++/* --------------------------------------------------------------------- */+/* Miscellaneous utility functions */+/* --------------------------------------------------------------------- */++/* 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 const char* sljit_get_platform_name(void);++/* Portable helper function to get an offset of a member.+ Same as offsetof() macro defined in stddef.h */+#define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10)++#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)++/* The sljit_stack structure and its manipulation functions provides+ an implementation for a top-down stack. The stack top is stored+ in the end field of the sljit_stack structure and the stack goes+ down to the min_start field, so the memory region reserved for+ this stack is between min_start (inclusive) and end (exclusive)+ fields. However the application can only use the region between+ start (inclusive) and end (exclusive) fields. The sljit_stack_resize+ function can be used to extend this region up to min_start.++ This feature uses the "address space reserve" feature of modern+ operating systems. Instead of allocating a large memory block+ applications can allocate a small memory region and extend it+ later without moving the content of the memory area. Therefore+ after a successful resize by sljit_stack_resize all pointers into+ this region are still valid.++ Note:+ this structure may not be supported by all operating systems.+ end and max_limit fields are aligned to PAGE_SIZE bytes (usually+ 4 Kbyte or more).+ stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more. */++struct sljit_stack {+ /* User data, anything can be stored here.+ Initialized to the same value as the end field. */+ sljit_u8 *top;+/* These members are read only. */+ /* End address of the stack */+ sljit_u8 *end;+ /* Current start address of the stack. */+ sljit_u8 *start;+ /* Lowest start address of the stack. */+ sljit_u8 *min_start;+};++/* Allocates a new stack. Returns NULL if unsuccessful.+ Note: see sljit_create_compiler for the explanation of allocator_data. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data);+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data);++/* Can be used to increase (extend) or decrease (shrink) the stack+ memory area. Returns with new_start if successful and NULL otherwise.+ It always fails if new_start is less than min_start or greater or equal+ than end fields. The fields of the stack are not changed if the returned+ value is NULL (the current memory content is never lost). */+SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start);++#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */++#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)++/* Get the entry address of a given function (signed, unsigned result). */+#define SLJIT_FUNC_ADDR(func_name) ((sljit_sw)func_name)+#define SLJIT_FUNC_UADDR(func_name) ((sljit_uw)func_name)++#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */++/* All JIT related code should be placed in the same context (library, binary, etc.). */++/* Get the entry address of a given function (signed, unsigned result). */+#define SLJIT_FUNC_ADDR(func_name) (*(sljit_sw*)(void*)func_name)+#define SLJIT_FUNC_UADDR(func_name) (*(sljit_uw*)(void*)func_name)++/* For powerpc64, the function pointers point to a context descriptor. */+struct sljit_function_context {+ sljit_uw addr;+ sljit_uw r2;+ sljit_uw r11;+};++/* Fill the context arguments using the addr and the function.+ If func_ptr is NULL, it will not be set to the address of context+ If addr is NULL, the function address also comes from the func pointer. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func);++#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 #ifdef __cplusplus } /* extern "C" */
src/c/pcre2/src/sljit/sljitNativeARM_32.c view
@@ -34,3087 +34,4603 @@ { #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO;-#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- return "ARMv5" SLJIT_CPUINFO ARM_ABI_INFO;-#else-#error "Internal error: Unknown ARM architecture"-#endif-}--/* Last register + 1. */-#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)-#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)-#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4)--#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)-#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)--/* In ARM instruction words.- Cache lines are usually 32 byte aligned. */-#define CONST_POOL_ALIGNMENT 8-#define CONST_POOL_EMPTY 0xffffffff--#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_s32)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))--/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */-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, 12, 14, 15-};--static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {- 0, 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7-};--#define RM(rm) ((sljit_uw)reg_map[rm])-#define RM8(rm) ((sljit_uw)reg_map[rm] << 8)-#define RD(rd) ((sljit_uw)reg_map[rd] << 12)-#define RN(rn) ((sljit_uw)reg_map[rn] << 16)--#define VM(rm) ((sljit_uw)freg_map[rm])-#define VD(rd) ((sljit_uw)freg_map[rd] << 12)-#define VN(rn) ((sljit_uw)freg_map[rn] << 16)--/* --------------------------------------------------------------------- */-/* Instrucion forms */-/* --------------------------------------------------------------------- */--/* The instruction includes the AL condition.- INST_NAME - CONDITIONAL remove this flag. */-#define COND_MASK 0xf0000000-#define CONDITIONAL 0xe0000000-#define PUSH_POOL 0xff000000--#define ADC 0xe0a00000-#define ADD 0xe0800000-#define AND 0xe0000000-#define B 0xea000000-#define BIC 0xe1c00000-#define BL 0xeb000000-#define BLX 0xe12fff30-#define BX 0xe12fff10-#define CLZ 0xe16f0f10-#define CMN 0xe1600000-#define CMP 0xe1400000-#define BKPT 0xe1200070-#define EOR 0xe0200000-#define MOV 0xe1a00000-#define MUL 0xe0000090-#define MVN 0xe1e00000-#define NOP 0xe1a00000-#define ORR 0xe1800000-#define PUSH 0xe92d0000-#define POP 0xe8bd0000-#define RSB 0xe0600000-#define RSC 0xe0e00000-#define SBC 0xe0c00000-#define SMULL 0xe0c00090-#define SUB 0xe0400000-#define TST 0xe1000000-#define UMULL 0xe0800090-#define VABS_F32 0xeeb00ac0-#define VADD_F32 0xee300a00-#define VCMP_F32 0xeeb40a40-#define VCVT_F32_S32 0xeeb80ac0-#define VCVT_F64_F32 0xeeb70ac0-#define VCVT_S32_F32 0xeebd0ac0-#define VDIV_F32 0xee800a00-#define VLDR_F32 0xed100a00-#define VMOV_F32 0xeeb00a40-#define VMOV 0xee000a10-#define VMOV2 0xec400a10-#define VMRS 0xeef1fa10-#define VMUL_F32 0xee200a00-#define VNEG_F32 0xeeb10a40-#define VPOP 0xecbd0b00-#define VPUSH 0xed2d0b00-#define VSTR_F32 0xed000a00-#define VSUB_F32 0xee300a40--#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)-/* Arm v7 specific instructions. */-#define MOVW 0xe3000000-#define MOVT 0xe3400000-#define SXTB 0xe6af0070-#define SXTH 0xe6bf0070-#define UXTB 0xe6ef0070-#define UXTH 0xe6ff0070-#endif--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)--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_s32 i;-- /* The label could point the address after the constant pool. */- if (compiler->last_label && compiler->last_label->size == compiler->size)- compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1;-- SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE);- inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));- FAIL_IF(!inst);- compiler->size++;- *inst = 0xff000000 | compiler->cpool_fill;-- for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) {- inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));- FAIL_IF(!inst);- compiler->size++;- *inst = 0;- }-- cpool_ptr = compiler->cpool;- cpool_end = cpool_ptr + compiler->cpool_fill;- while (cpool_ptr < cpool_end) {- inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));- FAIL_IF(!inst);- compiler->size++;- *inst = *cpool_ptr++;- }- compiler->cpool_diff = CONST_POOL_EMPTY;- compiler->cpool_fill = 0;- return SLJIT_SUCCESS;-}--static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst)-{- sljit_uw* ptr;-- if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))- FAIL_IF(push_cpool(compiler));-- ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));- FAIL_IF(!ptr);- compiler->size++;- *ptr = inst;- return SLJIT_SUCCESS;-}--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_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));- else if (compiler->cpool_fill > 0) {- cpool_ptr = compiler->cpool;- cpool_end = cpool_ptr + compiler->cpool_fill;- cpool_unique_ptr = compiler->cpool_unique;- do {- if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) {- cpool_index = (sljit_uw)(cpool_ptr - compiler->cpool);- break;- }- cpool_ptr++;- cpool_unique_ptr++;- } while (cpool_ptr < cpool_end);- }-- if (cpool_index == CPOOL_SIZE) {- /* Must allocate a new entry in the literal pool. */- if (compiler->cpool_fill < CPOOL_SIZE) {- cpool_index = compiler->cpool_fill;- compiler->cpool_fill++;- }- else {- FAIL_IF(push_cpool(compiler));- cpool_index = 0;- compiler->cpool_fill = 1;- }- }-- SLJIT_ASSERT((inst & 0xfff) == 0);- ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));- FAIL_IF(!ptr);- compiler->size++;- *ptr = inst | cpool_index;-- compiler->cpool[cpool_index] = literal;- compiler->cpool_unique[cpool_index] = 0;- if (compiler->cpool_diff == CONST_POOL_EMPTY)- compiler->cpool_diff = compiler->size;- return SLJIT_SUCCESS;-}--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))- FAIL_IF(push_cpool(compiler));-- SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0);- ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));- FAIL_IF(!ptr);- compiler->size++;- *ptr = inst | compiler->cpool_fill;-- compiler->cpool[compiler->cpool_fill] = literal;- compiler->cpool_unique[compiler->cpool_fill] = 1;- compiler->cpool_fill++;- if (compiler->cpool_diff == CONST_POOL_EMPTY)- compiler->cpool_diff = compiler->size;- return SLJIT_SUCCESS;-}--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)))- return push_cpool(compiler);- return SLJIT_SUCCESS;-}--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));- SLJIT_ASSERT(reg_map[TMP_REG1] != 14);-- return push_inst(compiler, BLX | RM(TMP_REG1));-}--static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)-{- sljit_uw diff;- sljit_uw ind;- sljit_uw counter = 0;- sljit_uw* clear_const_pool = const_pool;- sljit_uw* clear_const_pool_end = const_pool + cpool_size;-- SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT);- /* Set unused flag for all literals in the constant pool.- I.e.: unused literals can belong to branches, which can be encoded as B or BL.- We can "compress" the constant pool by discarding these literals. */- while (clear_const_pool < clear_const_pool_end)- *clear_const_pool++ = (sljit_uw)(-1);-- while (last_pc_patch < code_ptr) {- /* Data transfer instruction with Rn == r15. */- if ((*last_pc_patch & 0x0c0f0000) == 0x040f0000) {- diff = (sljit_uw)(const_pool - last_pc_patch);- ind = (*last_pc_patch) & 0xfff;-- /* 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_s32)const_pool[ind] < 0) {- const_pool[ind] = counter;- ind = counter;- counter++;- }- else- ind = const_pool[ind];-- SLJIT_ASSERT(diff >= 1);- if (diff >= 2 || ind > 0) {- diff = (diff + (sljit_uw)ind - 2) << 2;- SLJIT_ASSERT(diff <= 0xfff);- *last_pc_patch = (*last_pc_patch & ~(sljit_uw)0xfff) | diff;- }- else- *last_pc_patch = (*last_pc_patch & ~(sljit_uw)(0xfff | (1 << 23))) | 0x004;- }- last_pc_patch++;- }- return counter;-}--/* 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_s32 index;- sljit_s32 value;-};--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_u32 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 = cpool_start_address[cpool_current_index];- else {- curr_patch = *first_patch;- prev_patch = NULL;- while (1) {- if (!curr_patch) {- value = cpool_start_address[cpool_current_index];- break;- }- if ((sljit_uw)curr_patch->index == cpool_current_index) {- value = (sljit_uw)curr_patch->value;- if (prev_patch)- prev_patch->next = curr_patch->next;- else- *first_patch = curr_patch->next;- SLJIT_FREE(curr_patch, compiler->allocator_data);- break;- }- prev_patch = curr_patch;- curr_patch = curr_patch->next;- }- }-- if ((sljit_sw)value >= 0) {- if (value > cpool_current_index) {- curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch), compiler->allocator_data);- if (!curr_patch) {- while (*first_patch) {- curr_patch = *first_patch;- *first_patch = (*first_patch)->next;- SLJIT_FREE(curr_patch, compiler->allocator_data);- }- return SLJIT_ERR_ALLOC_FAILED;- }- curr_patch->next = *first_patch;- curr_patch->index = (sljit_sw)value;- curr_patch->value = (sljit_sw)cpool_start_address[value];- *first_patch = curr_patch;- }- cpool_start_address[value] = *buf_ptr;- }- return SLJIT_SUCCESS;-}--#else--static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst)-{- sljit_uw* ptr;-- ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));- FAIL_IF(!ptr);- compiler->size++;- *ptr = inst;- return SLJIT_SUCCESS;-}--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) | ((sljit_u32)imm & 0xfff)));- return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | (((sljit_u32)imm >> 16) & 0xfff));-}--#endif--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;-- if (jump->flags & SLJIT_REWRITABLE_JUMP)- return 0;--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- if (jump->flags & IS_BL)- code_ptr--;-- if (jump->flags & JUMP_ADDR)- 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));- }-- /* Branch to Thumb code has not been optimized yet. */- if (diff & 0x3)- return 0;-- if (jump->flags & IS_BL) {- if (diff <= 0x01ffffff && diff >= -0x02000000) {- *code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK);- jump->flags |= PATCH_B;- return 1;- }- }- else {- if (diff <= 0x01ffffff && diff >= -0x02000000) {- *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK);- jump->flags |= PATCH_B;- }- }-#else- if (jump->flags & JUMP_ADDR)- 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);- }-- /* Branch to Thumb code has not been optimized yet. */- if (diff & 0x3)- return 0;-- if (diff <= 0x01ffffff && diff >= -0x02000000) {- code_ptr -= 2;- *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK);- jump->flags |= PATCH_B;- return 1;- }-#endif- return 0;-}--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 *)jump_ptr;- sljit_uw *inst = (sljit_uw *)ptr[0];- sljit_uw mov_pc = ptr[1];- 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);-- SLJIT_UNUSED_ARG(executable_offset);-- if (diff <= 0x7fffff && diff >= -0x800000) {- /* Turn to branch. */- if (!bl) {- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);- }- inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);- inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 1);- }- } else {- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);- }- inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);- inst[1] = NOP;- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);- inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 2);- }- }- } else {- /* Get the position of the constant. */- if (mov_pc & (1 << 23))- ptr = inst + ((mov_pc & 0xfff) >> 2) + 2;- else- ptr = inst + 1;-- if (*inst != mov_pc) {- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + (!bl ? 1 : 2), 0);- }- inst[0] = mov_pc;- if (!bl) {- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);- 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_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);- inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 2);- }- }- }-- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);- }-- *ptr = new_addr;-- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);- }- }-#else- sljit_uw *inst = (sljit_uw*)jump_ptr;-- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);-- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);- }-- 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_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);- inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 2);- }-#endif-}--static sljit_uw get_imm(sljit_uw imm);-static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm);--static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, 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 ldr_literal = ptr[1];- sljit_uw src2;-- SLJIT_UNUSED_ARG(executable_offset);-- src2 = get_imm(new_constant);- if (src2) {- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);- }-- *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;-- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);- inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 1);- }- return;- }-- src2 = get_imm(~new_constant);- if (src2) {- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);- }-- *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;-- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);- inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 1);- }- return;- }-- if (ldr_literal & (1 << 23))- ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2;- else- ptr = inst + 1;-- if (*inst != ldr_literal) {- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);- }-- *inst = ldr_literal;-- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);- inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 1);- }- }-- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);- }-- *ptr = new_constant;-- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);- }-#else- sljit_uw *inst = (sljit_uw*)addr;-- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);-- if (flush_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);- }-- 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_cache) {- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);- inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 2);- }-#endif-}--SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)-{- struct sljit_memory_fragment *buf;- sljit_uw *code;- sljit_uw *code_ptr;- sljit_uw *buf_ptr;- sljit_uw *buf_end;- sljit_uw size;- sljit_uw word_count;- sljit_uw next_addr;- sljit_sw executable_offset;- sljit_uw addr;-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- sljit_uw cpool_size;- sljit_uw cpool_skip_alignment;- sljit_uw cpool_current_index;- sljit_uw *cpool_start_address;- sljit_uw *last_pc_patch;- struct future_patch *first_patch;-#endif-- struct sljit_label *label;- struct sljit_jump *jump;- struct sljit_const *const_;- struct sljit_put_label *put_label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_generate_code(compiler));- reverse_buf(compiler);-- /* Second code generation pass. */-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- size = compiler->size + (compiler->patches << 1);- if (compiler->cpool_fill > 0)- size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1;-#else- size = compiler->size;-#endif- code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw), compiler->exec_allocator_data);- PTR_FAIL_WITH_EXEC_IF(code);- buf = compiler->buf;--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- cpool_size = 0;- cpool_skip_alignment = 0;- cpool_current_index = 0;- cpool_start_address = NULL;- first_patch = NULL;- last_pc_patch = code;-#endif-- code_ptr = code;- word_count = 0;- next_addr = 1;- executable_offset = SLJIT_EXEC_OFFSET(code);-- label = compiler->labels;- jump = compiler->jumps;- const_ = compiler->consts;- put_label = compiler->put_labels;-- if (label && label->size == 0) {- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);- label = label->next;- }-- do {- buf_ptr = (sljit_uw*)buf->memory;- buf_end = buf_ptr + (buf->used_size >> 2);- do {- word_count++;-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- if (cpool_size > 0) {- if (cpool_skip_alignment > 0) {- buf_ptr++;- cpool_skip_alignment--;- }- else {- if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {- SLJIT_FREE_EXEC(code, compiler->exec_allocator_data);- compiler->error = SLJIT_ERR_ALLOC_FAILED;- return NULL;- }- buf_ptr++;- if (++cpool_current_index >= cpool_size) {- SLJIT_ASSERT(!first_patch);- cpool_size = 0;- if (label && label->size == word_count) {- /* Points after the current instruction. */- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- label->size = (sljit_uw)(code_ptr - code);- label = label->next;-- next_addr = compute_next_addr(label, jump, const_, put_label);- }- }- }- }- else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {-#endif- *code_ptr = *buf_ptr++;- if (next_addr == word_count) {- SLJIT_ASSERT(!label || label->size >= word_count);- SLJIT_ASSERT(!jump || jump->addr >= word_count);- SLJIT_ASSERT(!const_ || const_->addr >= word_count);- SLJIT_ASSERT(!put_label || put_label->addr >= word_count);-- /* These structures are ordered by their address. */- if (jump && jump->addr == word_count) {-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- if (detect_jump_type(jump, code_ptr, code, executable_offset))- code_ptr--;- jump->addr = (sljit_uw)code_ptr;-#else- jump->addr = (sljit_uw)(code_ptr - 2);- if (detect_jump_type(jump, code_ptr, code, executable_offset))- code_ptr -= 2;-#endif- jump = jump->next;- }- if (label && label->size == word_count) {- /* code_ptr can be affected above. */- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);- label->size = (sljit_uw)((code_ptr + 1) - code);- label = label->next;- }- if (const_ && const_->addr == word_count) {-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- const_->addr = (sljit_uw)code_ptr;-#else- const_->addr = (sljit_uw)(code_ptr - 1);-#endif- const_ = const_->next;- }- if (put_label && put_label->addr == word_count) {- SLJIT_ASSERT(put_label->label);- put_label->addr = (sljit_uw)code_ptr;- put_label = put_label->next;- }- next_addr = compute_next_addr(label, jump, const_, put_label);- }- code_ptr++;-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- }- else {- /* Fortunately, no need to shift. */- cpool_size = *buf_ptr++ & ~PUSH_POOL;- SLJIT_ASSERT(cpool_size > 0);- cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1);- cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size);- if (cpool_current_index > 0) {- /* Unconditional branch. */- *code_ptr = B | (((sljit_uw)(cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);- code_ptr = (sljit_uw*)(cpool_start_address + cpool_current_index);- }- cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1;- cpool_current_index = 0;- last_pc_patch = code_ptr;- }-#endif- } while (buf_ptr < buf_end);- buf = buf->next;- } while (buf);-- SLJIT_ASSERT(!label);- SLJIT_ASSERT(!jump);- SLJIT_ASSERT(!const_);- SLJIT_ASSERT(!put_label);--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- SLJIT_ASSERT(cpool_size == 0);- if (compiler->cpool_fill > 0) {- cpool_start_address = ALIGN_INSTRUCTION(code_ptr);- cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill);- if (cpool_current_index > 0)- code_ptr = (sljit_uw*)(cpool_start_address + cpool_current_index);-- buf_ptr = compiler->cpool;- buf_end = buf_ptr + compiler->cpool_fill;- cpool_current_index = 0;- while (buf_ptr < buf_end) {- if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {- SLJIT_FREE_EXEC(code, compiler->exec_allocator_data);- compiler->error = SLJIT_ERR_ALLOC_FAILED;- return NULL;- }- buf_ptr++;- cpool_current_index++;- }- SLJIT_ASSERT(!first_patch);- }-#endif-- jump = compiler->jumps;- while (jump) {- buf_ptr = (sljit_uw *)jump->addr;-- if (jump->flags & PATCH_B) {- addr = (sljit_uw)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 - addr) <= 0x01ffffff && (sljit_sw)(jump->u.label->addr - addr) >= -0x02000000);- *buf_ptr |= ((jump->u.label->addr - addr) >> 2) & 0x00ffffff;- }- else {- SLJIT_ASSERT((sljit_sw)(jump->u.target - addr) <= 0x01ffffff && (sljit_sw)(jump->u.target - addr) >= -0x02000000);- *buf_ptr |= ((jump->u.target - addr) >> 2) & 0x00ffffff;- }- }- else if (jump->flags & SLJIT_REWRITABLE_JUMP) {-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- 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, 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, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);-#endif- }- else {-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- if (jump->flags & IS_BL)- buf_ptr--;- if (*buf_ptr & (1 << 23))- buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;- else- 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, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);-#endif- }- jump = jump->next;- }--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- const_ = compiler->consts;- while (const_) {- buf_ptr = (sljit_uw*)const_->addr;- const_->addr = (sljit_uw)code_ptr;-- code_ptr[0] = (sljit_uw)buf_ptr;- code_ptr[1] = *buf_ptr;- if (*buf_ptr & (1 << 23))- buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;- else- buf_ptr += 1;- /* Set the value again (can be a simple constant). */- inline_set_const((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);- code_ptr += 2;-- const_ = const_->next;- }-#endif-- put_label = compiler->put_labels;- while (put_label) {- addr = put_label->label->addr;- buf_ptr = (sljit_uw*)put_label->addr;--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- SLJIT_ASSERT((buf_ptr[0] & 0xffff0000) == 0xe59f0000);- buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr;-#else- SLJIT_ASSERT((buf_ptr[-1] & 0xfff00000) == MOVW && (buf_ptr[0] & 0xfff00000) == MOVT);- buf_ptr[-1] |= ((addr << 4) & 0xf0000) | (addr & 0xfff);- buf_ptr[0] |= ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff);-#endif- put_label = put_label->next;- }-- SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size);-- compiler->error = SLJIT_ERR_COMPILED;- compiler->executable_offset = executable_offset;- compiler->executable_size = (sljit_uw)(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);- SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);- 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_CLZ:- case SLJIT_HAS_CMOV:-#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)- case SLJIT_HAS_PREFETCH:-#endif- return 1;-- default:- return 0;- }-}--/* --------------------------------------------------------------------- */-/* Entry, exit */-/* --------------------------------------------------------------------- */--/* Creates an index in data_transfer_insts array. */-#define WORD_SIZE 0x00-#define BYTE_SIZE 0x01-#define HALF_SIZE 0x02-#define PRELOAD 0x03-#define SIGNED 0x04-#define LOAD_DATA 0x08--/* Flag bits for emit_op. */-#define ALLOW_IMM 0x10-#define ALLOW_INV_IMM 0x20-#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM)-#define ALLOW_NEG_IMM 0x40--/* 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 */,-/* 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, target_reg, base_reg, arg) \- (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (sljit_uw)(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))--#define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \- ((sljit_uw)(opcode) | (sljit_uw)(mode) | VD(dst) | VM(src1) | VN(src2))--/* Flags for emit_op: */- /* Arguments are swapped. */-#define ARGS_SWAPPED 0x01- /* Inverted immediate. */-#define INV_IMM 0x02- /* Source and destination is register. */-#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- src1: reg- src2: reg or imm (if allowed)- 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)--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_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_uw imm, offset;- sljit_s32 i, tmp, size, word_arg_count, saved_arg_count;-#ifdef __SOFTFP__- sljit_u32 float_arg_count;-#else- sljit_u32 old_offset, f32_offset;- sljit_u32 remap[3];- sljit_u32 *remap_ptr = remap;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- imm = 0;-- tmp = SLJIT_S0 - saveds;- for (i = SLJIT_S0; i > tmp; i--)- imm |= (sljit_uw)1 << reg_map[i];-- for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)- imm |= (sljit_uw)1 << reg_map[i];-- SLJIT_ASSERT(reg_map[TMP_REG2] == 14);-- /* Push saved and temporary registers- multiple registers: stmdb sp!, {..., lr}- single register: str reg, [sp, #-4]! */- if (imm != 0)- FAIL_IF(push_inst(compiler, PUSH | (1 << 14) | imm));- else- FAIL_IF(push_inst(compiler, 0xe52d0004 | RD(TMP_REG2)));-- /* Stack must be aligned to 8 bytes: */- size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);-- if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {- if ((size & SSIZE_OF(sw)) != 0) {- FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | sizeof(sljit_sw)));- size += SSIZE_OF(sw);- }-- if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {- FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));- } else {- if (fsaveds > 0)- FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));- if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)- FAIL_IF(push_inst(compiler, VPUSH | VD(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));- }- }-- local_size = ((size + local_size + 0x7) & ~0x7) - size;- compiler->local_size = local_size;-- arg_types >>= SLJIT_ARG_SHIFT;- word_arg_count = 0;- saved_arg_count = 0;-#ifdef __SOFTFP__- SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);-- offset = 0;- float_arg_count = 0;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (offset & 0x7)- offset += sizeof(sljit_sw);-- if (offset < 4 * sizeof(sljit_sw))- FAIL_IF(push_inst(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));- else- FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800100 | RN(SLJIT_SP)- | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));- float_arg_count++;- offset += sizeof(sljit_f64) - sizeof(sljit_sw);- break;- case SLJIT_ARG_TYPE_F32:- if (offset < 4 * sizeof(sljit_sw))- FAIL_IF(push_inst(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));- else- FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800000 | RN(SLJIT_SP)- | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));- float_arg_count++;- break;- default:- word_arg_count++;-- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- tmp = SLJIT_S0 - saved_arg_count;- saved_arg_count++;- } else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))- tmp = word_arg_count;- else- break;-- if (offset < 4 * sizeof(sljit_sw))- FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));- else- FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000- | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw))));- break;- }-- offset += sizeof(sljit_sw);- arg_types >>= SLJIT_ARG_SHIFT;- }-- compiler->args_size = offset;-#else- offset = SLJIT_FR0;- old_offset = SLJIT_FR0;- f32_offset = 0;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (offset != old_offset)- *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, SLJIT_32, offset, old_offset, 0);- old_offset++;- offset++;- break;- case SLJIT_ARG_TYPE_F32:- if (f32_offset != 0) {- *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0x20, offset, f32_offset, 0);- f32_offset = 0;- } else {- if (offset != old_offset)- *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0, offset, old_offset, 0);- f32_offset = old_offset;- old_offset++;- }- offset++;- break;- default:- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0 - saved_arg_count) | RM(SLJIT_R0 + word_arg_count)));- saved_arg_count++;- }-- word_arg_count++;- break;- }- arg_types >>= SLJIT_ARG_SHIFT;- }-- SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));-- while (remap_ptr > remap)- FAIL_IF(push_inst(compiler, *(--remap_ptr)));-#endif-- if (local_size > 0)- FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 size;-- CHECK_ERROR();- CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);-- if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))- size += SSIZE_OF(sw);-- compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;- return SLJIT_SUCCESS;-}--static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)-{- sljit_uw imm2 = get_imm(imm);-- if (imm2 == 0) {- FAIL_IF(load_immediate(compiler, TMP_REG2, imm));- imm2 = RM(TMP_REG2);- }-- return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | imm2);-}--static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)-{- sljit_s32 local_size, fscratches, fsaveds, i, tmp;- sljit_s32 lr_dst = TMP_PC;- sljit_uw reg_list;-- SLJIT_ASSERT(reg_map[TMP_REG2] == 14);-- local_size = compiler->local_size;- fscratches = compiler->fscratches;- fsaveds = compiler->fsaveds;-- if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {- if (local_size > 0)- FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));-- if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {- FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));- } else {- if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)- FAIL_IF(push_inst(compiler, VPOP | VD(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));- if (fsaveds > 0)- FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));- }-- local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;- }-- if (frame_size < 0) {- lr_dst = TMP_REG2;- frame_size = 0;- } else if (frame_size > 0)- lr_dst = 0;-- reg_list = 0;- if (lr_dst != 0)- reg_list |= (sljit_uw)1 << reg_map[lr_dst];-- tmp = SLJIT_S0 - compiler->saveds;- for (i = SLJIT_S0; i > tmp; i--)- reg_list |= (sljit_uw)1 << reg_map[i];-- for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)- reg_list |= (sljit_uw)1 << reg_map[i];-- if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {- /* The local_size does not include the saved registers. */- local_size += SSIZE_OF(sw);-- if (reg_list != 0)- local_size += SSIZE_OF(sw);-- if (frame_size > local_size)- FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_uw)(frame_size - local_size)));- else if (frame_size < local_size)- FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));-- if (reg_list == 0)- return SLJIT_SUCCESS;-- if (compiler->saveds > 0) {- SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_S0]));- lr_dst = SLJIT_S0;- } else {- SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_FIRST_SAVED_REG]));- lr_dst = SLJIT_FIRST_SAVED_REG;- }-- return push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000- | RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw)));- }-- if (local_size > 0)- FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));-- /* Pop saved and temporary registers- multiple registers: ldmia sp!, {...}- single register: ldr reg, [sp], #4 */- if ((reg_list & (reg_list - 1)) == 0) {- SLJIT_ASSERT(lr_dst != 0);- SLJIT_ASSERT(reg_list == (sljit_uw)1 << reg_map[lr_dst]);-- return push_inst(compiler, 0xe49d0004 | RD(lr_dst));- }-- FAIL_IF(push_inst(compiler, POP | reg_list));- if (frame_size > 0)- return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_uw)frame_size - sizeof(sljit_sw)));- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)-{- CHECK_ERROR();- CHECK(check_sljit_emit_return_void(compiler));-- return emit_stack_frame_release(compiler, 0);-}--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--#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, MOV | (flags & SET_FLAGS) | \- RD(dst) | (compiler->shift_imm << 7) | (opcode << 5) | RM(src2)); \- return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); \- } \- return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) \- | RM8((flags & ARGS_SWAPPED) ? src1 : src2) | (sljit_uw)(opcode << 5) \- | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1));--static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,- sljit_uw dst, sljit_uw src1, sljit_uw src2)-{- switch (GET_OPCODE(op)) {- case SLJIT_MOV:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));- if (dst != src2) {- if (src2 & SRC2_IMM) {- return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);- }- return push_inst(compiler, MOV | RD(dst) | RM(src2));- }- return SLJIT_SUCCESS;-- case SLJIT_MOV_U8:- case SLJIT_MOV_S8:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));- if (flags & MOVE_REG_CONV) {-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- if (op == SLJIT_MOV_U8)- return push_inst(compiler, AND | RD(dst) | RN(src2) | SRC2_IMM | 0xff);- FAIL_IF(push_inst(compiler, MOV | RD(dst) | (24 << 7) | RM(src2)));- return push_inst(compiler, MOV | RD(dst) | (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | RM(dst));-#else- return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2));-#endif- }- else if (dst != src2) {- SLJIT_ASSERT(src2 & SRC2_IMM);- return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);- }- return SLJIT_SUCCESS;-- case SLJIT_MOV_U16:- case SLJIT_MOV_S16:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));- if (flags & MOVE_REG_CONV) {-#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- FAIL_IF(push_inst(compiler, MOV | RD(dst) | (16 << 7) | RM(src2)));- return push_inst(compiler, MOV | RD(dst) | (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | RM(dst));-#else- return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2));-#endif- }- else if (dst != src2) {- SLJIT_ASSERT(src2 & SRC2_IMM);- return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);- }- return SLJIT_SUCCESS;-- case SLJIT_NOT:- if (src2 & SRC2_IMM)- return push_inst(compiler, ((flags & INV_IMM) ? MOV : MVN) | (flags & SET_FLAGS) | RD(dst) | src2);-- return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | 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)));- return SLJIT_SUCCESS;-- case SLJIT_ADD:- SLJIT_ASSERT(!(flags & INV_IMM));-- if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)- return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));- return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));-- case SLJIT_ADDC:- SLJIT_ASSERT(!(flags & INV_IMM));- return push_inst(compiler, ADC | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));-- case SLJIT_SUB:- SLJIT_ASSERT(!(flags & INV_IMM));-- if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)- return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));-- return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS)- | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));-- case SLJIT_SUBC:- SLJIT_ASSERT(!(flags & INV_IMM));- return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SBC : RSC) | (flags & SET_FLAGS)- | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));-- case SLJIT_MUL:- SLJIT_ASSERT(!(flags & INV_IMM));- SLJIT_ASSERT(!(src2 & SRC2_IMM));- compiler->status_flags_state = 0;-- if (!HAS_FLAGS(op))- return push_inst(compiler, MUL | RN(dst) | RM8(src2) | RM(src1));-- FAIL_IF(push_inst(compiler, SMULL | RN(TMP_REG1) | RD(dst) | RM8(src2) | RM(src1)));-- /* cmp TMP_REG1, dst asr #31. */- return push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | RM(dst) | 0xfc0);-- case SLJIT_AND:- if ((flags & (UNUSED_RETURN | INV_IMM)) == UNUSED_RETURN)- return push_inst(compiler, TST | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));- return push_inst(compiler, (!(flags & INV_IMM) ? AND : BIC) | (flags & SET_FLAGS)- | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));-- case SLJIT_OR:- SLJIT_ASSERT(!(flags & INV_IMM));- return push_inst(compiler, ORR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));-- case SLJIT_XOR:- SLJIT_ASSERT(!(flags & INV_IMM));- return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));-- case SLJIT_SHL:- EMIT_SHIFT_INS_AND_RETURN(0);-- case SLJIT_LSHR:- EMIT_SHIFT_INS_AND_RETURN(1);-- case SLJIT_ASHR:- EMIT_SHIFT_INS_AND_RETURN(2);- }-- SLJIT_UNREACHABLE();- return SLJIT_SUCCESS;-}--#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_u32 rol;-- if (imm <= 0xff)- return SRC2_IMM | imm;-- if (!(imm & 0xff000000)) {- imm <<= 8;- rol = 8;- }- else {- imm = (imm << 24) | (imm >> 8);- rol = 0;- }-- if (!(imm & 0xff000000)) {- imm <<= 8;- rol += 4;- }-- if (!(imm & 0xf0000000)) {- imm <<= 4;- rol += 2;- }-- if (!(imm & 0xc0000000)) {- imm <<= 2;- rol += 1;- }-- if (!(imm & 0x00ffffff))- return SRC2_IMM | (imm >> 24) | (rol << 8);- else- return 0;-}--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)-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_uw rol;-- /* Step1: Search a zero byte (8 continous zero bit). */- mask = 0xff000000;- rol = 8;- while(1) {- if (!(imm & mask)) {- /* Rol imm by rol. */- imm = (imm << rol) | (imm >> (32 - rol));- /* Calculate arm rol. */- rol = 4 + (rol >> 1);- break;- }- rol += 2;- mask >>= 2;- if (mask & 0x3) {- /* rol by 8. */- imm = (imm << 8) | (imm >> 24);- mask = 0xff00;- rol = 24;- while (1) {- if (!(imm & mask)) {- /* Rol imm by rol. */- imm = (imm << rol) | (imm >> (32 - rol));- /* Calculate arm rol. */- rol = (rol >> 1) - 8;- break;- }- rol += 2;- mask >>= 2;- if (mask & 0x3)- return 0;- }- break;- }- }-- /* The low 8 bit must be zero. */- SLJIT_ASSERT(!(imm & 0xff));-- if (!(imm & 0xff000000)) {- imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);- imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);- }- else if (imm & 0xc0000000) {- imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);- imm <<= 8;- rol += 4;-- if (!(imm & 0xff000000)) {- imm <<= 8;- rol += 4;- }-- if (!(imm & 0xf0000000)) {- imm <<= 4;- rol += 2;- }-- if (!(imm & 0xc0000000)) {- imm <<= 2;- rol += 1;- }-- if (!(imm & 0x00ffffff))- imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);- else- return 0;- }- else {- if (!(imm & 0xf0000000)) {- imm <<= 4;- rol += 2;- }-- if (!(imm & 0xc0000000)) {- imm <<= 2;- rol += 1;- }-- imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);- imm <<= 8;- rol += 4;-- if (!(imm & 0xf0000000)) {- imm <<= 4;- rol += 2;- }-- if (!(imm & 0xc0000000)) {- imm <<= 2;- rol += 1;- }-- if (!(imm & 0x00ffffff))- imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);- else- return 0;- }-- FAIL_IF(push_inst(compiler, (positive ? MOV : MVN) | RD(reg) | imm1));- FAIL_IF(push_inst(compiler, (positive ? ORR : BIC) | RD(reg) | RN(reg) | imm2));- return 1;-}-#endif--static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm)-{- sljit_uw tmp;--#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)- if (!(imm & ~(sljit_uw)0xffff))- return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff));-#endif-- /* Create imm by 1 inst. */- tmp = get_imm(imm);- if (tmp)- return push_inst(compiler, MOV | RD(reg) | tmp);-- tmp = get_imm(~imm);- if (tmp)- return push_inst(compiler, MVN | RD(reg) | tmp);--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- /* Create imm by 2 inst. */- FAIL_IF(generate_int(compiler, reg, imm, 1));- FAIL_IF(generate_int(compiler, reg, ~imm, 0));-- /* Load integer. */- return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm);-#else- 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-}--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_uw imm, offset_reg;- sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags);-- SLJIT_ASSERT (arg & SLJIT_MEM);- SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);-- if (!(arg & REG_MASK)) {- if (is_type1_transfer) {- FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xfff));- argw &= 0xfff;- }- else {- FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xff));- argw &= 0xff;- }-- return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg,- is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw)));- }-- if (arg & OFFS_REG_MASK) {- offset_reg = OFFS_REG(arg);- arg &= REG_MASK;- argw &= 0x3;-- if (argw != 0 && !is_type1_transfer) {- FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_uw)argw << 7)));- return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));- }-- /* Bit 25: RM is offset. */- return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,- RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | ((sljit_uw)argw << 7)));- }-- arg &= REG_MASK;-- if (is_type1_transfer) {- if (argw > 0xfff) {- imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);- if (imm) {- FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));- argw = argw & 0xfff;- arg = tmp_reg;- }- }- else if (argw < -0xfff) {- imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xfff);- if (imm) {- FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));- argw = -(-argw & 0xfff);- arg = tmp_reg;- }- }-- if (argw >= 0 && argw <= 0xfff)- return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));-- if (argw < 0 && argw >= -0xfff)- return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, -argw));- }- else {- if (argw > 0xff) {- imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xff);- if (imm) {- FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));- argw = argw & 0xff;- arg = tmp_reg;- }- }- else if (argw < -0xff) {- imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff);- if (imm) {- FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));- argw = -(-argw & 0xff);- arg = tmp_reg;- }- }-- if (argw >= 0 && argw <= 0xff)- return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw)));-- if (argw < 0 && argw >= -0xff) {- argw = -argw;- return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, TYPE2_TRANSFER_IMM(argw)));- }- }-- FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));- return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,- RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0)));-}--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)-{- /* 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. */-- /* We prefers register and simple consts. */- sljit_s32 dst_reg;- sljit_s32 src1_reg;- sljit_s32 src2_reg = 0;- sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;- sljit_s32 neg_op = 0;-- if (dst == TMP_REG2)- flags |= UNUSED_RETURN;-- SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));-- if (inp_flags & ALLOW_NEG_IMM) {- switch (GET_OPCODE(op)) {- case SLJIT_ADD:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- neg_op = SLJIT_SUB;- break;- case SLJIT_ADDC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- neg_op = SLJIT_SUBC;- break;- case SLJIT_SUB:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- neg_op = SLJIT_ADD;- break;- case SLJIT_SUBC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- neg_op = SLJIT_ADDC;- break;- }- }-- do {- if (!(inp_flags & ALLOW_IMM))- break;-- if (src2 & SLJIT_IMM) {- src2_reg = (sljit_s32)get_imm((sljit_uw)src2w);- if (src2_reg)- break;- if (inp_flags & ALLOW_INV_IMM) {- src2_reg = (sljit_s32)get_imm(~(sljit_uw)src2w);- if (src2_reg) {- flags |= INV_IMM;- break;- }- }- if (neg_op != 0) {- src2_reg = (sljit_s32)get_imm((sljit_uw)-src2w);- if (src2_reg) {- op = neg_op | GET_ALL_FLAGS(op);- break;- }- }- }-- if (src1 & SLJIT_IMM) {- src2_reg = (sljit_s32)get_imm((sljit_uw)src1w);- if (src2_reg) {- flags |= ARGS_SWAPPED;- src1 = src2;- src1w = src2w;- break;- }- if (inp_flags & ALLOW_INV_IMM) {- src2_reg = (sljit_s32)get_imm(~(sljit_uw)src1w);- if (src2_reg) {- flags |= ARGS_SWAPPED | INV_IMM;- src1 = src2;- src1w = src2w;- break;- }- }- if (neg_op >= SLJIT_SUB) {- /* Note: additive operation (commutative). */- src2_reg = (sljit_s32)get_imm((sljit_uw)-src1w);- if (src2_reg) {- src1 = src2;- src1w = src2w;- op = neg_op | GET_ALL_FLAGS(op);- break;- }- }- }- } 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, (sljit_uw)src1w));- src1_reg = TMP_REG1;- }-- /* Destination. */- dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG2;-- if (op <= SLJIT_MOV_P) {- if (dst & SLJIT_MEM) {- if (inp_flags & BYTE_SIZE)- inp_flags &= ~SIGNED;-- if (FAST_IS_REG(src2))- return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG2);- }-- if (FAST_IS_REG(src2) && dst_reg != TMP_REG2)- flags |= MOVE_REG_CONV;- }-- /* Source 2. */- if (src2_reg == 0) {- src2_reg = (op <= SLJIT_MOV_P) ? dst_reg : TMP_REG2;-- 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, (sljit_uw)src2w));- }-- FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg));-- if (!(dst & SLJIT_MEM))- return SLJIT_SUCCESS;-- return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1);-}--#ifdef __cplusplus-extern "C" {-#endif--#if defined(__GNUC__)-extern unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator);-extern int __aeabi_idivmod(int numerator, int denominator);-#else-#error "Software divmod functions are needed"-#endif--#ifdef __cplusplus-}-#endif--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)-{- sljit_uw saved_reg_list[3];- sljit_sw saved_reg_count;-- CHECK_ERROR();- CHECK(check_sljit_emit_op0(compiler, op));-- op = GET_OPCODE(op);- switch (op) {- case SLJIT_BREAKPOINT:- FAIL_IF(push_inst(compiler, BKPT));- break;- case SLJIT_NOP:- FAIL_IF(push_inst(compiler, NOP));- break;- case SLJIT_LMUL_UW:- case SLJIT_LMUL_SW:- return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)- | RN(SLJIT_R1) | RD(SLJIT_R0) | RM8(SLJIT_R0) | RM(SLJIT_R1));- 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] */));- }- }--#if defined(__GNUC__)- FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,- ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));-#else-#error "Software divmod functions are needed"-#endif-- 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 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8)- | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);- }- return SLJIT_SUCCESS;- case SLJIT_ENDBR:- case SLJIT_SKIP_FRAMES_BEFORE_RETURN:- return SLJIT_SUCCESS;- }-- return SLJIT_SUCCESS;-}--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);-- switch (GET_OPCODE(op)) {- case SLJIT_MOV:- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:- case SLJIT_MOV_P:- return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);-- case SLJIT_MOV_U8:- return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);-- case SLJIT_MOV_S8:- return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);-- case SLJIT_MOV_U16:- return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);-- case SLJIT_MOV_S16:- return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, 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);-- case SLJIT_CLZ:- return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);- }-- return SLJIT_SUCCESS;-}--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, 0, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- switch (GET_OPCODE(op)) {- case SLJIT_ADD:- case SLJIT_ADDC:- case SLJIT_SUB:- case SLJIT_SUBC:- return emit_op(compiler, op, ALLOW_IMM | ALLOW_NEG_IMM, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_OR:- case SLJIT_XOR:- return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_MUL:- return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_AND:- return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_SHL:- case SLJIT_LSHR:- case SLJIT_ASHR:- if (src2 & SLJIT_IMM) {- compiler->shift_imm = src2w & 0x1f;- return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w);- }- else {- compiler->shift_imm = 0x20;- return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);- }- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 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_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- switch (op) {- case SLJIT_FAST_RETURN:- SLJIT_ASSERT(reg_map[TMP_REG2] == 14);-- if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));- else- FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));-- return push_inst(compiler, BX | RM(TMP_REG2));- case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:- return SLJIT_SUCCESS;- case SLJIT_PREFETCH_L1:- case SLJIT_PREFETCH_L2:- case SLJIT_PREFETCH_L3:- case SLJIT_PREFETCH_ONCE:-#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)- SLJIT_ASSERT(src & SLJIT_MEM);- return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);-#else /* !SLJIT_CONFIG_ARM_V7 */- return SLJIT_SUCCESS;-#endif /* SLJIT_CONFIG_ARM_V7 */- }-- return SLJIT_SUCCESS;-}--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_s32 sljit_get_float_register_index(sljit_s32 reg)-{- CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));- return (freg_map[reg] << 1);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{- SLJIT_UNUSED_ARG(size);- CHECK_ERROR();- CHECK(check_sljit_emit_op_custom(compiler, instruction, size));-- return push_inst(compiler, *(sljit_uw*)instruction);-}--/* --------------------------------------------------------------------- */-/* Floating point operators */-/* --------------------------------------------------------------------- */--#define FPU_LOAD (1 << 20)-#define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \- ((inst) | (sljit_uw)((add) << 23) | RN(base) | VD(freg) | (sljit_uw)(offs))--static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)-{- sljit_uw imm;- sljit_uw inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD));-- SLJIT_ASSERT(arg & SLJIT_MEM);- arg &= ~SLJIT_MEM;-- if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {- FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (((sljit_uw)argw & 0x3) << 7)));- arg = TMP_REG2;- argw = 0;- }-- /* Fast loads and stores. */- 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));-- imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);- if (imm) {- FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | imm));- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, (argw & 0x3fc) >> 2));- }- imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);- if (imm) {- argw = -argw;- FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG2) | RN(arg & REG_MASK) | imm));- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG2, reg, (argw & 0x3fc) >> 2));- }- }-- if (arg) {- FAIL_IF(load_immediate(compiler, TMP_REG2, (sljit_uw)argw));- FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(TMP_REG2)));- }- else- FAIL_IF(load_immediate(compiler, TMP_REG2, (sljit_uw)argw));-- return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, 0));-}--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_32;-- if (src & SLJIT_MEM) {- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));- src = TMP_FREG1;- }-- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_32, TMP_FREG1, src, 0)));-- if (FAST_IS_REG(dst))- return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | VN(TMP_FREG1));-- /* Store the integer value from a VFP register. */- return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);-}--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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- op ^= SLJIT_32;-- if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, VMOV | RD(src) | VN(TMP_FREG1)));- else if (src & SLJIT_MEM) {- /* Load the integer value into a VFP register. */- FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));- }- else {- FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));- FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | VN(TMP_FREG1)));- }-- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_32, dst_r, TMP_FREG1, 0)));-- if (dst & SLJIT_MEM)- return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);- return SLJIT_SUCCESS;-}--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_32;-- if (src1 & SLJIT_MEM) {- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));- src1 = TMP_FREG1;- }-- if (src2 & SLJIT_MEM) {- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));- src2 = TMP_FREG2;- }-- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_32, src1, src2, 0)));- return push_inst(compiler, VMRS);-}--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_s32 dst_r;-- CHECK_ERROR();-- SLJIT_COMPILE_ASSERT((SLJIT_32 == 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_32;-- if (src & SLJIT_MEM) {- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw));- src = dst_r;- }-- switch (GET_OPCODE(op)) {- 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_32, dst_r, src, 0)));- else- dst_r = src;- }- break;- case SLJIT_NEG_F64:- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_32, dst_r, src, 0)));- break;- case SLJIT_ABS_F64:- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src, 0)));- break;- case SLJIT_CONV_F64_FROM_F32:- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_32, dst_r, src, 0)));- op ^= SLJIT_32;- break;- }-- if (dst & SLJIT_MEM)- return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);- return SLJIT_SUCCESS;-}--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_s32 dst_r;-- CHECK_ERROR();- CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- op ^= SLJIT_32;-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- if (src2 & SLJIT_MEM) {- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));- src2 = TMP_FREG2;- }-- if (src1 & SLJIT_MEM) {- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));- src1 = TMP_FREG1;- }-- switch (GET_OPCODE(op)) {- case SLJIT_ADD_F64:- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_32, dst_r, src2, src1)));- break;-- case SLJIT_SUB_F64:- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_32, dst_r, src2, src1)));- break;-- case SLJIT_MUL_F64:- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_32, dst_r, src2, src1)));- break;-- case SLJIT_DIV_F64:- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_32, dst_r, src2, src1)));- break;- }-- if (dst_r == TMP_FREG1)- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw));-- return SLJIT_SUCCESS;-}--#undef FPU_LOAD-#undef EMIT_FPU_DATA_TRANSFER--/* --------------------------------------------------------------------- */-/* Other instructions */-/* --------------------------------------------------------------------- */--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);-- SLJIT_ASSERT(reg_map[TMP_REG2] == 14);-- if (FAST_IS_REG(dst))- return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2));-- /* Memory. */- return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1);-}--/* --------------------------------------------------------------------- */-/* Conditional instructions */-/* --------------------------------------------------------------------- */--static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)-{- switch (type) {- case SLJIT_EQUAL:- case SLJIT_EQUAL_F64:- return 0x00000000;-- case SLJIT_NOT_EQUAL:- case SLJIT_NOT_EQUAL_F64:- return 0x10000000;-- case SLJIT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)- return 0x20000000;- /* fallthrough */-- case SLJIT_LESS:- case SLJIT_LESS_F64:- return 0x30000000;-- case SLJIT_NOT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)- return 0x30000000;- /* fallthrough */-- case SLJIT_GREATER_EQUAL:- case SLJIT_GREATER_EQUAL_F64:- return 0x20000000;-- case SLJIT_GREATER:- case SLJIT_GREATER_F64:- return 0x80000000;-- case SLJIT_LESS_EQUAL:- case SLJIT_LESS_EQUAL_F64:- return 0x90000000;-- case SLJIT_SIG_LESS:- return 0xb0000000;-- case SLJIT_SIG_GREATER_EQUAL:- return 0xa0000000;-- case SLJIT_SIG_GREATER:- return 0xc0000000;-- case SLJIT_SIG_LESS_EQUAL:- return 0xd0000000;-- case SLJIT_OVERFLOW:- if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))- return 0x10000000;- /* fallthrough */-- case SLJIT_UNORDERED_F64:- return 0x60000000;-- case SLJIT_NOT_OVERFLOW:- if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))- return 0x00000000;- /* fallthrough */-- case SLJIT_ORDERED_F64:- return 0x70000000;-- default:- SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);- return 0xe0000000;- }-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)-{- struct sljit_label *label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_label(compiler));-- if (compiler->last_label && compiler->last_label->size == compiler->size)- return compiler->last_label;-- label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));- PTR_FAIL_IF(!label);- set_label(label, compiler);- return label;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)-{- struct sljit_jump *jump;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_jump(compiler, type));-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);- type &= 0xff;-- SLJIT_ASSERT(reg_map[TMP_REG1] != 14);--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- if (type >= SLJIT_FAST_CALL)- PTR_FAIL_IF(prepare_blx(compiler));- PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,- type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(compiler, type), 0));-- if (jump->flags & SLJIT_REWRITABLE_JUMP) {- jump->addr = compiler->size;- compiler->patches++;- }-- if (type >= SLJIT_FAST_CALL) {- jump->flags |= IS_BL;- PTR_FAIL_IF(emit_blx(compiler));- }-- if (!(jump->flags & SLJIT_REWRITABLE_JUMP))- jump->addr = compiler->size;-#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(compiler, type)));- jump->addr = compiler->size;-#endif- return jump;-}--#ifdef __SOFTFP__--static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)-{- sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;- sljit_u32 offset = 0;- sljit_u32 word_arg_offset = 0;- sljit_u32 src_offset = 4 * sizeof(sljit_sw);- sljit_u32 float_arg_count = 0;- sljit_s32 types = 0;- sljit_u8 offsets[4];- sljit_u8 *offset_ptr = offsets;-- if (src && FAST_IS_REG(*src))- src_offset = (sljit_uw)reg_map[*src] * sizeof(sljit_sw);-- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types) {- types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);-- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (offset & 0x7)- offset += sizeof(sljit_sw);- *offset_ptr++ = (sljit_u8)offset;- offset += sizeof(sljit_f64);- float_arg_count++;- break;- case SLJIT_ARG_TYPE_F32:- *offset_ptr++ = (sljit_u8)offset;- offset += sizeof(sljit_f32);- float_arg_count++;- break;- default:- *offset_ptr++ = (sljit_u8)offset;- offset += sizeof(sljit_sw);- word_arg_offset += sizeof(sljit_sw);- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {- /* Keep lr register on the stack. */- if (is_tail_call)- offset += sizeof(sljit_sw);-- offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_uw)0x7;-- *extra_space = offset;-- if (is_tail_call)- FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));- else- FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | offset));- } else {- if (is_tail_call)- FAIL_IF(emit_stack_frame_release(compiler, -1));- *extra_space = 0;- }-- /* Process arguments in reversed direction. */- while (types) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- float_arg_count--;- offset = *(--offset_ptr);-- SLJIT_ASSERT((offset & 0x7) == 0);-- if (offset < 4 * sizeof(sljit_sw)) {- if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {- FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));- *src = TMP_REG1;- }- FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));- } else- FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP)- | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));- break;- case SLJIT_ARG_TYPE_F32:- float_arg_count--;- offset = *(--offset_ptr);-- if (offset < 4 * sizeof(sljit_sw)) {- if (src_offset == offset) {- FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));- *src = TMP_REG1;- }- FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));- } else- FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP)- | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));- break;- default:- word_arg_offset -= sizeof(sljit_sw);- offset = *(--offset_ptr);-- SLJIT_ASSERT(offset >= word_arg_offset);-- if (offset != word_arg_offset) {- if (offset < 4 * sizeof(sljit_sw)) {- if (src_offset == offset) {- FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));- *src = TMP_REG1;- }- else if (src_offset == word_arg_offset) {- *src = (sljit_s32)(SLJIT_R0 + (offset >> 2));- src_offset = offset;- }- FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2)));- } else- FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));- }- break;- }-- types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)-{- if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)- FAIL_IF(push_inst(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));- if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)- FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12)));-- return SLJIT_SUCCESS;-}--#else /* !__SOFTFP__ */--static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)-{- sljit_u32 offset = SLJIT_FR0;- sljit_u32 new_offset = SLJIT_FR0;- sljit_u32 f32_offset = 0;-- /* Remove return value. */- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (offset != new_offset)- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,- SLJIT_32, new_offset, offset, 0)));-- new_offset++;- offset++;- break;- case SLJIT_ARG_TYPE_F32:- if (f32_offset != 0) {- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,- 0x400000, f32_offset, offset, 0)));- f32_offset = 0;- } else {- if (offset != new_offset)- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,- 0, new_offset, offset, 0)));- f32_offset = new_offset;- new_offset++;- }- offset++;- break;- }- arg_types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--#endif /* __SOFTFP__ */--#undef EMIT_FPU_OPERATION--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types)-{-#ifdef __SOFTFP__- struct sljit_jump *jump;- sljit_u32 extra_space = (sljit_u32)type;-#endif-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));--#ifdef __SOFTFP__- PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));- SLJIT_ASSERT((extra_space & 0x7) == 0);-- if ((type & SLJIT_CALL_RETURN) && extra_space == 0)- type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- jump = sljit_emit_jump(compiler, type);- PTR_FAIL_IF(jump == NULL);-- if (extra_space > 0) {- if (type & SLJIT_CALL_RETURN)- PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,- TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));-- PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));-- if (type & SLJIT_CALL_RETURN) {- PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));- return jump;- }- }-- SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));- PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));- return jump;-#else /* !__SOFTFP__ */- if (type & SLJIT_CALL_RETURN) {- PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));- type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);- }-- PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_jump(compiler, type);-#endif /* __SOFTFP__ */-}--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;-- CHECK_ERROR();- CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- SLJIT_ASSERT(reg_map[TMP_REG1] != 14);-- if (!(src & SLJIT_IMM)) {- if (FAST_IS_REG(src)) {- SLJIT_ASSERT(reg_map[src] != 14);- return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));- }-- SLJIT_ASSERT(src & SLJIT_MEM);- FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));- return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1));- }-- /* These jumps are converted to jump/call instructions when possible. */- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- FAIL_IF(!jump);- set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));- jump->u.target = (sljit_uw)srcw;--#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_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, 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)));-#endif- jump->addr = compiler->size;- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{-#ifdef __SOFTFP__- sljit_u32 extra_space = (sljit_u32)type;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));-- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));- src = TMP_REG1;- }-- if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) {- FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));- src = TMP_REG1;- }--#ifdef __SOFTFP__- FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));- SLJIT_ASSERT((extra_space & 0x7) == 0);-- if ((type & SLJIT_CALL_RETURN) && extra_space == 0)- type = SLJIT_JUMP;--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));-- if (extra_space > 0) {- if (type & SLJIT_CALL_RETURN)- FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,- TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));-- FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));-- if (type & SLJIT_CALL_RETURN)- return push_inst(compiler, BX | RM(TMP_REG2));- }-- SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));- return softfloat_post_call_with_args(compiler, arg_types);-#else /* !__SOFTFP__ */- if (type & SLJIT_CALL_RETURN) {- FAIL_IF(emit_stack_frame_release(compiler, -1));- type = SLJIT_JUMP;- }-- FAIL_IF(hardfloat_call_with_args(compiler, arg_types));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_ijump(compiler, type, src, srcw);-#endif /* __SOFTFP__ */-}--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_s32 dst_reg, flags = GET_ALL_FLAGS(op);- sljit_uw cc, ins;-- CHECK_ERROR();- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));- ADJUST_LOCAL_OFFSET(dst, dstw);-- op = GET_OPCODE(op);- cc = get_cc(compiler, type & 0xff);- dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;-- if (op < SLJIT_ADD) {- FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | SRC2_IMM | 0));- FAIL_IF(push_inst(compiler, ((MOV | RD(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));- if (dst & SLJIT_MEM)- return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);- return SLJIT_SUCCESS;- }-- ins = (op == SLJIT_AND ? AND : (op == SLJIT_OR ? ORR : EOR));-- if (dst & SLJIT_MEM)- FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));-- FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));-- if (op == SLJIT_AND)- FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));-- if (dst & SLJIT_MEM)- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));-- if (flags & SLJIT_SET_Z)- return push_inst(compiler, MOV | SET_FLAGS | RD(TMP_REG2) | RM(dst_reg));- 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_32;-- cc = get_cc(compiler, type & 0xff);-- if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {- tmp = get_imm((sljit_uw)srcw);- if (tmp)- return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc);-- tmp = get_imm(~(sljit_uw)srcw);- if (tmp)- return push_inst(compiler, ((MVN | RD(dst_reg) | 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, (sljit_uw)srcw));- src = TMP_REG1;-#endif- }-- return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 reg,- sljit_s32 mem, sljit_sw memw)-{- sljit_s32 flags;- sljit_uw is_type1_transfer, inst;-- CHECK_ERROR();- CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));-- is_type1_transfer = 1;-- switch (type & 0xff) {- case SLJIT_MOV:- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:- case SLJIT_MOV_P:- flags = WORD_SIZE;- break;- case SLJIT_MOV_U8:- flags = BYTE_SIZE;- break;- case SLJIT_MOV_S8:- if (!(type & SLJIT_MEM_STORE))- is_type1_transfer = 0;- flags = BYTE_SIZE | SIGNED;- break;- case SLJIT_MOV_U16:- is_type1_transfer = 0;- flags = HALF_SIZE;- break;- case SLJIT_MOV_S16:- is_type1_transfer = 0;- flags = HALF_SIZE | SIGNED;- break;- default:- SLJIT_UNREACHABLE();- flags = WORD_SIZE;- break;- }-- if (!(type & SLJIT_MEM_STORE))- flags |= LOAD_DATA;-- SLJIT_ASSERT(is_type1_transfer == !!IS_TYPE1_TRANSFER(flags));-- if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {- if (!is_type1_transfer && memw != 0)- return SLJIT_ERR_UNSUPPORTED;- }- else {- if (is_type1_transfer) {- if (memw > 4095 || memw < -4095)- return SLJIT_ERR_UNSUPPORTED;- }- else {- if (memw > 255 || memw < -255)- return SLJIT_ERR_UNSUPPORTED;- }- }-- if (type & SLJIT_MEM_SUPP)- return SLJIT_SUCCESS;-- if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {- memw &= 0x3;-- inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | ((sljit_uw)memw << 7));-- if (is_type1_transfer)- inst |= (1 << 25);-- if (type & SLJIT_MEM_PRE)- inst |= (1 << 21);- else- inst ^= (1 << 24);-- return push_inst(compiler, inst);- }-- inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0);-- if (type & SLJIT_MEM_PRE)- inst |= (1 << 21);- else- inst ^= (1 << 24);-- if (is_type1_transfer) {- if (memw >= 0)- inst |= (1 << 23);- else- memw = -memw;-- return push_inst(compiler, inst | (sljit_uw)memw);- }-- if (memw >= 0)- inst |= (1 << 23);- else- memw = -memw;-- return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_uw)memw));-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)-{- struct sljit_const *const_;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));- ADJUST_LOCAL_OFFSET(dst, dstw);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- PTR_FAIL_IF(push_inst_with_unique_literal(compiler,- EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_uw)init_value));- compiler->patches++;-#else- PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));-#endif-- const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));- PTR_FAIL_IF(!const_);- set_const(const_, compiler);-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));- return const_;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- struct sljit_put_label *put_label;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;--#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)- PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));- compiler->patches++;-#else- PTR_FAIL_IF(emit_imm(compiler, dst_r, 0));-#endif-- put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));- PTR_FAIL_IF(!put_label);- set_put_label(put_label, compiler, 0);-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));- return put_label;-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)-{- inline_set_jump_addr(addr, executable_offset, new_target, 1);-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)-{- inline_set_const(addr, executable_offset, (sljit_uw)new_constant, 1);+#elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ return "ARMv6" SLJIT_CPUINFO ARM_ABI_INFO;+#else+#error "Internal error: Unknown ARM architecture"+#endif+}++/* Length of an instruction word. */+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_PC (SLJIT_NUMBER_OF_REGISTERS + 4)++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++/* In ARM instruction words.+ Cache lines are usually 32 byte aligned. */+#define CONST_POOL_ALIGNMENT 8+#define CONST_POOL_EMPTY 0xffffffff++#define ALIGN_INSTRUCTION(ptr) \+ (sljit_ins*)(((sljit_ins)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_ins)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_ins)) - 1))+#define MAX_DIFFERENCE(max_diff) \+ (((max_diff) / (sljit_s32)sizeof(sljit_ins)) - (CONST_POOL_ALIGNMENT - 1))++/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */+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, 12, 14, 15+};++static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {+ 0,+ 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,+ 7, 6,+ 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,+ 7, 6+};++static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {+ 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1+};++#define RM(rm) ((sljit_ins)reg_map[rm])+#define RM8(rm) ((sljit_ins)reg_map[rm] << 8)+#define RD(rd) ((sljit_ins)reg_map[rd] << 12)+#define RN(rn) ((sljit_ins)reg_map[rn] << 16)++#define VM(vm) (((sljit_ins)freg_map[vm]) | ((sljit_ins)freg_ebit_map[vm] << 5))+#define VD(vd) (((sljit_ins)freg_map[vd] << 12) | ((sljit_ins)freg_ebit_map[vd] << 22))+#define VN(vn) (((sljit_ins)freg_map[vn] << 16) | ((sljit_ins)freg_ebit_map[vn] << 7))++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++/* The instruction includes the AL condition.+ INST_NAME - CONDITIONAL remove this flag. */+#define COND_MASK 0xf0000000+#define CONDITIONAL 0xe0000000+#define PUSH_POOL 0xff000000++#define ADC 0xe0a00000+#define ADD 0xe0800000+#define AND 0xe0000000+#define B 0xea000000+#define BIC 0xe1c00000+#define BKPT 0xe1200070+#define BL 0xeb000000+#define BLX 0xe12fff30+#define BX 0xe12fff10+#define CLZ 0xe16f0f10+#define CMN 0xe1600000+#define CMP 0xe1400000+#define EOR 0xe0200000+#define LDR 0xe5100000+#define LDR_POST 0xe4100000+#define LDREX 0xe1900f9f+#define LDREXB 0xe1d00f9f+#define LDREXH 0xe1f00f9f+#define MLA 0xe0200090+#define MOV 0xe1a00000+#define MUL 0xe0000090+#define MVN 0xe1e00000+#define NOP 0xe1a00000+#define ORR 0xe1800000+#define PUSH 0xe92d0000+#define POP 0xe8bd0000+#define REV 0xe6bf0f30+#define REV16 0xe6bf0fb0+#define RSB 0xe0600000+#define RSC 0xe0e00000+#define SBC 0xe0c00000+#define SMULL 0xe0c00090+#define STR 0xe5000000+#define STREX 0xe1800f90+#define STREXB 0xe1c00f90+#define STREXH 0xe1e00f90+#define SUB 0xe0400000+#define SXTB 0xe6af0070+#define SXTH 0xe6bf0070+#define TST 0xe1000000+#define UMULL 0xe0800090+#define UXTB 0xe6ef0070+#define UXTH 0xe6ff0070+#define VABS_F32 0xeeb00ac0+#define VADD_F32 0xee300a00+#define VAND 0xf2000110+#define VCMP_F32 0xeeb40a40+#define VCVT_F32_S32 0xeeb80ac0+#define VCVT_F32_U32 0xeeb80a40+#define VCVT_F64_F32 0xeeb70ac0+#define VCVT_S32_F32 0xeebd0ac0+#define VDIV_F32 0xee800a00+#define VDUP 0xee800b10+#define VDUP_s 0xf3b00c00+#define VEOR 0xf3000110+#define VLD1 0xf4200000+#define VLD1_r 0xf4a00c00+#define VLD1_s 0xf4a00000+#define VLDR_F32 0xed100a00+#define VMOV_F32 0xeeb00a40+#define VMOV 0xee000a10+#define VMOV2 0xec400a10+#define VMOV_i 0xf2800010+#define VMOV_s 0xee000b10+#define VMOVN 0xf3b20200+#define VMRS 0xeef1fa10+#define VMUL_F32 0xee200a00+#define VNEG_F32 0xeeb10a40+#define VORR 0xf2200110+#define VPOP 0xecbd0b00+#define VPUSH 0xed2d0b00+#define VSHLL 0xf2800a10+#define VSHR 0xf2800010+#define VSRA 0xf2800110+#define VST1 0xf4000000+#define VST1_s 0xf4800000+#define VSTR_F32 0xed000a00+#define VSUB_F32 0xee300a40++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+/* Arm v7 specific instructions. */+#define MOVT 0xe3400000+#define MOVW 0xe3000000+#define RBIT 0xe6ff0f30+#endif++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)++static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)+{+ if (compiler->scratches == -1)+ return 0;++ if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))+ fr -= SLJIT_F64_SECOND(0);++ return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches))+ || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0)+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));+}++#endif /* SLJIT_ARGUMENT_CHECKS */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)++static sljit_s32 push_cpool(struct sljit_compiler *compiler)+{+ /* Pushing the constant pool into the instruction stream. */+ sljit_ins* inst;+ sljit_uw* cpool_ptr;+ sljit_uw* cpool_end;+ sljit_s32 i;++ /* The label could point the address after the constant pool. */+ if (compiler->last_label && compiler->last_label->size == compiler->size)+ compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1;++ SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE);+ inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!inst);+ compiler->size++;+ *inst = 0xff000000 | compiler->cpool_fill;++ for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) {+ inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!inst);+ compiler->size++;+ *inst = 0;+ }++ cpool_ptr = compiler->cpool;+ cpool_end = cpool_ptr + compiler->cpool_fill;+ while (cpool_ptr < cpool_end) {+ inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!inst);+ compiler->size++;+ *inst = *cpool_ptr++;+ }+ compiler->cpool_diff = CONST_POOL_EMPTY;+ compiler->cpool_fill = 0;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins inst)+{+ sljit_ins* ptr;++ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))+ FAIL_IF(push_cpool(compiler));++ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size++;+ *ptr = inst;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_ins inst, sljit_uw literal)+{+ sljit_ins* ptr;+ sljit_uw cpool_index = CPOOL_SIZE;+ sljit_uw* cpool_ptr;+ sljit_uw* cpool_end;+ 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));+ else if (compiler->cpool_fill > 0) {+ cpool_ptr = compiler->cpool;+ cpool_end = cpool_ptr + compiler->cpool_fill;+ cpool_unique_ptr = compiler->cpool_unique;+ do {+ if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) {+ cpool_index = (sljit_uw)(cpool_ptr - compiler->cpool);+ break;+ }+ cpool_ptr++;+ cpool_unique_ptr++;+ } while (cpool_ptr < cpool_end);+ }++ if (cpool_index == CPOOL_SIZE) {+ /* Must allocate a new entry in the literal pool. */+ if (compiler->cpool_fill < CPOOL_SIZE) {+ cpool_index = compiler->cpool_fill;+ compiler->cpool_fill++;+ }+ else {+ FAIL_IF(push_cpool(compiler));+ cpool_index = 0;+ compiler->cpool_fill = 1;+ }+ }++ SLJIT_ASSERT((inst & 0xfff) == 0);+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size++;+ *ptr = inst | cpool_index;++ compiler->cpool[cpool_index] = literal;+ compiler->cpool_unique[cpool_index] = 0;+ if (compiler->cpool_diff == CONST_POOL_EMPTY)+ compiler->cpool_diff = compiler->size;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_ins inst, sljit_uw literal)+{+ sljit_ins* ptr;++ if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE))+ FAIL_IF(push_cpool(compiler));++ SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0);+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size++;+ *ptr = inst | compiler->cpool_fill;++ compiler->cpool[compiler->cpool_fill] = literal;+ compiler->cpool_unique[compiler->cpool_fill] = 1;+ compiler->cpool_fill++;+ if (compiler->cpool_diff == CONST_POOL_EMPTY)+ compiler->cpool_diff = compiler->size;+ return SLJIT_SUCCESS;+}++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)))+ return push_cpool(compiler);+ return SLJIT_SUCCESS;+}++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));+ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);++ return push_inst(compiler, BLX | RM(TMP_REG1));+}++static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)+{+ sljit_uw diff;+ sljit_uw ind;+ sljit_uw counter = 0;+ sljit_uw* clear_const_pool = const_pool;+ sljit_uw* clear_const_pool_end = const_pool + cpool_size;++ SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT);+ /* Set unused flag for all literals in the constant pool.+ I.e.: unused literals can belong to branches, which can be encoded as B or BL.+ We can "compress" the constant pool by discarding these literals. */+ while (clear_const_pool < clear_const_pool_end)+ *clear_const_pool++ = (sljit_uw)(-1);++ while (last_pc_patch < code_ptr) {+ /* Data transfer instruction with Rn == r15. */+ if ((*last_pc_patch & 0x0e0f0000) == 0x040f0000) {+ diff = (sljit_uw)(const_pool - last_pc_patch);+ ind = (*last_pc_patch) & 0xfff;++ /* 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_s32)const_pool[ind] < 0) {+ const_pool[ind] = counter;+ ind = counter;+ counter++;+ }+ else+ ind = const_pool[ind];++ SLJIT_ASSERT(diff >= 1);+ if (diff >= 2 || ind > 0) {+ diff = (diff + (sljit_uw)ind - 2) << 2;+ SLJIT_ASSERT(diff <= 0xfff);+ *last_pc_patch = (*last_pc_patch & ~(sljit_uw)0xfff) | diff;+ }+ else+ *last_pc_patch = (*last_pc_patch & ~(sljit_uw)(0xfff | (1 << 23))) | 0x004;+ }+ last_pc_patch++;+ }+ return counter;+}++/* 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_s32 index;+ sljit_s32 value;+};++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_u32 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 = cpool_start_address[cpool_current_index];+ else {+ curr_patch = *first_patch;+ prev_patch = NULL;+ while (1) {+ if (!curr_patch) {+ value = cpool_start_address[cpool_current_index];+ break;+ }+ if ((sljit_uw)curr_patch->index == cpool_current_index) {+ value = (sljit_uw)curr_patch->value;+ if (prev_patch)+ prev_patch->next = curr_patch->next;+ else+ *first_patch = curr_patch->next;+ SLJIT_FREE(curr_patch, compiler->allocator_data);+ break;+ }+ prev_patch = curr_patch;+ curr_patch = curr_patch->next;+ }+ }++ if ((sljit_sw)value >= 0) {+ if (value > cpool_current_index) {+ curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch), compiler->allocator_data);+ if (!curr_patch) {+ while (*first_patch) {+ curr_patch = *first_patch;+ *first_patch = (*first_patch)->next;+ SLJIT_FREE(curr_patch, compiler->allocator_data);+ }+ return SLJIT_ERR_ALLOC_FAILED;+ }+ curr_patch->next = *first_patch;+ curr_patch->index = (sljit_sw)value;+ curr_patch->value = (sljit_sw)cpool_start_address[value];+ *first_patch = curr_patch;+ }+ cpool_start_address[value] = *buf_ptr;+ }+ return SLJIT_SUCCESS;+}++#else++static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins inst)+{+ sljit_ins* ptr;++ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size++;+ *ptr = inst;+ return SLJIT_SUCCESS;+}++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) | ((sljit_u32)imm & 0xfff)));+ return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | (((sljit_u32)imm >> 16) & 0xfff));+}++#endif++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;++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ return 0;++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ if (jump->flags & IS_BL)+ code_ptr--;+#endif /* SLJIT_CONFIG_ARM_V6 */++ if (jump->flags & JUMP_ADDR)+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset);+ else {+ SLJIT_ASSERT(jump->u.label != NULL);+ diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2));+ }++ /* Branch to Thumb code has not been optimized yet. */+ if (diff & 0x3)+ return 0;++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ if (jump->flags & IS_BL) {+ if (diff <= 0x01ffffff && diff >= -0x02000000) {+ *code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK);+ jump->flags |= PATCH_B;+ return 1;+ }+ }+ else {+ if (diff <= 0x01ffffff && diff >= -0x02000000) {+ *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK);+ jump->flags |= PATCH_B;+ }+ }+#else /* !SLJIT_CONFIG_ARM_V6 */+ if (diff <= 0x01ffffff && diff >= -0x02000000) {+ *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (*code_ptr & COND_MASK);+ jump->flags |= PATCH_B;+ return 1;+ }+#endif /* SLJIT_CONFIG_ARM_V6 */+ return 0;+}++static void set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache)+{+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ sljit_ins *ptr = (sljit_ins*)jump_ptr;+ sljit_ins *inst = (sljit_ins*)ptr[0];+ sljit_ins mov_pc = ptr[1];+ 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);++ SLJIT_UNUSED_ARG(executable_offset);++ if (diff <= 0x7fffff && diff >= -0x800000) {+ /* Turn to branch. */+ if (!bl) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ }+ inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ } else {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ }+ inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);+ inst[1] = NOP;+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ }+ }+ } else {+ /* Get the position of the constant. */+ if (mov_pc & (1 << 23))+ ptr = inst + ((mov_pc & 0xfff) >> 2) + 2;+ else+ ptr = inst + 1;++ if (*inst != mov_pc) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + (!bl ? 1 : 2), 0);+ }+ inst[0] = mov_pc;+ if (!bl) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ } else {+ inst[1] = BLX | RM(TMP_REG1);+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ }+ }+ }++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);+ }++ *ptr = new_addr;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);+ }+ }+#else /* !SLJIT_CONFIG_ARM_V6 */+ sljit_ins *inst = (sljit_ins*)jump_ptr;++ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ }++ 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_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ }+#endif /* SLJIT_CONFIG_ARM_V6 */+}++static sljit_uw get_imm(sljit_uw imm);+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm);+static 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);++static void set_const_value(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, sljit_s32 flush_cache)+{+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ sljit_ins *ptr = (sljit_ins*)addr;+ sljit_ins *inst = (sljit_ins*)ptr[0];+ sljit_uw ldr_literal = ptr[1];+ sljit_uw src2;++ SLJIT_UNUSED_ARG(executable_offset);++ src2 = get_imm(new_constant);+ if (src2) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ }++ *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ return;+ }++ src2 = get_imm(~new_constant);+ if (src2) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ }++ *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ return;+ }++ if (ldr_literal & (1 << 23))+ ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2;+ else+ ptr = inst + 1;++ if (*inst != ldr_literal) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ }++ *inst = ldr_literal;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ }++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);+ }++ *ptr = new_constant;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);+ }+#else /* !SLJIT_CONFIG_ARM_V6 */+ sljit_ins *inst = (sljit_ins*)addr;++ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ }++ 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_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ }+#endif /* SLJIT_CONFIG_ARM_V6 */+}++static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_uw addr;+ sljit_sw diff;+ SLJIT_UNUSED_ARG(executable_offset);++ if (jump->flags & JUMP_ADDR)+ addr = jump->u.target;+ else+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ /* The pc+8 offset is represented by the 2 * SSIZE_OF(ins) below. */+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ if ((diff & 0x3) == 0 && diff <= (0x3fc + 2 * SSIZE_OF(ins)) && diff >= (-0x3fc + 2 * SSIZE_OF(ins))) {+ jump->flags |= PATCH_B;+ return 0;+ }++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ return 0;+#else /* !SLJIT_CONFIG_ARM_V6 */+ return 1;+#endif /* SLJIT_CONFIG_ARM_V6 */+}++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)++static void reduce_code_size(struct sljit_compiler *compiler)+{+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_uw total_size;+ sljit_uw size_reduce = 0;+ sljit_sw diff;++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();++ while (1) {+ SLJIT_GET_NEXT_MIN();++ if (next_min_addr == SLJIT_MAX_ADDRESS)+ break;++ if (next_min_addr == next_label_size) {+ label->size -= size_reduce;++ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_const_addr) {+ const_->addr -= size_reduce;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ continue;+ }++ if (next_min_addr != next_jump_addr)+ continue;++ jump->addr -= size_reduce;+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ total_size = JUMP_MAX_SIZE - 1;++ if (!(jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR))) {+ /* Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr - 2;++ if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins)))+ total_size = 1 - 1;+ }++ size_reduce += JUMP_MAX_SIZE - 1 - total_size;+ } else {+ /* Real size minus 1. Unit size: instruction. */+ total_size = 1;++ if (!(jump->flags & JUMP_ADDR)) {+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;+ if (diff <= 0xff + 2 && diff >= -0xff + 2)+ total_size = 0;+ }++ size_reduce += 1 - total_size;+ }++ jump->flags |= total_size << JUMP_SIZE_SHIFT;+ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ }++ compiler->size -= size_reduce;+}++#endif /* SLJIT_CONFIG_ARM_V7 */++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_sw executable_offset;+ sljit_uw addr;+ sljit_sw diff;+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ sljit_uw cpool_size;+ sljit_uw cpool_skip_alignment;+ sljit_uw cpool_current_index;+ sljit_ins *cpool_start_address;+ sljit_ins *last_pc_patch;+ struct future_patch *first_patch;+#endif++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));++ /* Second code generation pass. */+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ compiler->size += (compiler->patches << 1);+ if (compiler->cpool_fill > 0)+ compiler->size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1;+#else /* !SLJIT_CONFIG_ARM_V6 */+ reduce_code_size(compiler);+#endif /* SLJIT_CONFIG_ARM_V6 */+ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);+ PTR_FAIL_WITH_EXEC_IF(code);++ reverse_buf(compiler);+ buf = compiler->buf;++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ cpool_size = 0;+ cpool_skip_alignment = 0;+ cpool_current_index = 0;+ cpool_start_address = NULL;+ first_patch = NULL;+ last_pc_patch = code;+#endif /* SLJIT_CONFIG_ARM_V6 */++ code_ptr = code;+ word_count = 0;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();+ SLJIT_GET_NEXT_MIN();++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ if (cpool_size > 0) {+ if (cpool_skip_alignment > 0) {+ buf_ptr++;+ cpool_skip_alignment--;+ } else {+ if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {+ SLJIT_FREE_EXEC(code, exec_allocator_data);+ compiler->error = SLJIT_ERR_ALLOC_FAILED;+ return NULL;+ }+ buf_ptr++;+ if (++cpool_current_index >= cpool_size) {+ SLJIT_ASSERT(!first_patch);+ cpool_size = 0;+ }+ }+ } else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {+#endif /* SLJIT_CONFIG_ARM_V6 */+ *code_ptr = *buf_ptr++;+ if (next_min_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);++ if (next_min_addr == next_label_size) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ /* These structures are ordered by their address. */+ if (next_min_addr == next_jump_addr) {+ if (!(jump->flags & JUMP_MOV_ADDR)) {+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ if (detect_jump_type(jump, code_ptr, code, executable_offset))+ code_ptr--;+ jump->addr = (sljit_uw)code_ptr;+#else /* !SLJIT_CONFIG_ARM_V6 */+ word_count += jump->flags >> JUMP_SIZE_SHIFT;+ jump->addr = (sljit_uw)code_ptr;+ if (!detect_jump_type(jump, code_ptr, code, executable_offset)) {+ code_ptr[2] = code_ptr[0];+ addr = ((code_ptr[0] & 0xf) << 12);+ code_ptr[0] = MOVW | addr;+ code_ptr[1] = MOVT | addr;+ code_ptr += 2;+ }+ SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins));+#endif /* SLJIT_CONFIG_ARM_V6 */+ } else {+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ word_count += jump->flags >> JUMP_SIZE_SHIFT;+#endif /* SLJIT_CONFIG_ARM_V7 */+ addr = (sljit_uw)code_ptr;+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);+ jump->addr = addr;+ }+ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ } else if (next_min_addr == next_const_addr) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ }++ SLJIT_GET_NEXT_MIN();+ }+ code_ptr++;+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ } else {+ /* Fortunately, no need to shift. */+ cpool_size = *buf_ptr++ & ~PUSH_POOL;+ SLJIT_ASSERT(cpool_size > 0);+ cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1);+ cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size);+ if (cpool_current_index > 0) {+ /* Unconditional branch. */+ *code_ptr = B | (((sljit_ins)(cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);+ code_ptr = (sljit_ins*)(cpool_start_address + cpool_current_index);+ }+ cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1;+ cpool_current_index = 0;+ last_pc_patch = code_ptr;+ }+#endif /* SLJIT_CONFIG_ARM_V6 */+ word_count++;+ } while (buf_ptr < buf_end);+ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ SLJIT_ASSERT(cpool_size == 0);+ if (compiler->cpool_fill > 0) {+ cpool_start_address = ALIGN_INSTRUCTION(code_ptr);+ cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill);+ if (cpool_current_index > 0)+ code_ptr = (sljit_ins*)(cpool_start_address + cpool_current_index);++ buf_ptr = compiler->cpool;+ buf_end = buf_ptr + compiler->cpool_fill;+ cpool_current_index = 0;+ while (buf_ptr < buf_end) {+ if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {+ SLJIT_FREE_EXEC(code, exec_allocator_data);+ compiler->error = SLJIT_ERR_ALLOC_FAILED;+ return NULL;+ }+ buf_ptr++;+ cpool_current_index++;+ }+ SLJIT_ASSERT(!first_patch);+ }+#endif++ jump = compiler->jumps;+ while (jump) {+ addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;+ buf_ptr = (sljit_ins*)jump->addr;++ if (jump->flags & JUMP_MOV_ADDR) {+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ SLJIT_ASSERT((buf_ptr[0] & (sljit_ins)0xffff0000) == 0xe59f0000);+#else /* !SLJIT_CONFIG_ARM_V6 */+ SLJIT_ASSERT((buf_ptr[0] & ~(sljit_ins)0xf000) == 0);+#endif /* SLJIT_CONFIG_ARM_V6 */++ if (jump->flags & PATCH_B) {+ SLJIT_ASSERT((((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) & 0x3) == 0);+ diff = ((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) >> 2;++ SLJIT_ASSERT(diff <= 0xff && diff >= -0xff);++ addr = ADD;+ if (diff < 0) {+ diff = -diff;+ addr = SUB;+ }++ buf_ptr[0] = addr | (buf_ptr[0] & 0xf000) | RN(TMP_PC) | (1 << 25) | (0xf << 8) | (sljit_ins)(diff & 0xff);+ } else {+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr;+#else /* !SLJIT_CONFIG_ARM_V6 */+ buf_ptr[1] = MOVT | buf_ptr[0] | ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff);+ buf_ptr[0] = MOVW | buf_ptr[0] | ((addr << 4) & 0xf0000) | (addr & 0xfff);+#endif /* SLJIT_CONFIG_ARM_V6 */+ }+ } else if (jump->flags & PATCH_B) {+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);+ SLJIT_ASSERT(diff <= 0x01ffffff && diff >= -0x02000000);+ *buf_ptr |= (diff >> 2) & 0x00ffffff;+ } else {+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ if (jump->flags & IS_BL)+ buf_ptr--;++ if (jump->flags & SLJIT_REWRITABLE_JUMP) {+ jump->addr = (sljit_uw)code_ptr;+ code_ptr[0] = (sljit_ins)buf_ptr;+ code_ptr[1] = *buf_ptr;+ set_jump_addr((sljit_uw)code_ptr, executable_offset, addr, 0);+ code_ptr += 2;+ } else {+ if (*buf_ptr & (1 << 23))+ buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;+ else+ buf_ptr += 1;+ *buf_ptr = addr;+ }+#else /* !SLJIT_CONFIG_ARM_V6 */+ set_jump_addr((sljit_uw)buf_ptr, executable_offset, addr, 0);+#endif /* SLJIT_CONFIG_ARM_V6 */+ }++ jump = jump->next;+ }++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ const_ = compiler->consts;+ while (const_) {+ buf_ptr = (sljit_ins*)const_->addr;+ const_->addr = (sljit_uw)code_ptr;++ code_ptr[0] = (sljit_ins)buf_ptr;+ code_ptr[1] = *buf_ptr;+ if (*buf_ptr & (1 << 23))+ buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;+ else+ buf_ptr += 1;+ /* Set the value again (can be a simple constant). */+ set_const_value((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);+ code_ptr += 2;++ const_ = const_->next;+ }+#endif /* SLJIT_CONFIG_ARM_V6 */++ SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_uw);++ 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);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ return code;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ switch (feature_type) {+ case SLJIT_HAS_FPU:+ case SLJIT_HAS_F64_AS_F32_PAIR:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return (SLJIT_IS_FPU_AVAILABLE) != 0;+#else+ /* Available by default. */+ return 1;+#endif /* SLJIT_IS_FPU_AVAILABLE */+ case SLJIT_HAS_SIMD:+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ return 0;+#else+#ifdef SLJIT_IS_FPU_AVAILABLE+ return (SLJIT_IS_FPU_AVAILABLE) != 0;+#else+ /* Available by default. */+ return 1;+#endif /* SLJIT_IS_FPU_AVAILABLE */+#endif /* SLJIT_CONFIG_ARM_V6 */++ case SLJIT_SIMD_REGS_ARE_PAIRS:+ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_ROT:+ case SLJIT_HAS_CMOV:+ case SLJIT_HAS_REV:+ case SLJIT_HAS_PREFETCH:+ case SLJIT_HAS_COPY_F32:+ case SLJIT_HAS_COPY_F64:+ case SLJIT_HAS_ATOMIC:+ return 1;++ case SLJIT_HAS_CTZ:+#if defined(SLJIT_CONFIG_ARM_V6) && SLJIT_CONFIG_ARM_V6+ return 2;+#else+ return 1;+#endif /* SLJIT_CONFIG_ARM_V6 */++ default:+ return 0;+ }+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++/* Creates an index in data_transfer_insts array. */+#define WORD_SIZE 0x00+#define BYTE_SIZE 0x01+#define HALF_SIZE 0x02+#define PRELOAD 0x03+#define SIGNED 0x04+#define LOAD_DATA 0x08++/* Flag bits for emit_op. */+#define ALLOW_IMM 0x10+#define ALLOW_INV_IMM 0x20+#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM)+#define ALLOW_NEG_IMM 0x40+#define ALLOW_DOUBLE_IMM 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_ins 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 */,+/* 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, target_reg, base_reg, arg) \+ (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (sljit_ins)(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))++#define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \+ ((sljit_ins)(opcode) | (sljit_ins)(mode) | VD(dst) | VM(src1) | VN(src2))++/* Flags for emit_op: */+ /* Arguments are swapped. */+#define ARGS_SWAPPED 0x01+ /* Inverted immediate. */+#define INV_IMM 0x02+ /* Source and destination is register. */+#define REGISTER_OP 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+ src1: reg+ src2: reg or imm (if allowed)+ 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)++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_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_uw imm, offset;+ sljit_s32 i, tmp, size, word_arg_count;+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);+#ifdef __SOFTFP__+ sljit_u32 float_arg_count;+#else+ sljit_u32 old_offset, f32_offset;+ sljit_u32 remap[3];+ sljit_u32 *remap_ptr = remap;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ imm = 0;++ tmp = SLJIT_S0 - saveds;+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--)+ imm |= (sljit_uw)1 << reg_map[i];++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)+ imm |= (sljit_uw)1 << reg_map[i];++ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ /* Push saved and temporary registers+ multiple registers: stmdb sp!, {..., lr}+ single register: str reg, [sp, #-4]! */+ if (imm != 0)+ FAIL_IF(push_inst(compiler, PUSH | (1 << 14) | imm));+ else+ FAIL_IF(push_inst(compiler, 0xe52d0004 | RD(TMP_REG2)));++ /* Stack must be aligned to 8 bytes: */+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);++ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ if ((size & SSIZE_OF(sw)) != 0) {+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | sizeof(sljit_sw)));+ size += SSIZE_OF(sw);+ }++ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {+ FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_ins)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));+ } else {+ if (fsaveds > 0)+ FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_ins)fsaveds << 1)));+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)+ FAIL_IF(push_inst(compiler, VPUSH | VD(fscratches) | ((sljit_ins)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));+ }+ }++ local_size = ((size + local_size + 0x7) & ~0x7) - size;+ compiler->local_size = local_size;++ if (options & SLJIT_ENTER_REG_ARG)+ arg_types = 0;++ arg_types >>= SLJIT_ARG_SHIFT;+ word_arg_count = 0;+ saved_arg_count = 0;+#ifdef __SOFTFP__+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);++ offset = 0;+ float_arg_count = 0;++ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (offset & 0x7)+ offset += sizeof(sljit_sw);++ if (offset < 4 * sizeof(sljit_sw))+ FAIL_IF(push_inst(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));+ else+ FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800100 | RN(SLJIT_SP)+ | (float_arg_count << 12) | ((offset + (sljit_ins)size - 4 * sizeof(sljit_sw)) >> 2)));+ float_arg_count++;+ offset += sizeof(sljit_f64) - sizeof(sljit_sw);+ break;+ case SLJIT_ARG_TYPE_F32:+ if (offset < 4 * sizeof(sljit_sw))+ FAIL_IF(push_inst(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));+ else+ FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800000 | RN(SLJIT_SP)+ | (float_arg_count << 12) | ((offset + (sljit_ins)size - 4 * sizeof(sljit_sw)) >> 2)));+ float_arg_count++;+ break;+ default:+ word_arg_count++;++ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ tmp = SLJIT_S0 - saved_arg_count;+ saved_arg_count++;+ } else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))+ tmp = word_arg_count;+ else+ break;++ if (offset < 4 * sizeof(sljit_sw))+ FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));+ else+ FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_ins)size - 4 * sizeof(sljit_sw))));+ break;+ }++ offset += sizeof(sljit_sw);+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ compiler->args_size = offset;+#else+ offset = SLJIT_FR0;+ old_offset = SLJIT_FR0;+ f32_offset = 0;++ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (offset != old_offset)+ *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, SLJIT_32, offset, old_offset, 0);+ old_offset++;+ offset++;+ break;+ case SLJIT_ARG_TYPE_F32:+ if (f32_offset != 0) {+ *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0x20, offset, f32_offset, 0);+ f32_offset = 0;+ } else {+ if (offset != old_offset)+ *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0, offset, old_offset, 0);+ f32_offset = old_offset;+ old_offset++;+ }+ offset++;+ break;+ default:+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0 - saved_arg_count) | RM(SLJIT_R0 + word_arg_count)));+ saved_arg_count++;+ }++ word_arg_count++;+ break;+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));++ while (remap_ptr > remap)+ FAIL_IF(push_inst(compiler, *(--remap_ptr)));+#endif++ if (local_size > 0)+ FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM | ALLOW_DOUBLE_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);++ /* Doubles are saved, so alignment is unaffected. */+ if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))+ size += SSIZE_OF(sw);++ compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)+{+ sljit_uw imm2 = get_imm(imm);++ if (imm2 == 0)+ return emit_op(compiler, SLJIT_ADD, ALLOW_IMM | ALLOW_DOUBLE_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, (sljit_sw)imm);++ return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | imm2);+}++static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)+{+ sljit_s32 local_size, fscratches, fsaveds, i, tmp;+ sljit_s32 restored_reg = 0;+ sljit_s32 lr_dst = TMP_PC;+ sljit_uw reg_list = 0;++ SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128);++ local_size = compiler->local_size;+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;++ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ if (local_size > 0)+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));++ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {+ FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_ins)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));+ } else {+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)+ FAIL_IF(push_inst(compiler, VPOP | VD(fscratches) | ((sljit_ins)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));+ if (fsaveds > 0)+ FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_ins)fsaveds << 1)));+ }++ local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;+ }++ if (frame_size < 0) {+ lr_dst = TMP_REG2;+ frame_size = 0;+ } else if (frame_size > 0) {+ SLJIT_ASSERT(frame_size == 1 || (frame_size & 0x7) == 0);+ lr_dst = 0;+ frame_size &= ~0x7;+ }++ if (lr_dst != 0)+ reg_list |= (sljit_uw)1 << reg_map[lr_dst];++ tmp = SLJIT_S0 - compiler->saveds;+ i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options);+ if (tmp < i) {+ restored_reg = i;+ do {+ reg_list |= (sljit_uw)1 << reg_map[i];+ } while (--i > tmp);+ }++ i = compiler->scratches;+ if (i >= SLJIT_FIRST_SAVED_REG) {+ restored_reg = i;+ do {+ reg_list |= (sljit_uw)1 << reg_map[i];+ } while (--i >= SLJIT_FIRST_SAVED_REG);+ }++ if (lr_dst == TMP_REG2 && reg_list == 0) {+ restored_reg = TMP_REG2;+ lr_dst = 0;+ }++ if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {+ /* The local_size does not include the saved registers. */+ tmp = 0;+ if (reg_list != 0) {+ tmp = 2;+ if (local_size <= 0xfff) {+ if (local_size == 0) {+ SLJIT_ASSERT(restored_reg != TMP_REG2);+ if (frame_size == 0)+ return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | 0x800008);+ if (frame_size > 2 * SSIZE_OF(sw))+ return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)(frame_size - (2 * SSIZE_OF(sw))));+ }++ FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)local_size));+ tmp = 1;+ } else if (frame_size == 0) {+ frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw);+ tmp = 3;+ }++ /* Place for the saved register. */+ if (restored_reg != TMP_REG2)+ local_size += SSIZE_OF(sw);+ }++ /* Place for the lr register. */+ local_size += SSIZE_OF(sw);++ if (frame_size > local_size)+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_ins)(frame_size - local_size)));+ else if (frame_size < local_size)+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));++ if (tmp <= 1)+ return SLJIT_SUCCESS;++ if (tmp == 2) {+ frame_size -= SSIZE_OF(sw);+ if (restored_reg != TMP_REG2)+ frame_size -= SSIZE_OF(sw);++ return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)frame_size);+ }++ tmp = (restored_reg == TMP_REG2) ? 0x800004 : 0x800008;+ return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)tmp);+ }++ if (local_size > 0)+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));++ /* Pop saved and temporary registers+ multiple registers: ldmia sp!, {...}+ single register: ldr reg, [sp], #4 */+ if ((reg_list & (reg_list - 1)) == 0) {+ SLJIT_ASSERT(lr_dst != 0);+ SLJIT_ASSERT(reg_list == (sljit_uw)1 << reg_map[lr_dst]);++ return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(lr_dst) | 0x800004);+ }++ FAIL_IF(push_inst(compiler, POP | reg_list));++ if (frame_size > 0)+ return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_ins)frame_size - sizeof(sljit_sw)));++ if (lr_dst != 0)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | sizeof(sljit_sw));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ return emit_stack_frame_release(compiler, 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ srcw = 0;+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));+ src = TMP_REG1;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 1));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_uw dst, sljit_uw src1, sljit_uw src2)+{+ sljit_s32 reg, is_masked;+ sljit_uw shift_type;++ switch (op) {+ case SLJIT_MOV:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));+ if (dst != src2) {+ if (src2 & SRC2_IMM) {+ return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);+ }+ return push_inst(compiler, MOV | RD(dst) | RM(src2));+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));+ if (flags & REGISTER_OP)+ return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2));++ if (dst != src2) {+ SLJIT_ASSERT(src2 & SRC2_IMM);+ return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));+ if (flags & REGISTER_OP)+ return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2));++ if (dst != src2) {+ SLJIT_ASSERT(src2 & SRC2_IMM);+ return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_CLZ:+ SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM));+ FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));+ return SLJIT_SUCCESS;++ case SLJIT_CTZ:+ SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM));+ SLJIT_ASSERT(src1 == TMP_REG1 && src2 != TMP_REG2 && !(flags & ARGS_SWAPPED));+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0));+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RN(src2) | RM(TMP_REG2)));+ FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(TMP_REG1)));+ FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(dst) | 32));+ return push_inst(compiler, (EOR ^ 0xf0000000) | SRC2_IMM | RD(dst) | RN(dst) | 0x1f);+#else /* !SLJIT_CONFIG_ARM_V6 */+ FAIL_IF(push_inst(compiler, RBIT | RD(dst) | RM(src2)));+ return push_inst(compiler, CLZ | RD(dst) | RM(dst));+#endif /* SLJIT_CONFIG_ARM_V6 */++ case SLJIT_REV:+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));+ return push_inst(compiler, REV | RD(dst) | RM(src2));++ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));+ FAIL_IF(push_inst(compiler, REV16 | RD(dst) | RM(src2)));+ if (!(flags & REGISTER_OP))+ return SLJIT_SUCCESS;+ return push_inst(compiler, (op == SLJIT_REV_U16 ? UXTH : SXTH) | RD(dst) | RM(dst));+ case SLJIT_ADD:+ SLJIT_ASSERT(!(flags & INV_IMM));++ if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)+ return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));+ return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_ADDC:+ SLJIT_ASSERT(!(flags & INV_IMM));+ return push_inst(compiler, ADC | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_SUB:+ SLJIT_ASSERT(!(flags & INV_IMM));++ if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)+ return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS)+ | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_SUBC:+ SLJIT_ASSERT(!(flags & INV_IMM));+ return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SBC : RSC) | (flags & SET_FLAGS)+ | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_MUL:+ SLJIT_ASSERT(!(flags & INV_IMM));+ SLJIT_ASSERT(!(src2 & SRC2_IMM));+ compiler->status_flags_state = 0;++ if (!(flags & SET_FLAGS))+ return push_inst(compiler, MUL | RN(dst) | RM8(src2) | RM(src1));++ reg = dst == TMP_REG1 ? TMP_REG2 : TMP_REG1;+ FAIL_IF(push_inst(compiler, SMULL | RN(reg) | RD(dst) | RM8(src2) | RM(src1)));++ /* cmp TMP_REG1, dst asr #31. */+ return push_inst(compiler, CMP | SET_FLAGS | RN(reg) | RM(dst) | 0xfc0);++ case SLJIT_AND:+ if ((flags & (UNUSED_RETURN | INV_IMM)) == UNUSED_RETURN)+ return push_inst(compiler, TST | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));+ return push_inst(compiler, (!(flags & INV_IMM) ? AND : BIC) | (flags & SET_FLAGS)+ | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_OR:+ SLJIT_ASSERT(!(flags & INV_IMM));+ return push_inst(compiler, ORR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_XOR:+ if (flags & INV_IMM) {+ SLJIT_ASSERT(src2 == SRC2_IMM);+ return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src1));+ }+ return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_SHL:+ case SLJIT_MSHL:+ shift_type = 0;+ is_masked = op == SLJIT_MSHL;+ break;++ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ shift_type = 1;+ is_masked = op == SLJIT_MLSHR;+ break;++ case SLJIT_ASHR:+ case SLJIT_MASHR:+ shift_type = 2;+ is_masked = op == SLJIT_MASHR;+ break;++ case SLJIT_ROTL:+ if (compiler->shift_imm == 0x20) {+ FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0));+ src2 = TMP_REG2;+ } else+ compiler->shift_imm = (sljit_uw)(-(sljit_sw)compiler->shift_imm) & 0x1f;+ /* fallthrough */++ case SLJIT_ROTR:+ shift_type = 3;+ is_masked = 0;+ break;++ case SLJIT_MULADD:+ return push_inst(compiler, MLA | RN(dst) | RD(dst) | RM8(src2) | RM(src1));++ default:+ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+ }++ SLJIT_ASSERT(!(flags & ARGS_SWAPPED) && !(flags & INV_IMM) && !(src2 & SRC2_IMM));++ if (compiler->shift_imm != 0x20) {+ SLJIT_ASSERT(src1 == TMP_REG1);++ if (compiler->shift_imm != 0)+ return push_inst(compiler, MOV | (flags & SET_FLAGS) |+ RD(dst) | (compiler->shift_imm << 7) | (shift_type << 5) | RM(src2));+ return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2));+ }++ SLJIT_ASSERT(src1 != TMP_REG2);++ if (is_masked) {+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG2) | RN(src2) | SRC2_IMM | 0x1f));+ src2 = TMP_REG2;+ }++ return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst)+ | RM8(src2) | (sljit_ins)(shift_type << 5) | 0x10 | RM(src1));+}++#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_u32 rol;++ if (imm <= 0xff)+ return SRC2_IMM | imm;++ if (!(imm & 0xff000000)) {+ imm <<= 8;+ rol = 8;+ } else {+ imm = (imm << 24) | (imm >> 8);+ rol = 0;+ }++ if (!(imm & 0xff000000)) {+ imm <<= 8;+ rol += 4;+ }++ if (!(imm & 0xf0000000)) {+ imm <<= 4;+ rol += 2;+ }++ if (!(imm & 0xc0000000)) {+ imm <<= 2;+ rol += 1;+ }++ if (!(imm & 0x00ffffff))+ return SRC2_IMM | (imm >> 24) | (rol << 8);+ return 0;+}++static sljit_uw compute_imm(sljit_uw imm, sljit_uw* imm2)+{+ sljit_uw mask;+ sljit_uw imm1;+ sljit_uw rol;++ /* Step1: Search a zero byte (8 continous zero bit). */+ mask = 0xff000000;+ rol = 8;+ while (1) {+ if (!(imm & mask)) {+ /* Rol imm by rol. */+ imm = (imm << rol) | (imm >> (32 - rol));+ /* Calculate arm rol. */+ rol = 4 + (rol >> 1);+ break;+ }++ rol += 2;+ mask >>= 2;+ if (mask & 0x3) {+ /* rol by 8. */+ imm = (imm << 8) | (imm >> 24);+ mask = 0xff00;+ rol = 24;+ while (1) {+ if (!(imm & mask)) {+ /* Rol imm by rol. */+ imm = (imm << rol) | (imm >> (32 - rol));+ /* Calculate arm rol. */+ rol = (rol >> 1) - 8;+ break;+ }+ rol += 2;+ mask >>= 2;+ if (mask & 0x3)+ return 0;+ }+ break;+ }+ }++ /* The low 8 bit must be zero. */+ SLJIT_ASSERT(!(imm & 0xff));++ if (!(imm & 0xff000000)) {+ imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);+ *imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);+ } else if (imm & 0xc0000000) {+ imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);+ imm <<= 8;+ rol += 4;++ if (!(imm & 0xff000000)) {+ imm <<= 8;+ rol += 4;+ }++ if (!(imm & 0xf0000000)) {+ imm <<= 4;+ rol += 2;+ }++ if (!(imm & 0xc0000000)) {+ imm <<= 2;+ rol += 1;+ }++ if (!(imm & 0x00ffffff))+ *imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);+ else+ return 0;+ } else {+ if (!(imm & 0xf0000000)) {+ imm <<= 4;+ rol += 2;+ }++ if (!(imm & 0xc0000000)) {+ imm <<= 2;+ rol += 1;+ }++ imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);+ imm <<= 8;+ rol += 4;++ if (!(imm & 0xf0000000)) {+ imm <<= 4;+ rol += 2;+ }++ if (!(imm & 0xc0000000)) {+ imm <<= 2;+ rol += 1;+ }++ if (!(imm & 0x00ffffff))+ *imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);+ else+ return 0;+ }++ return imm1;+}++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm)+{+ sljit_uw tmp;+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ sljit_uw imm1, imm2;+#else /* !SLJIT_CONFIG_ARM_V6 */+ if (!(imm & ~(sljit_uw)0xffff))+ return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff));+#endif /* SLJIT_CONFIG_ARM_V6 */++ /* Create imm by 1 inst. */+ tmp = get_imm(imm);+ if (tmp)+ return push_inst(compiler, MOV | RD(reg) | tmp);++ tmp = get_imm(~imm);+ if (tmp)+ return push_inst(compiler, MVN | RD(reg) | tmp);++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ /* Create imm by 2 inst. */+ imm1 = compute_imm(imm, &imm2);+ if (imm1 != 0) {+ FAIL_IF(push_inst(compiler, MOV | RD(reg) | imm1));+ return push_inst(compiler, ORR | RD(reg) | RN(reg) | imm2);+ }++ imm1 = compute_imm(~imm, &imm2);+ if (imm1 != 0) {+ FAIL_IF(push_inst(compiler, MVN | RD(reg) | imm1));+ return push_inst(compiler, BIC | RD(reg) | RN(reg) | imm2);+ }++ /* Load integer. */+ return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm);+#else /* !SLJIT_CONFIG_ARM_V6 */+ 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 /* SLJIT_CONFIG_ARM_V6 */+}++static 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_uw imm, offset_reg, tmp;+ sljit_sw mask = IS_TYPE1_TRANSFER(flags) ? 0xfff : 0xff;+ sljit_sw sign = IS_TYPE1_TRANSFER(flags) ? 0x1000 : 0x100;++ SLJIT_ASSERT(arg & SLJIT_MEM);+ SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -mask && argw <= mask));++ if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {+ tmp = (sljit_uw)(argw & (sign | mask));+ tmp = (sljit_uw)((argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask);++ FAIL_IF(load_immediate(compiler, tmp_reg, tmp));++ argw -= (sljit_sw)tmp;+ tmp = 1;++ if (argw < 0) {+ argw = -argw;+ tmp = 0;+ }++ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, tmp, reg, tmp_reg,+ (mask == 0xff) ? TYPE2_TRANSFER_IMM(argw) : argw));+ }++ if (arg & OFFS_REG_MASK) {+ offset_reg = OFFS_REG(arg);+ arg &= REG_MASK;+ argw &= 0x3;++ if (argw != 0 && (mask == 0xff)) {+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_ins)argw << 7)));+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));+ }++ /* Bit 25: RM is offset. */+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,+ RM(offset_reg) | (mask == 0xff ? 0 : (1 << 25)) | ((sljit_ins)argw << 7)));+ }++ arg &= REG_MASK;++ if (argw > mask) {+ tmp = (sljit_uw)(argw & (sign | mask));+ tmp = (sljit_uw)((argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask);+ imm = get_imm(tmp);++ if (imm) {+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));+ argw -= (sljit_sw)tmp;+ arg = tmp_reg;++ SLJIT_ASSERT(argw >= -mask && argw <= mask);+ }+ } else if (argw < -mask) {+ tmp = (sljit_uw)(-argw & (sign | mask));+ tmp = (sljit_uw)((-argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask);+ imm = get_imm(tmp);++ if (imm) {+ FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));+ argw += (sljit_sw)tmp;+ arg = tmp_reg;++ SLJIT_ASSERT(argw >= -mask && argw <= mask);+ }+ }++ if (argw <= mask && argw >= -mask) {+ if (argw >= 0) {+ if (mask == 0xff)+ argw = TYPE2_TRANSFER_IMM(argw);+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));+ }++ argw = -argw;++ if (mask == 0xff)+ argw = TYPE2_TRANSFER_IMM(argw);++ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, argw));+ }++ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,+ RM(tmp_reg) | (mask == 0xff ? 0 : (1 << 25))));+}++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)+{+ /* 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. */++ /* We prefers register and simple consts. */+ sljit_s32 dst_reg;+ sljit_s32 src1_reg = 0;+ sljit_s32 src2_reg = 0;+ sljit_s32 src2_tmp_reg = 0;+ sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;+ sljit_s32 neg_op = 0;+ sljit_u32 imm2;++ op = GET_OPCODE(op);++ if (flags & SET_FLAGS)+ inp_flags &= ~ALLOW_DOUBLE_IMM;++ if (dst == TMP_REG1)+ flags |= UNUSED_RETURN;++ SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));++ if (inp_flags & ALLOW_NEG_IMM) {+ switch (op) {+ case SLJIT_ADD:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ neg_op = SLJIT_SUB;+ break;+ case SLJIT_ADDC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ neg_op = SLJIT_SUBC;+ break;+ case SLJIT_SUB:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ neg_op = SLJIT_ADD;+ break;+ case SLJIT_SUBC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ neg_op = SLJIT_ADDC;+ break;+ }+ }++ do {+ if (!(inp_flags & ALLOW_IMM))+ break;++ if (src2 == SLJIT_IMM) {+ src2_reg = (sljit_s32)get_imm((sljit_uw)src2w);+ if (src2_reg)+ break;++ if (inp_flags & ALLOW_INV_IMM) {+ src2_reg = (sljit_s32)get_imm(~(sljit_uw)src2w);+ if (src2_reg) {+ flags |= INV_IMM;+ break;+ }+ }++ if (neg_op != 0) {+ src2_reg = (sljit_s32)get_imm((neg_op == SLJIT_ADD || neg_op == SLJIT_SUB) ? (sljit_uw)-src2w : ~(sljit_uw)src2w);+ if (src2_reg) {+ op = neg_op | GET_ALL_FLAGS(op);+ break;+ }+ }+ }++ if (src1 == SLJIT_IMM) {+ src2_reg = (sljit_s32)get_imm((sljit_uw)src1w);+ if (src2_reg) {+ flags |= ARGS_SWAPPED;+ src1 = src2;+ src1w = src2w;+ break;+ }++ if (inp_flags & ALLOW_INV_IMM) {+ src2_reg = (sljit_s32)get_imm(~(sljit_uw)src1w);+ if (src2_reg) {+ flags |= ARGS_SWAPPED | INV_IMM;+ src1 = src2;+ src1w = src2w;+ break;+ }+ }++ if (neg_op >= SLJIT_SUB) {+ /* Note: additive operation (commutative). */+ SLJIT_ASSERT(op == SLJIT_ADD || op == SLJIT_ADDC);++ src2_reg = (sljit_s32)get_imm((sljit_uw)-src1w);+ if (src2_reg) {+ src1 = src2;+ src1w = src2w;+ op = neg_op | GET_ALL_FLAGS(op);+ break;+ }+ }+ }+ } while(0);++ /* Destination. */+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG2;++ if (op <= SLJIT_MOV_P) {+ if (dst & SLJIT_MEM) {+ if (inp_flags & BYTE_SIZE)+ inp_flags &= ~SIGNED;++ if (FAST_IS_REG(src2))+ return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG1);+ }++ if (FAST_IS_REG(src2) && dst_reg != TMP_REG2)+ flags |= REGISTER_OP;++ src2_tmp_reg = dst_reg;+ } else {+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {+ if (!(dst & SLJIT_MEM) && (!(src2 & SLJIT_MEM) || op == SLJIT_REV_S16))+ flags |= REGISTER_OP;+ }++ src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;+ }++ if (src2_reg == 0 && (src2 & SLJIT_MEM)) {+ src2_reg = src2_tmp_reg;+ FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG1));+ }++ /* 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 if (!(inp_flags & ALLOW_DOUBLE_IMM) || src2_reg != 0 || op == SLJIT_SUB || op == SLJIT_SUBC) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));+ src1_reg = TMP_REG1;+ }++ /* Source 2. */+ if (src2_reg == 0) {+ src2_reg = src2_tmp_reg;++ if (FAST_IS_REG(src2))+ src2_reg = src2;+ else if (!(inp_flags & ALLOW_DOUBLE_IMM))+ FAIL_IF(load_immediate(compiler, src2_reg, (sljit_uw)src2w));+ else {+ SLJIT_ASSERT(!(flags & SET_FLAGS));++ if (src1_reg == 0) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));+ src1_reg = TMP_REG1;+ }++ src2_reg = (sljit_s32)compute_imm((sljit_uw)src2w, &imm2);++ if (src2_reg == 0 && neg_op != 0) {+ src2_reg = (sljit_s32)compute_imm((sljit_uw)-src2w, &imm2);+ if (src2_reg != 0)+ op = neg_op;+ }++ if (src2_reg == 0) {+ FAIL_IF(load_immediate(compiler, src2_tmp_reg, (sljit_uw)src2w));+ src2_reg = src2_tmp_reg;+ } else {+ FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg));+ src1_reg = dst_reg;+ src2_reg = (sljit_s32)imm2;++ if (op == SLJIT_ADDC)+ op = SLJIT_ADD;+ else if (op == SLJIT_SUBC)+ op = SLJIT_SUB;+ }+ }+ }++ if (src1_reg == 0) {+ SLJIT_ASSERT((inp_flags & ALLOW_DOUBLE_IMM) && !(flags & SET_FLAGS));++ src1_reg = (sljit_s32)compute_imm((sljit_uw)src1w, &imm2);++ if (src1_reg == 0 && neg_op != 0) {+ src1_reg = (sljit_s32)compute_imm((sljit_uw)-src1w, &imm2);+ if (src1_reg != 0)+ op = neg_op;+ }++ if (src1_reg == 0) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));+ src1_reg = TMP_REG1;+ } else {+ FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src2_reg, (sljit_uw)src1_reg));+ src1_reg = dst_reg;+ src2_reg = (sljit_s32)imm2;++ if (op == SLJIT_ADDC)+ op = SLJIT_ADD;+ }+ }++ FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg));++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;++ return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1);+}++#ifdef __cplusplus+extern "C" {+#endif++#if defined(__GNUC__)+extern unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator);+extern int __aeabi_idivmod(int numerator, int denominator);+#else+#error "Software divmod functions are needed"+#endif++#ifdef __cplusplus+}+#endif++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+ sljit_uw saved_reg_list[3];+ sljit_sw saved_reg_count;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ FAIL_IF(push_inst(compiler, BKPT));+ break;+ case SLJIT_NOP:+ FAIL_IF(push_inst(compiler, NOP));+ break;+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+ return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)+ | RN(SLJIT_R1) | RD(SLJIT_R0) | RM8(SLJIT_R0) | RM(SLJIT_R1));+ 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, STR | 0x2d0000 | (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, STR | 0x8d0004 | (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, STR | 0x8d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));+ }+ }++#if defined(__GNUC__)+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));+#else+#error "Software divmod functions are needed"+#endif++ if (saved_reg_count > 0) {+ if (saved_reg_count >= 3) {+ SLJIT_ASSERT(saved_reg_list[2] < 8);+ FAIL_IF(push_inst(compiler, LDR | 0x8d0008 | (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, LDR | 0x8d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));+ }+ return push_inst(compiler, (LDR ^ (1 << 24)) | 0x8d0000 | (sljit_ins)(saved_reg_count >= 3 ? 16 : 8)+ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);+ }+ return SLJIT_SUCCESS;+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++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);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ case SLJIT_MOV_P:+ return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOV_U8:+ return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);++ case SLJIT_MOV_S8:+ return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);++ case SLJIT_MOV_U16:+ return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);++ case SLJIT_MOV_S16:+ return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);++ case SLJIT_CLZ:+ case SLJIT_CTZ:+ case SLJIT_REV:+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ return emit_op(compiler, op, HALF_SIZE, dst, dstw, TMP_REG1, 0, src, srcw);+ }++ return SLJIT_SUCCESS;+}++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_s32 inp_flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ case SLJIT_ADDC:+ case SLJIT_SUB:+ case SLJIT_SUBC:+ return emit_op(compiler, op, ALLOW_IMM | ALLOW_NEG_IMM | ALLOW_DOUBLE_IMM, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_OR:+ return emit_op(compiler, op, ALLOW_IMM | ALLOW_DOUBLE_IMM, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_XOR:+ inp_flags = ALLOW_IMM | ALLOW_DOUBLE_IMM;+ if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {+ inp_flags |= ALLOW_INV_IMM;+ }+ return emit_op(compiler, op, inp_flags, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_MUL:+ return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_AND:+ return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_MSHL:+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (src2 == SLJIT_IMM) {+ compiler->shift_imm = src2w & 0x1f;+ return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w);+ } else {+ compiler->shift_imm = 0x20;+ return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);+ }+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ switch (GET_OPCODE(op)) {+ case SLJIT_MULADD:+ return emit_op(compiler, op, 0, dst_reg, 0, src1, src1w, src2, src2w);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+ sljit_s32 is_left;++ CHECK_ERROR();+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));++ op = GET_OPCODE(op);+ is_left = (op == SLJIT_SHL || op == SLJIT_MSHL);++ if (src1_reg == src2_reg) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, is_left ? SLJIT_ROTL : SLJIT_ROTR, dst_reg, 0, src1_reg, 0, src3, src3w);+ }++ ADJUST_LOCAL_OFFSET(src3, src3w);++ /* Shift type of ROR is 3. */+ if (src3 == SLJIT_IMM) {+ src3w &= 0x1f;++ if (src3w == 0)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src1_reg) | ((sljit_ins)(is_left ? 0 : 1) << 5) | ((sljit_ins)src3w << 7)));+ src3w = (src3w ^ 0x1f) + 1;+ return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM(src2_reg) | ((sljit_ins)(is_left ? 1 : 0) << 5) | ((sljit_ins)src3w << 7));+ }++ if (src3 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src3, src3w, TMP_REG2));+ src3 = TMP_REG2;+ }++ if (op == SLJIT_MSHL || op == SLJIT_MLSHR || dst_reg == src3) {+ FAIL_IF(push_inst(compiler, AND | SRC2_IMM | RD(TMP_REG2) | RN(src3) | 0x1f));+ src3 = TMP_REG2;+ }++ FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM8(src3) | ((sljit_ins)(is_left ? 0 : 1) << 5) | 0x10 | RM(src1_reg)));+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src2_reg) | ((sljit_ins)(is_left ? 1 : 0) << 5) | (1 << 7)));+ FAIL_IF(push_inst(compiler, EOR | SRC2_IMM | RD(TMP_REG2) | RN(src3) | 0x1f));+ return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM8(TMP_REG2) | ((sljit_ins)(is_left ? 1 : 0) << 5) | 0x10 | RM(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));++ return push_inst(compiler, BX | RM(TMP_REG2));+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ SLJIT_ASSERT(src & SLJIT_MEM);+ return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 size, dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ switch (op) {+ case SLJIT_FAST_ENTER:+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(dst))+ return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2));+ break;+ case SLJIT_GET_RETURN_ADDRESS:+ size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);++ if (compiler->fsaveds > 0 || compiler->fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ /* The size of pc is not added above. */+ if ((size & SSIZE_OF(sw)) == 0)+ size += SSIZE_OF(sw);++ size += GET_SAVED_FLOAT_REGISTERS_SIZE(compiler->fscratches, compiler->fsaveds, f64);+ }++ SLJIT_ASSERT(((compiler->local_size + size + SSIZE_OF(sw)) & 0x7) == 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, TMP_REG1));+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));++ if (type == SLJIT_GP_REGISTER)+ return reg_map[reg];++ if (type == SLJIT_FLOAT_REGISTER || type == SLJIT_SIMD_REG_64)+ return freg_map[reg];++ if (type != SLJIT_SIMD_REG_128)+ return freg_map[reg] & ~0x1;++ return -1;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+ SLJIT_UNUSED_ARG(size);+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define FPU_LOAD (1 << 20)+#define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \+ ((inst) | (sljit_ins)((add) << 23) | RN(base) | VD(freg) | (sljit_ins)(offs))++static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ sljit_uw imm;+ sljit_ins inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD));++ SLJIT_ASSERT(arg & SLJIT_MEM);+ arg &= ~SLJIT_MEM;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (((sljit_ins)argw & 0x3) << 7)));+ arg = TMP_REG1;+ argw = 0;+ }++ /* Fast loads and stores. */+ 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));++ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);+ if (imm) {+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | imm));+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2));+ }+ imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);+ if (imm) {+ argw = -argw;+ FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG1) | RN(arg & REG_MASK) | imm));+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2));+ }+ }++ if (arg) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(TMP_REG1)));+ }+ else+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));++ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0));+}++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_32;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_32, TMP_FREG1, src, 0)));++ if (FAST_IS_REG(dst))+ return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | VN(TMP_FREG1));++ /* Store the integer value from a VFP register. */+ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);+}++static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, VMOV | RD(src) | VN(TMP_FREG1)));+ else if (src & SLJIT_MEM) {+ /* Load the integer value into a VFP register. */+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));+ }+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));+ FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | VN(TMP_FREG1)));+ }++ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(ins, ins & SLJIT_32, dst_r, TMP_FREG1, 0)));++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, (ins & SLJIT_32), TMP_FREG1, dst, dstw);+ return SLJIT_SUCCESS;+}++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)+{+ return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_S32 | (~op & SLJIT_32), dst, dstw, src, srcw);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_U32 | (~op & SLJIT_32), dst, dstw, src, srcw);+}++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_32;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));+ src2 = TMP_FREG2;+ }++ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_32, src1, src2, 0)));+ FAIL_IF(push_inst(compiler, VMRS));++ if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL)+ return SLJIT_SUCCESS;++ return push_inst(compiler, (CMP - CONDITIONAL) | (0x60000000 /* VS */) | SET_FLAGS | RN(TMP_REG1) | RM(TMP_REG1));+}++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_s32 dst_r;++ CHECK_ERROR();++ SLJIT_COMPILE_ASSERT((SLJIT_32 == 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_32;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (!(dst & SLJIT_MEM))+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_32, dst_r, src, 0)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_32, dst_r, src, 0)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src, 0)));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_32, dst_r, src, 0)));+ op ^= SLJIT_32;+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);+ return SLJIT_SUCCESS;+}++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_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ op ^= SLJIT_32;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));+ src2 = TMP_FREG2;+ }++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));+ src1 = TMP_FREG1;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_32, dst_r, src2, src1)));+ break;+ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_32, dst_r, src2, src1)));+ break;+ case SLJIT_MUL_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_32, dst_r, src2, src1)));+ break;+ case SLJIT_DIV_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_32, dst_r, src2, src1)));+ break;+ case SLJIT_COPYSIGN_F64:+ FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(src2) | RD(TMP_REG1) | ((op & SLJIT_32) ? (1 << 7) : 0)));+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src1, 0)));+ FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | SRC2_IMM | 0));+ return push_inst(compiler, EMIT_FPU_OPERATION((VNEG_F32 & ~COND_MASK) | 0xb0000000, op & SLJIT_32, dst_r, dst_r, 0));+ }++ if (dst_r != dst)+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw));++ return SLJIT_SUCCESS;+}++#undef EMIT_FPU_DATA_TRANSFER++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+#if defined(__ARM_NEON) && __ARM_NEON+ sljit_u32 exp;+ sljit_ins ins;+#endif /* NEON */+ union {+ sljit_u32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++#if defined(__ARM_NEON) && __ARM_NEON+ if ((u.imm << (32 - 19)) == 0) {+ exp = (u.imm >> (23 + 2)) & 0x3f;++ if (exp == 0x20 || exp == 0x1f) {+ ins = ((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f);+ return push_inst(compiler, (VMOV_F32 ^ (1 << 6)) | ((ins & 0xf0) << 12) | VD(freg) | (ins & 0xf));+ }+ }+#endif /* NEON */++ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));+ return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+#if defined(__ARM_NEON) && __ARM_NEON+ sljit_u32 exp;+ sljit_ins ins;+#endif /* NEON */+ union {+ sljit_u32 imm[2];+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++#if defined(__ARM_NEON) && __ARM_NEON+ if (u.imm[0] == 0 && (u.imm[1] << (64 - 48)) == 0) {+ exp = (u.imm[1] >> ((52 - 32) + 2)) & 0x1ff;++ if (exp == 0x100 || exp == 0xff) {+ ins = ((u.imm[1] >> (56 - 32)) & 0x80) | ((u.imm[1] >> (48 - 32)) & 0x7f);+ return push_inst(compiler, (VMOV_F32 ^ (1 << 6)) | (1 << 8) | ((ins & 0xf0) << 12) | VD(freg) | (ins & 0xf));+ }+ }+#endif /* NEON */++ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));+ if (u.imm[0] == u.imm[1])+ return push_inst(compiler, VMOV2 | RN(TMP_REG1) | RD(TMP_REG1) | VM(freg));++ FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));+ return push_inst(compiler, VMOV2 | RN(TMP_REG2) | RD(TMP_REG1) | VM(freg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_s32 reg2;+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ if (reg & REG_PAIR_MASK) {+ reg2 = REG_PAIR_SECOND(reg);+ reg = REG_PAIR_FIRST(reg);++ inst = VMOV2 | RN(reg) | RD(reg2) | VM(freg);+ } else {+ inst = VMOV | VN(freg) | RD(reg);++ if (!(op & SLJIT_32))+ inst |= 1 << 7;+ }++ if (GET_OPCODE(op) == SLJIT_COPY_FROM_F64)+ inst |= 1 << 20;++ return push_inst(compiler, inst);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_ATOMIC_STORED:+ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ return 0x00000000;++ case SLJIT_NOT_EQUAL:+ case SLJIT_ATOMIC_NOT_STORED:+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ return 0x10000000;++ case SLJIT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)+ return 0x20000000;+ /* fallthrough */++ case SLJIT_LESS:+ return 0x30000000;++ case SLJIT_NOT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)+ return 0x30000000;+ /* fallthrough */++ case SLJIT_GREATER_EQUAL:+ return 0x20000000;++ case SLJIT_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ return 0x80000000;++ case SLJIT_LESS_EQUAL:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ return 0x90000000;++ case SLJIT_SIG_LESS:+ case SLJIT_UNORDERED_OR_LESS:+ return 0xb0000000;++ case SLJIT_SIG_GREATER_EQUAL:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ return 0xa0000000;++ case SLJIT_SIG_GREATER:+ case SLJIT_F_GREATER:+ case SLJIT_ORDERED_GREATER:+ return 0xc0000000;++ case SLJIT_SIG_LESS_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ return 0xd0000000;++ case SLJIT_OVERFLOW:+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))+ return 0x10000000;+ /* fallthrough */++ case SLJIT_UNORDERED:+ return 0x60000000;++ case SLJIT_NOT_OVERFLOW:+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))+ return 0x00000000;+ /* fallthrough */++ case SLJIT_ORDERED:+ return 0x70000000;++ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ return 0x40000000;++ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ return 0x50000000;++ default:+ SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);+ return 0xe0000000;+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ if (type >= SLJIT_FAST_CALL)+ PTR_FAIL_IF(prepare_blx(compiler));++ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,+ type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(compiler, type), 0));++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ compiler->patches++;++ if (type >= SLJIT_FAST_CALL) {+ jump->flags |= IS_BL;+ jump->addr = compiler->size;+ PTR_FAIL_IF(emit_blx(compiler));+ }+#else /* !SLJIT_CONFIG_ARM_V6 */+ jump->addr = compiler->size;+ if (type >= SLJIT_FAST_CALL)+ jump->flags |= IS_BL;+ PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(compiler, type)));+ compiler->size += JUMP_MAX_SIZE - 1;+#endif /* SLJIT_CONFIG_ARM_V6 */+ return jump;+}++#ifdef __SOFTFP__++static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)+{+ sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;+ sljit_u32 offset = 0;+ sljit_u32 word_arg_offset = 0;+ sljit_u32 src_offset = 4 * sizeof(sljit_sw);+ sljit_u32 float_arg_count = 0;+ sljit_s32 types = 0;+ sljit_u8 offsets[4];+ sljit_u8 *offset_ptr = offsets;++ if (src && FAST_IS_REG(*src))+ src_offset = (sljit_u32)reg_map[*src] * sizeof(sljit_sw);++ arg_types >>= SLJIT_ARG_SHIFT;++ while (arg_types) {+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);++ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (offset & 0x7)+ offset += sizeof(sljit_sw);+ *offset_ptr++ = (sljit_u8)offset;+ offset += sizeof(sljit_f64);+ float_arg_count++;+ break;+ case SLJIT_ARG_TYPE_F32:+ *offset_ptr++ = (sljit_u8)offset;+ offset += sizeof(sljit_f32);+ float_arg_count++;+ break;+ default:+ *offset_ptr++ = (sljit_u8)offset;+ offset += sizeof(sljit_sw);+ word_arg_offset += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {+ /* Keep lr register on the stack. */+ if (is_tail_call)+ offset += sizeof(sljit_sw);++ offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_u32)0x7;++ *extra_space = offset;++ if (is_tail_call)+ FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));+ else+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | offset));+ } else {+ if (is_tail_call)+ FAIL_IF(emit_stack_frame_release(compiler, -1));+ *extra_space = 0;+ }++ /* Process arguments in reversed direction. */+ while (types) {+ switch (types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ float_arg_count--;+ offset = *(--offset_ptr);++ SLJIT_ASSERT((offset & 0x7) == 0);++ if (offset < 4 * sizeof(sljit_sw)) {+ if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));+ *src = TMP_REG1;+ }+ FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));+ } else+ FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP)+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));+ break;+ case SLJIT_ARG_TYPE_F32:+ float_arg_count--;+ offset = *(--offset_ptr);++ if (offset < 4 * sizeof(sljit_sw)) {+ if (src_offset == offset) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));+ *src = TMP_REG1;+ }+ FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));+ } else+ FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP)+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));+ break;+ default:+ word_arg_offset -= sizeof(sljit_sw);+ offset = *(--offset_ptr);++ SLJIT_ASSERT(offset >= word_arg_offset);++ if (offset != word_arg_offset) {+ if (offset < 4 * sizeof(sljit_sw)) {+ if (src_offset == offset) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));+ *src = TMP_REG1;+ }+ else if (src_offset == word_arg_offset) {+ *src = (sljit_s32)(SLJIT_R0 + (offset >> 2));+ src_offset = offset;+ }+ FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2)));+ } else+ FAIL_IF(push_inst(compiler, STR | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));+ }+ break;+ }++ types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)+ FAIL_IF(push_inst(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)+ FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12)));++ return SLJIT_SUCCESS;+}++#else /* !__SOFTFP__ */++static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ sljit_u32 offset = SLJIT_FR0;+ sljit_u32 new_offset = SLJIT_FR0;+ sljit_u32 f32_offset = 0;++ /* Remove return value. */+ arg_types >>= SLJIT_ARG_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (offset != new_offset)+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,+ SLJIT_32, new_offset, offset, 0)));++ new_offset++;+ offset++;+ break;+ case SLJIT_ARG_TYPE_F32:+ if (f32_offset != 0) {+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,+ 0x400000, f32_offset, offset, 0)));+ f32_offset = 0;+ } else {+ if (offset != new_offset)+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,+ 0, new_offset, offset, 0)));+ f32_offset = new_offset;+ new_offset++;+ }+ offset++;+ break;+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++#endif /* __SOFTFP__ */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+#ifdef __SOFTFP__+ struct sljit_jump *jump;+ sljit_u32 extra_space = (sljit_u32)type;+#endif++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++#ifdef __SOFTFP__+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {+ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));+ SLJIT_ASSERT((extra_space & 0x7) == 0);++ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);++ SLJIT_SKIP_CHECKS(compiler);+ jump = sljit_emit_jump(compiler, type);+ PTR_FAIL_IF(jump == NULL);++ if (extra_space > 0) {+ if (type & SLJIT_CALL_RETURN)+ PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,+ TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));++ PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));++ if (type & SLJIT_CALL_RETURN) {+ PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));+ return jump;+ }+ }++ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));+ PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));+ return jump;+ }+#endif /* __SOFTFP__ */++ if (type & SLJIT_CALL_RETURN) {+ PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);+ }++#ifndef __SOFTFP__+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));+#endif /* !__SOFTFP__ */++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, type);+}++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;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);++ if (src != SLJIT_IMM) {+ if (FAST_IS_REG(src)) {+ SLJIT_ASSERT(reg_map[src] != 14);+ return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));+ }++ SLJIT_ASSERT(src & SLJIT_MEM);+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1));+ }++ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));+ jump->u.target = (sljit_uw)srcw;++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ if (type >= SLJIT_FAST_CALL)+ FAIL_IF(prepare_blx(compiler));+ jump->addr = compiler->size;+ FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));+ if (type >= SLJIT_FAST_CALL) {+ jump->addr = compiler->size;+ FAIL_IF(emit_blx(compiler));+ }+#else /* !SLJIT_CONFIG_ARM_V6 */+ jump->addr = compiler->size;+ FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));+ compiler->size += JUMP_MAX_SIZE - 1;+#endif /* SLJIT_CONFIG_ARM_V6 */+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+#ifdef __SOFTFP__+ sljit_u32 extra_space = (sljit_u32)type;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));+ src = TMP_REG1;+ }++#ifdef __SOFTFP__+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {+ FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));+ SLJIT_ASSERT((extra_space & 0x7) == 0);++ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)+ type = SLJIT_JUMP;++ SLJIT_SKIP_CHECKS(compiler);+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));++ if (extra_space > 0) {+ if (type & SLJIT_CALL_RETURN)+ FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,+ TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));++ FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));++ if (type & SLJIT_CALL_RETURN)+ return push_inst(compiler, BX | RM(TMP_REG2));+ }++ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));+ return softfloat_post_call_with_args(compiler, arg_types);+ }+#endif /* __SOFTFP__ */++ if (type & SLJIT_CALL_RETURN) {+ FAIL_IF(emit_stack_frame_release(compiler, -1));+ type = SLJIT_JUMP;+ }++#ifndef __SOFTFP__+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ FAIL_IF(hardfloat_call_with_args(compiler, arg_types));+#endif /* !__SOFTFP__ */++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+}++#ifdef __SOFTFP__++static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ if (compiler->options & SLJIT_ENTER_REG_ARG) {+ if (src == SLJIT_FR0)+ return SLJIT_SUCCESS;++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);+ }++ if (FAST_IS_REG(src)) {+ if (op & SLJIT_32)+ return push_inst(compiler, VMOV | (1 << 20) | RD(SLJIT_R0) | VN(src));+ return push_inst(compiler, VMOV2 | (1 << 20) | RD(SLJIT_R0) | RN(SLJIT_R1) | VM(src));+ }++ SLJIT_SKIP_CHECKS(compiler);++ if (op & SLJIT_32)+ return sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src, srcw);+ return sljit_emit_mem(compiler, SLJIT_MOV, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), src, srcw);+}++#endif /* __SOFTFP__ */++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_s32 dst_reg, flags = GET_ALL_FLAGS(op);+ sljit_ins cc, ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+ cc = get_cc(compiler, type);+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (op < SLJIT_ADD) {+ FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | SRC2_IMM | 0));+ FAIL_IF(push_inst(compiler, ((MOV | RD(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));+ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+ }++ ins = (op == SLJIT_AND ? AND : (op == SLJIT_OR ? ORR : EOR));++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));++ FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));++ if (op == SLJIT_AND)+ FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));++ if (flags & SLJIT_SET_Z)+ return push_inst(compiler, MOV | SET_FLAGS | RD(TMP_REG2) | RM(dst_reg));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+ sljit_ins cc, tmp;++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (src2_reg != dst_reg && src1 == dst_reg) {+ src1 = src2_reg;+ src1w = 0;+ src2_reg = dst_reg;+ type ^= 0x1;+ }++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, (src2_reg != dst_reg) ? dst_reg : TMP_REG1, src1, src1w, TMP_REG1));++ if (src2_reg != dst_reg) {+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else {+ src1 = TMP_REG1;+ src1w = 0;+ }+ } else if (dst_reg != src2_reg)+ FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src2_reg)));++ cc = get_cc(compiler, type & ~SLJIT_32);++ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {+ tmp = get_imm((sljit_uw)src1w);+ if (tmp)+ return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc);++ tmp = get_imm(~(sljit_uw)src1w);+ if (tmp)+ return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc);++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ tmp = (sljit_ins)src1w;+ 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 /* !SLJIT_CONFIG_ARM_V7 */+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));+ src1 = TMP_REG1;+#endif /* SLJIT_CONFIG_ARM_V7 */+ }++ return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src1)) & ~COND_MASK) | cc);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+ sljit_ins cc;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ type ^= SLJIT_32;++ if (dst_freg != src2_freg) {+ if (dst_freg == src1) {+ src1 = src2_freg;+ src1w = 0;+ type ^= 0x1;+ } else+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, (type & SLJIT_32), dst_freg, src2_freg, 0)));+ }++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) | FPU_LOAD, TMP_FREG2, src1, src1w));+ src1 = TMP_FREG2;+ }++ cc = get_cc(compiler, type & ~SLJIT_32);+ return push_inst(compiler, EMIT_FPU_OPERATION((VMOV_F32 & ~COND_MASK) | cc, (type & SLJIT_32), dst_freg, src1, 0));+}++#undef EMIT_FPU_OPERATION++static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset)+{+ sljit_s32 arg = *mem;+ sljit_sw argw = *memw;+ sljit_uw imm, tmp;+ sljit_sw mask = 0xfff;+ sljit_sw sign = 0x1000;++ SLJIT_ASSERT(max_offset >= 0xf00);++ *mem = TMP_REG1;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ *memw = 0;+ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)(argw & 0x3) << 7));+ }++ arg &= REG_MASK;++ if (arg) {+ if (argw <= max_offset && argw >= -mask) {+ *mem = arg;+ return SLJIT_SUCCESS;+ }++ if (argw >= 0) {+ tmp = (sljit_uw)(argw & (sign | mask));+ tmp = (sljit_uw)((argw + ((tmp <= (sljit_uw)max_offset || tmp == (sljit_uw)sign) ? 0 : sign)) & ~mask);+ imm = get_imm(tmp);++ if (imm) {+ *memw = argw - (sljit_sw)tmp;+ SLJIT_ASSERT(*memw >= -mask && *memw <= max_offset);++ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | imm);+ }+ } else {+ tmp = (sljit_uw)(-argw & (sign | mask));+ tmp = (sljit_uw)((-argw + ((tmp <= (sljit_uw)((sign << 1) - max_offset - 1)) ? 0 : sign)) & ~mask);+ imm = get_imm(tmp);++ if (imm) {+ *memw = argw + (sljit_sw)tmp;+ SLJIT_ASSERT(*memw >= -mask && *memw <= max_offset);++ return push_inst(compiler, SUB | RD(TMP_REG1) | RN(arg) | imm);+ }+ }+ }++ tmp = (sljit_uw)(argw & (sign | mask));+ tmp = (sljit_uw)((argw + ((tmp <= (sljit_uw)max_offset || tmp == (sljit_uw)sign) ? 0 : sign)) & ~mask);+ *memw = argw - (sljit_sw)tmp;++ FAIL_IF(load_immediate(compiler, TMP_REG1, tmp));++ if (arg == 0)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(arg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (!(reg & REG_PAIR_MASK))+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);++ ADJUST_LOCAL_OFFSET(mem, memw);++ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));++ flags = WORD_SIZE;++ if (!(type & SLJIT_MEM_STORE)) {+ if (REG_PAIR_FIRST(reg) == (mem & REG_MASK)) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1));+ return emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1);+ }++ flags = WORD_SIZE | LOAD_DATA;+ }++ FAIL_IF(emit_op_mem(compiler, flags, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1));+ return emit_op_mem(compiler, flags, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 flags;+ sljit_ins is_type1_transfer, inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));++ is_type1_transfer = 1;++ switch (type & 0xff) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ case SLJIT_MOV_P:+ flags = WORD_SIZE;+ break;+ case SLJIT_MOV_U8:+ flags = BYTE_SIZE;+ break;+ case SLJIT_MOV_S8:+ if (!(type & SLJIT_MEM_STORE))+ is_type1_transfer = 0;+ flags = BYTE_SIZE | SIGNED;+ break;+ case SLJIT_MOV_U16:+ is_type1_transfer = 0;+ flags = HALF_SIZE;+ break;+ case SLJIT_MOV_S16:+ is_type1_transfer = 0;+ flags = HALF_SIZE | SIGNED;+ break;+ default:+ SLJIT_UNREACHABLE();+ flags = WORD_SIZE;+ break;+ }++ if (!(type & SLJIT_MEM_STORE))+ flags |= LOAD_DATA;++ SLJIT_ASSERT(is_type1_transfer == !!IS_TYPE1_TRANSFER(flags));++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ if (!is_type1_transfer && memw != 0)+ return SLJIT_ERR_UNSUPPORTED;+ } else {+ if (is_type1_transfer) {+ if (memw > 4095 || memw < -4095)+ return SLJIT_ERR_UNSUPPORTED;+ } else if (memw > 255 || memw < -255)+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ memw &= 0x3;++ inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | ((sljit_ins)memw << 7));++ if (is_type1_transfer)+ inst |= (1 << 25);++ if (type & SLJIT_MEM_POST)+ inst ^= (1 << 24);+ else+ inst |= (1 << 21);++ return push_inst(compiler, inst);+ }++ inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0);++ if (type & SLJIT_MEM_POST)+ inst ^= (1 << 24);+ else+ inst |= (1 << 21);++ if (is_type1_transfer) {+ if (memw >= 0)+ inst |= (1 << 23);+ else+ memw = -memw;++ return push_inst(compiler, inst | (sljit_ins)memw);+ }++ if (memw >= 0)+ inst |= (1 << 23);+ else+ memw = -memw;++ return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_ins)memw));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));++ if (type & SLJIT_MEM_ALIGNED_32)+ return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw);++ if (type & SLJIT_MEM_STORE) {+ FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2)));++ if (type & SLJIT_32)+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1);++ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));+ mem |= SLJIT_MEM;++ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));+ FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2)));+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw + 4, TMP_REG1);+ }++ if (type & SLJIT_32) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));+ return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG2));+ }++ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));+ mem |= SLJIT_MEM;++ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, mem, memw + 4, TMP_REG1));+ return push_inst(compiler, VMOV2 | VM(freg) | RD(TMP_REG2) | RN(TMP_REG1));+}++static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw)+{+ sljit_s32 mem = *mem_ptr;+ sljit_uw imm;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ *mem_ptr = TMP_REG1;+ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 7));+ }++ if (SLJIT_UNLIKELY(!(mem & REG_MASK))) {+ *mem_ptr = TMP_REG1;+ return load_immediate(compiler, TMP_REG1, (sljit_uw)memw);+ }++ mem &= REG_MASK;++ if (memw == 0) {+ *mem_ptr = mem;+ return SLJIT_SUCCESS;+ }++ *mem_ptr = TMP_REG1;+ imm = get_imm((sljit_uw)(memw < 0 ? -memw : memw));++ if (imm != 0)+ return push_inst(compiler, ((memw < 0) ? SUB : ADD) | RD(TMP_REG1) | RN(mem) | imm);++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));+ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(mem));+}++static SLJIT_INLINE sljit_s32 simd_get_quad_reg_index(sljit_s32 freg)+{+ freg += freg & 0x1;++ SLJIT_ASSERT((freg_map[freg] & 0x1) == (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS));++ if (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)+ freg--;++ return freg;+}++#define SLJIT_QUAD_OTHER_HALF(freg) ((((freg) & 0x1) << 1) - 1)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4)+ freg = simd_get_quad_reg_index(freg);++ if (!(srcdst & SLJIT_MEM)) {+ if (reg_size == 4)+ srcdst = simd_get_quad_reg_index(srcdst);++ if (type & SLJIT_SIMD_STORE)+ ins = VD(srcdst) | VN(freg) | VM(freg);+ else+ ins = VD(freg) | VN(srcdst) | VM(srcdst);++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 6;++ return push_inst(compiler, VORR | ins);+ }++ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));++ if (elem_size > 3)+ elem_size = 3;++ ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD(freg)+ | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8));++ SLJIT_ASSERT(reg_size >= alignment);++ if (alignment == 3)+ ins |= 0x10;+ else if (alignment >= 3)+ ins |= 0x20;++ return push_inst(compiler, ins | RN(srcdst) | ((sljit_ins)elem_size) << 6 | 0xf);+}++static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value)+{+ sljit_ins result;++ if (elem_size > 1 && (sljit_u16)value == (value >> 16)) {+ elem_size = 1;+ value = (sljit_u16)value;+ }++ if (elem_size == 1 && (sljit_u8)value == (value >> 8)) {+ elem_size = 0;+ value = (sljit_u8)value;+ }++ switch (elem_size) {+ case 0:+ SLJIT_ASSERT(value <= 0xff);+ result = 0xe00;+ break;+ case 1:+ SLJIT_ASSERT(value <= 0xffff);+ result = 0;++ while (1) {+ if (value <= 0xff) {+ result |= 0x800;+ break;+ }++ if ((value & 0xff) == 0) {+ value >>= 8;+ result |= 0xa00;+ break;+ }++ if (result != 0)+ return ~(sljit_ins)0;++ value ^= (sljit_uw)0xffff;+ result = (1 << 5);+ }+ break;+ default:+ SLJIT_ASSERT(value <= 0xffffffff);+ result = 0;++ while (1) {+ if (value <= 0xff) {+ result |= 0x000;+ break;+ }++ if ((value & ~(sljit_uw)0xff00) == 0) {+ value >>= 8;+ result |= 0x200;+ break;+ }++ if ((value & ~(sljit_uw)0xff0000) == 0) {+ value >>= 16;+ result |= 0x400;+ break;+ }++ if ((value & ~(sljit_uw)0xff000000) == 0) {+ value >>= 24;+ result |= 0x600;+ break;+ }++ if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) {+ value >>= 8;+ result |= 0xc00;+ break;+ }++ if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) {+ value >>= 16;+ result |= 0xd00;+ break;+ }++ if (result != 0)+ return ~(sljit_ins)0;++ value = ~value;+ result = (1 << 5);+ }+ break;+ }++ return ((sljit_ins)value & 0xf) | (((sljit_ins)value & 0x70) << 12) | (((sljit_ins)value & 0x80) << 17) | result;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins, imm;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4)+ freg = simd_get_quad_reg_index(freg);++ if (src == SLJIT_IMM && srcw == 0)+ return push_inst(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD(freg));++ if (SLJIT_UNLIKELY(elem_size == 3)) {+ SLJIT_ASSERT(type & SLJIT_SIMD_FLOAT);++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, freg, src, srcw));+ src = freg;+ } else if (freg != src)+ FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src)));++ freg += SLJIT_QUAD_OTHER_HALF(freg);++ if (freg != src)+ return push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src));+ return SLJIT_SUCCESS;+ }++ if (src & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));++ ins = (sljit_ins)(elem_size << 6);++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 5;++ return push_inst(compiler, VLD1_r | ins | VD(freg) | RN(src) | 0xf);+ }++ if (type & SLJIT_SIMD_FLOAT) {+ SLJIT_ASSERT(elem_size == 2);+ ins = ((sljit_ins)freg_ebit_map[src] << (16 + 2 + 1)) | ((sljit_ins)1 << (16 + 2));++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 6;++ return push_inst(compiler, VDUP_s | ins | VD(freg) | (sljit_ins)freg_map[src]);+ }++ if (src == SLJIT_IMM) {+ if (elem_size < 2)+ srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;++ imm = simd_get_imm(elem_size, (sljit_uw)srcw);++ if (imm != ~(sljit_ins)0) {+ if (reg_size == 4)+ imm |= (sljit_ins)1 << 6;++ return push_inst(compiler, VMOV_i | imm | VD(freg));+ }++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));+ src = TMP_REG1;+ }++ switch (elem_size) {+ case 0:+ ins = 1 << 22;+ break;+ case 1:+ ins = 1 << 5;+ break;+ default:+ ins = 0;+ break;+ }++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 21;++ return push_inst(compiler, VDUP | ins | VN(freg) | RD(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4)+ freg = simd_get_quad_reg_index(freg);++ if (type & SLJIT_SIMD_LANE_ZERO) {+ ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 6);++ if (type & SLJIT_SIMD_FLOAT) {+ if (elem_size == 3 && !(srcdst & SLJIT_MEM)) {+ if (lane_index == 1)+ freg += SLJIT_QUAD_OTHER_HALF(freg);++ if (srcdst != freg)+ FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(srcdst) | VM(srcdst)));++ freg += SLJIT_QUAD_OTHER_HALF(freg);+ return push_inst(compiler, VMOV_i | VD(freg));+ }++ if (srcdst == freg || (elem_size == 3 && srcdst == (freg + SLJIT_QUAD_OTHER_HALF(freg)))) {+ FAIL_IF(push_inst(compiler, VORR | ins | VD(TMP_FREG2) | VN(freg) | VM(freg)));+ srcdst = TMP_FREG2;+ srcdstw = 0;+ }+ }++ FAIL_IF(push_inst(compiler, VMOV_i | ins | VD(freg)));+ }++ if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) {+ lane_index -= (0x8 >> elem_size);+ freg += SLJIT_QUAD_OTHER_HALF(freg);+ }++ if (srcdst & SLJIT_MEM) {+ if (elem_size == 3)+ return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, freg, srcdst, srcdstw);++ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));++ lane_index = lane_index << elem_size;+ ins = (sljit_ins)((elem_size << 10) | (lane_index << 5));+ return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD(freg) | RN(srcdst) | 0xf);+ }++ if (type & SLJIT_SIMD_FLOAT) {+ if (elem_size == 3) {+ if (type & SLJIT_SIMD_STORE)+ return push_inst(compiler, VORR | VD(srcdst) | VN(freg) | VM(freg));+ return push_inst(compiler, VMOV_F32 | SLJIT_32 | VD(freg) | VM(srcdst));+ }++ if (type & SLJIT_SIMD_STORE) {+ if (freg_ebit_map[freg] == 0) {+ if (lane_index == 1)+ freg = SLJIT_F64_SECOND(freg);++ return push_inst(compiler, VMOV_F32 | VD(srcdst) | VM(freg));+ }++ FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN(freg) | RD(TMP_REG1)));+ return push_inst(compiler, VMOV | VN(srcdst) | RD(TMP_REG1));+ }++ FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(srcdst) | RD(TMP_REG1)));+ return push_inst(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN(freg) | RD(TMP_REG1));+ }++ if (srcdst == SLJIT_IMM) {+ if (elem_size < 2)+ srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcdstw));+ srcdst = TMP_REG1;+ }++ if (elem_size == 0)+ ins = 0x400000;+ else if (elem_size == 1)+ ins = 0x20;+ else+ ins = 0;++ lane_index = lane_index << elem_size;+ ins |= (sljit_ins)(((lane_index & 0x4) << 19) | ((lane_index & 0x3) << 5));++ if (type & SLJIT_SIMD_STORE) {+ ins |= (1 << 20);++ if (elem_size < 2 && !(type & SLJIT_SIMD_LANE_SIGNED))+ ins |= (1 << 23);+ }++ return push_inst(compiler, VMOV_s | ins | VN(freg) | RD(srcdst));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_s32 src_lane_index)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index));++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4) {+ freg = simd_get_quad_reg_index(freg);+ src = simd_get_quad_reg_index(src);++ if (src_lane_index >= (0x8 >> elem_size)) {+ src_lane_index -= (0x8 >> elem_size);+ src += SLJIT_QUAD_OTHER_HALF(src);+ }+ }++ if (elem_size == 3) {+ if (freg != src)+ FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src)));++ freg += SLJIT_QUAD_OTHER_HALF(freg);++ if (freg != src)+ return push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src));+ return SLJIT_SUCCESS;+ }++ ins = ((((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size));++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 6;++ return push_inst(compiler, VDUP_s | ins | VD(freg) | VM(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);+ sljit_s32 dst_reg;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4)+ freg = simd_get_quad_reg_index(freg);++ if (src & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));+ if (reg_size == 4 && elem2_size - elem_size == 1)+ FAIL_IF(push_inst(compiler, VLD1 | (0x7 << 8) | VD(freg) | RN(src) | 0xf));+ else+ FAIL_IF(push_inst(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD(freg) | RN(src) | 0xf));+ src = freg;+ } else if (reg_size == 4)+ src = simd_get_quad_reg_index(src);++ if (!(type & SLJIT_SIMD_FLOAT)) {+ dst_reg = (reg_size == 4) ? freg : TMP_FREG2;++ do {+ FAIL_IF(push_inst(compiler, VSHLL | ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0 : (1 << 24))+ | ((sljit_ins)1 << (19 + elem_size)) | VD(dst_reg) | VM(src)));+ src = dst_reg;+ } while (++elem_size < elem2_size);++ if (dst_reg == TMP_FREG2)+ return push_inst(compiler, VORR | VD(freg) | VN(TMP_FREG2) | VM(TMP_FREG2));+ return SLJIT_SUCCESS;+ }++ /* No SIMD variant, must use VFP instead. */+ SLJIT_ASSERT(reg_size == 4);++ if (freg == src) {+ freg += SLJIT_QUAD_OTHER_HALF(freg);+ FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src) | 0x20));+ freg += SLJIT_QUAD_OTHER_HALF(freg);+ return push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src));+ }++ FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src)));+ freg += SLJIT_QUAD_OTHER_HALF(freg);+ return push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src) | 0x20);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins, imms;+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw));++ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ switch (elem_size) {+ case 0:+ imms = 0x243219;+ ins = VSHR | (1 << 24) | (0x9 << 16);+ break;+ case 1:+ imms = (reg_size == 4) ? 0x243219 : 0x2231;+ ins = VSHR | (1 << 24) | (0x11 << 16);+ break;+ case 2:+ imms = (reg_size == 4) ? 0x2231 : 0x21;+ ins = VSHR | (1 << 24) | (0x21 << 16);+ break;+ default:+ imms = 0x21;+ ins = VSHR | (1 << 24) | (0x1 << 16) | (1 << 7);+ break;+ }++ if (reg_size == 4) {+ freg = simd_get_quad_reg_index(freg);+ ins |= (sljit_ins)1 << 6;+ }++ SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0);+ FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG2) | VM(freg)));++ if (reg_size == 4 && elem_size > 0)+ FAIL_IF(push_inst(compiler, VMOVN | ((sljit_ins)(elem_size - 1) << 18) | VD(TMP_FREG2) | VM(TMP_FREG2)));++ ins = (reg_size == 4 && elem_size == 0) ? (1 << 6) : 0;++ while (imms >= 0x100) {+ FAIL_IF(push_inst(compiler, VSRA | (1 << 24) | ins | ((imms & 0xff) << 16) | VD(TMP_FREG2) | VM(TMP_FREG2)));+ imms >>= 8;+ }++ FAIL_IF(push_inst(compiler, VSRA | (1 << 24) | ins | (1 << 7) | (imms << 16) | VD(TMP_FREG2) | VM(TMP_FREG2)));++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RD(dst_r) | VN(TMP_FREG2)));++ if (reg_size == 4 && elem_size == 0) {+ SLJIT_ASSERT(freg_map[TMP_FREG2] + 1 == freg_map[TMP_FREG1]);+ FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RD(TMP_REG2) | VN(TMP_FREG1)));+ FAIL_IF(push_inst(compiler, ORR | RD(dst_r) | RN(dst_r) | RM(TMP_REG2) | (0x8 << 7)));+ }++ if (dst_r == TMP_REG1)+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg));++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ switch (SLJIT_SIMD_GET_OPCODE(type)) {+ case SLJIT_SIMD_OP2_AND:+ ins = VAND;+ break;+ case SLJIT_SIMD_OP2_OR:+ ins = VORR;+ break;+ case SLJIT_SIMD_OP2_XOR:+ ins = VEOR;+ break;+ }++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4) {+ dst_freg = simd_get_quad_reg_index(dst_freg);+ src1_freg = simd_get_quad_reg_index(src1_freg);+ src2_freg = simd_get_quad_reg_index(src2_freg);+ ins |= (sljit_ins)1 << 6;+ }++ return push_inst(compiler, ins | VD(dst_freg) | VN(src1_freg) | VM(src2_freg));+}++#undef FPU_LOAD++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 mem_reg)+{+ sljit_u32 ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ ins = LDREXB;+ break;+ case SLJIT_MOV_U16:+ ins = LDREXH;+ break;+ default:+ ins = LDREX;+ break;+ }++ return push_inst(compiler, ins | RN(mem_reg) | RD(dst_reg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src_reg,+ sljit_s32 mem_reg,+ sljit_s32 temp_reg)+{+ sljit_u32 ins;++ /* temp_reg == mem_reg is undefined so use another temp register */+ SLJIT_UNUSED_ARG(temp_reg);++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ ins = STREXB;+ break;+ case SLJIT_MOV_U16:+ ins = STREXH;+ break;+ default:+ ins = STREX;+ break;+ }++ FAIL_IF(push_inst(compiler, ins | RN(mem_reg) | RD(TMP_REG1) | RM(src_reg)));+ if (op & SLJIT_SET_ATOMIC_STORED)+ return push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(TMP_REG1));++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler,+ EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_ins)init_value));+ compiler->patches++;+#else /* !SLJIT_CONFIG_ARM_V6 */+ PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));+#endif /* SLJIT_CONFIG_ARM_V6 */++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));+ compiler->patches++;+#else /* !SLJIT_CONFIG_ARM_V6 */+ PTR_FAIL_IF(push_inst(compiler, RD(dst_r)));+#endif /* SLJIT_CONFIG_ARM_V6 */++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 1);++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ compiler->size += 1;+#endif /* SLJIT_CONFIG_ARM_V7 */++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ 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_sw executable_offset)+{+ set_const_value(addr, executable_offset, (sljit_uw)new_constant, 1); }
src/c/pcre2/src/sljit/sljitNativeARM_64.c view
@@ -67,2097 +67,3402 @@ /* Instrucion forms */ /* --------------------------------------------------------------------- */ -#define ADC 0x9a000000-#define ADD 0x8b000000-#define ADDE 0x8b200000-#define ADDI 0x91000000-#define AND 0x8a000000-#define ANDI 0x92000000-#define ASRV 0x9ac02800-#define B 0x14000000-#define B_CC 0x54000000-#define BL 0x94000000-#define BLR 0xd63f0000-#define BR 0xd61f0000-#define BRK 0xd4200000-#define CBZ 0xb4000000-#define CLZ 0xdac01000-#define CSEL 0x9a800000-#define CSINC 0x9a800400-#define EOR 0xca000000-#define EORI 0xd2000000-#define FABS 0x1e60c000-#define FADD 0x1e602800-#define FCMP 0x1e602000-#define FCVT 0x1e224000-#define FCVTZS 0x9e780000-#define FDIV 0x1e601800-#define FMOV 0x1e604000-#define FMUL 0x1e600800-#define FNEG 0x1e614000-#define FSUB 0x1e603800-#define LDRI 0xf9400000-#define LDRI_F64 0xfd400000-#define LDP 0xa9400000-#define LDP_F64 0x6d400000-#define LDP_POST 0xa8c00000-#define LDR_PRE 0xf8400c00-#define LSLV 0x9ac02000-#define LSRV 0x9ac02400-#define MADD 0x9b000000-#define MOVK 0xf2800000-#define MOVN 0x92800000-#define MOVZ 0xd2800000-#define NOP 0xd503201f-#define ORN 0xaa200000-#define ORR 0xaa000000-#define ORRI 0xb2000000-#define RET 0xd65f0000-#define SBC 0xda000000-#define SBFM 0x93000000-#define SCVTF 0x9e620000-#define SDIV 0x9ac00c00-#define SMADDL 0x9b200000-#define SMULH 0x9b403c00-#define STP 0xa9000000-#define STP_F64 0x6d000000-#define STP_PRE 0xa9800000-#define STRB 0x38206800-#define STRBI 0x39000000-#define STRI 0xf9000000-#define STRI_F64 0xfd000000-#define STR_FI 0x3d000000-#define STR_FR 0x3c206800-#define STUR_FI 0x3c000000-#define STURBI 0x38000000-#define SUB 0xcb000000-#define SUBI 0xd1000000-#define SUBS 0xeb000000-#define UBFM 0xd3000000-#define UDIV 0x9ac00800-#define UMULH 0x9bc03c00--/* dest_reg is the absolute name of the register- Useful for reordering instructions in the delay slot. */-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);- *ptr = ins;- compiler->size++;- return SLJIT_SUCCESS;-}--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) | ((sljit_ins)(imm & 0xffff) << 5)));- FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)(imm >> 16) & 0xffff) << 5) | (1 << 21)));- FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)(imm >> 32) & 0xffff) << 5) | (2 << 21)));- return push_inst(compiler, MOVK | RD(dst) | ((sljit_ins)(imm >> 48) << 5) | (3 << 21));-}--static SLJIT_INLINE sljit_sw detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)-{- sljit_sw diff;- sljit_uw target_addr;-- if (jump->flags & SLJIT_REWRITABLE_JUMP) {- jump->flags |= PATCH_ABS64;- return 0;- }-- if (jump->flags & JUMP_ADDR)- target_addr = jump->u.target;- else {- SLJIT_ASSERT(jump->flags & JUMP_LABEL);- target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;- }-- diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4) - executable_offset;-- if (jump->flags & IS_COND) {- diff += SSIZE_OF(ins);- if (diff <= 0xfffff && diff >= -0x100000) {- code_ptr[-5] ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1;- jump->addr -= sizeof(sljit_ins);- jump->flags |= PATCH_COND;- return 5;- }- diff -= SSIZE_OF(ins);- }-- if (diff <= 0x7ffffff && diff >= -0x8000000) {- jump->flags |= PATCH_B;- return 4;- }-- if (target_addr < 0x100000000l) {- if (jump->flags & IS_COND)- code_ptr[-5] -= (2 << 5);- code_ptr[-2] = code_ptr[0];- return 2;- }-- if (target_addr < 0x1000000000000l) {- if (jump->flags & IS_COND)- code_ptr[-5] -= (1 << 5);- jump->flags |= PATCH_ABS48;- code_ptr[-1] = code_ptr[0];- return 1;- }-- jump->flags |= PATCH_ABS64;- return 0;-}--static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)-{- if (max_label < 0x100000000l) {- put_label->flags = 0;- return 2;- }-- if (max_label < 0x1000000000000l) {- put_label->flags = 1;- return 1;- }-- put_label->flags = 2;- return 0;-}--SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)-{- struct sljit_memory_fragment *buf;- sljit_ins *code;- sljit_ins *code_ptr;- sljit_ins *buf_ptr;- sljit_ins *buf_end;- sljit_uw word_count;- sljit_uw next_addr;- sljit_sw executable_offset;- sljit_sw addr;- sljit_u32 dst;-- struct sljit_label *label;- struct sljit_jump *jump;- struct sljit_const *const_;- struct sljit_put_label *put_label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_generate_code(compiler));- reverse_buf(compiler);-- code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);- PTR_FAIL_WITH_EXEC_IF(code);- buf = compiler->buf;-- code_ptr = code;- word_count = 0;- next_addr = 0;- executable_offset = SLJIT_EXEC_OFFSET(code);-- label = compiler->labels;- jump = compiler->jumps;- const_ = compiler->consts;- put_label = compiler->put_labels;-- do {- buf_ptr = (sljit_ins*)buf->memory;- buf_end = buf_ptr + (buf->used_size >> 2);- do {- *code_ptr = *buf_ptr++;- if (next_addr == word_count) {- SLJIT_ASSERT(!label || label->size >= word_count);- SLJIT_ASSERT(!jump || jump->addr >= word_count);- SLJIT_ASSERT(!const_ || const_->addr >= word_count);- SLJIT_ASSERT(!put_label || put_label->addr >= word_count);-- /* These structures are ordered by their address. */- if (label && label->size == word_count) {- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }- if (jump && jump->addr == word_count) {- jump->addr = (sljit_uw)(code_ptr - 4);- code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);- jump = jump->next;- }- if (const_ && const_->addr == word_count) {- const_->addr = (sljit_uw)code_ptr;- const_ = const_->next;- }- if (put_label && put_label->addr == word_count) {- SLJIT_ASSERT(put_label->label);- put_label->addr = (sljit_uw)(code_ptr - 3);- code_ptr -= put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));- put_label = put_label->next;- }- next_addr = compute_next_addr(label, jump, const_, put_label);- }- code_ptr ++;- word_count ++;- } while (buf_ptr < buf_end);-- buf = buf->next;- } while (buf);-- if (label && label->size == word_count) {- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }-- SLJIT_ASSERT(!label);- SLJIT_ASSERT(!jump);- SLJIT_ASSERT(!const_);- SLJIT_ASSERT(!put_label);- SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);-- jump = compiler->jumps;- while (jump) {- do {- addr = (sljit_sw)((jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);- buf_ptr = (sljit_ins *)jump->addr;-- if (jump->flags & PATCH_B) {- addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;- SLJIT_ASSERT(addr <= 0x1ffffff && addr >= -0x2000000);- buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (sljit_ins)(addr & 0x3ffffff);- if (jump->flags & IS_COND)- buf_ptr[-1] -= (4 << 5);- break;- }- if (jump->flags & PATCH_COND) {- addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;- SLJIT_ASSERT(addr <= 0x3ffff && addr >= -0x40000);- buf_ptr[0] = (buf_ptr[0] & ~(sljit_ins)0xffffe0) | (sljit_ins)((addr & 0x7ffff) << 5);- break;- }-- SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || (sljit_uw)addr <= (sljit_uw)0xffffffff);- SLJIT_ASSERT((jump->flags & PATCH_ABS64) || (sljit_uw)addr <= (sljit_uw)0xffffffffffff);-- dst = buf_ptr[0] & 0x1f;- buf_ptr[0] = MOVZ | dst | (((sljit_ins)addr & 0xffff) << 5);- buf_ptr[1] = MOVK | dst | (((sljit_ins)(addr >> 16) & 0xffff) << 5) | (1 << 21);- if (jump->flags & (PATCH_ABS48 | PATCH_ABS64))- buf_ptr[2] = MOVK | dst | (((sljit_ins)(addr >> 32) & 0xffff) << 5) | (2 << 21);- if (jump->flags & PATCH_ABS64)- buf_ptr[3] = MOVK | dst | ((sljit_ins)(addr >> 48) << 5) | (3 << 21);- } while (0);- jump = jump->next;- }-- put_label = compiler->put_labels;- while (put_label) {- addr = (sljit_sw)put_label->label->addr;- buf_ptr = (sljit_ins*)put_label->addr;-- buf_ptr[0] |= ((sljit_ins)addr & 0xffff) << 5;- buf_ptr[1] |= ((sljit_ins)(addr >> 16) & 0xffff) << 5;-- if (put_label->flags >= 1)- buf_ptr[2] |= ((sljit_ins)(addr >> 32) & 0xffff) << 5;-- if (put_label->flags >= 2)- buf_ptr[3] |= (sljit_ins)(addr >> 48) << 5;-- put_label = put_label->next;- }-- compiler->error = SLJIT_ERR_COMPILED;- compiler->executable_offset = executable_offset;- compiler->executable_size = (sljit_uw)(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);- SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);- 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_CLZ:- case SLJIT_HAS_CMOV:- case SLJIT_HAS_PREFETCH:- return 1;-- default:- return 0;- }-}--/* --------------------------------------------------------------------- */-/* Core code generator functions. */-/* --------------------------------------------------------------------- */--#define COUNT_TRAILING_ZERO(value, result) \- result = 0; \- if (!(value & 0xffffffff)) { \- result += 32; \- value >>= 32; \- } \- if (!(value & 0xffff)) { \- result += 16; \- value >>= 16; \- } \- if (!(value & 0xff)) { \- result += 8; \- value >>= 8; \- } \- if (!(value & 0xf)) { \- result += 4; \- value >>= 4; \- } \- if (!(value & 0x3)) { \- result += 2; \- value >>= 2; \- } \- if (!(value & 0x1)) { \- result += 1; \- value >>= 1; \- }--#define LOGICAL_IMM_CHECK (sljit_ins)0x100--static sljit_ins logical_imm(sljit_sw imm, sljit_u32 len)-{- sljit_s32 negated;- sljit_u32 ones, right;- sljit_uw mask, uimm;- sljit_ins ins;-- if (len & LOGICAL_IMM_CHECK) {- len &= ~LOGICAL_IMM_CHECK;- if (len == 32 && (imm == 0 || imm == -1))- return 0;- if (len == 16 && ((sljit_s32)imm == 0 || (sljit_s32)imm == -1))- return 0;- }-- SLJIT_ASSERT((len == 32 && imm != 0 && imm != -1)- || (len == 16 && (sljit_s32)imm != 0 && (sljit_s32)imm != -1));-- uimm = (sljit_uw)imm;- while (1) {- if (len <= 0) {- SLJIT_UNREACHABLE();- return 0;- }-- mask = ((sljit_uw)1 << len) - 1;- if ((uimm & mask) != ((uimm >> len) & mask))- break;- len >>= 1;- }-- len <<= 1;-- negated = 0;- if (uimm & 0x1) {- negated = 1;- uimm = ~uimm;- }-- if (len < 64)- uimm &= ((sljit_uw)1 << len) - 1;-- /* Unsigned right shift. */- COUNT_TRAILING_ZERO(uimm, right);-- /* Signed shift. We also know that the highest bit is set. */- imm = (sljit_sw)~uimm;- SLJIT_ASSERT(imm < 0);-- COUNT_TRAILING_ZERO(imm, ones);-- if (~imm)- return 0;-- if (len == 64)- ins = 1 << 22;- else- ins = (0x3f - ((len << 1) - 1)) << 10;-- if (negated)- return ins | ((len - ones - 1) << 10) | ((len - ones - right) << 16);-- return ins | ((ones - 1) << 10) | ((len - right) << 16);-}--#undef COUNT_TRAILING_ZERO--static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw simm)-{- sljit_uw imm = (sljit_uw)simm;- sljit_u32 i, zeros, ones, first;- sljit_ins bitmask;-- /* Handling simple immediates first. */- if (imm <= 0xffff)- return push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)imm << 5));-- if (simm < 0 && simm >= -0x10000)- return push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5));-- if (imm <= 0xffffffffl) {- if ((imm & 0xffff) == 0)- return push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)(imm >> 16) << 5) | (1 << 21));- if ((imm & 0xffff0000l) == 0xffff0000)- return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5));- if ((imm & 0xffff) == 0xffff)- return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | (((sljit_ins)~imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));-- bitmask = logical_imm(simm, 16);- if (bitmask != 0)- return push_inst(compiler, (ORRI ^ W_OP) | RD(dst) | RN(TMP_ZERO) | bitmask);-- FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | (((sljit_ins)imm & 0xffff) << 5)));- return push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));- }-- bitmask = logical_imm(simm, 32);- if (bitmask != 0)- return push_inst(compiler, ORRI | RD(dst) | RN(TMP_ZERO) | bitmask);-- if (simm < 0 && simm >= -0x100000000l) {- if ((imm & 0xffff) == 0xffff)- return push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));-- FAIL_IF(push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5)));- return push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));- }-- /* A large amount of number can be constructed from ORR and MOVx, but computing them is costly. */-- zeros = 0;- ones = 0;- for (i = 4; i > 0; i--) {- if ((simm & 0xffff) == 0)- zeros++;- if ((simm & 0xffff) == 0xffff)- ones++;- simm >>= 16;- }-- simm = (sljit_sw)imm;- first = 1;- if (ones > zeros) {- simm = ~simm;- for (i = 0; i < 4; i++) {- if (!(simm & 0xffff)) {- simm >>= 16;- continue;- }- if (first) {- first = 0;- FAIL_IF(push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));- }- else- FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)~simm & 0xffff) << 5) | (i << 21)));- simm >>= 16;- }- return SLJIT_SUCCESS;- }-- for (i = 0; i < 4; i++) {- if (!(simm & 0xffff)) {- simm >>= 16;- continue;- }- if (first) {- first = 0;- FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));- }- else- FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));- simm >>= 16;- }- return SLJIT_SUCCESS;-}--#define ARG1_IMM 0x0010000-#define ARG2_IMM 0x0020000-#define INT_OP 0x0040000-#define SET_FLAGS 0x0080000-#define UNUSED_RETURN 0x0100000--#define CHECK_FLAGS(flag_bits) \- if (flags & SET_FLAGS) { \- inv_bits |= flag_bits; \- if (flags & UNUSED_RETURN) \- dst = TMP_ZERO; \- }--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) ? W_OP : 0;- sljit_ins inst_bits;- sljit_s32 op = (flags & 0xffff);- sljit_s32 reg;- sljit_sw imm, nimm;-- if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {- /* Both are immediates. */- flags &= ~ARG1_IMM;- if (arg1 == 0 && op != SLJIT_ADD && op != SLJIT_SUB)- arg1 = TMP_ZERO;- else {- FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));- arg1 = TMP_REG1;- }- }-- if (flags & (ARG1_IMM | ARG2_IMM)) {- reg = (sljit_s32)((flags & ARG2_IMM) ? arg1 : arg2);- imm = (flags & ARG2_IMM) ? arg2 : arg1;-- switch (op) {- case SLJIT_MUL:- case SLJIT_CLZ:- case SLJIT_ADDC:- case SLJIT_SUBC:- /* No form with immediate operand (except imm 0, which- is represented by a ZERO register). */- break;- case SLJIT_MOV:- SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);- return load_immediate(compiler, dst, imm);- case SLJIT_NOT:- SLJIT_ASSERT(flags & ARG2_IMM);- FAIL_IF(load_immediate(compiler, dst, (flags & INT_OP) ? (~imm & 0xffffffff) : ~imm));- goto set_flags;- case SLJIT_SUB:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- if (flags & ARG1_IMM)- break;- imm = -imm;- /* Fall through. */- case SLJIT_ADD:- if (op != SLJIT_SUB)- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;-- if (imm == 0) {- CHECK_FLAGS(1 << 29);- return push_inst(compiler, ((op == SLJIT_ADD ? ADDI : SUBI) ^ inv_bits) | RD(dst) | RN(reg));- }- if (imm > 0 && imm <= 0xfff) {- CHECK_FLAGS(1 << 29);- return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((sljit_ins)imm << 10));- }- nimm = -imm;- if (nimm > 0 && nimm <= 0xfff) {- CHECK_FLAGS(1 << 29);- return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((sljit_ins)nimm << 10));- }- if (imm > 0 && imm <= 0xffffff && !(imm & 0xfff)) {- CHECK_FLAGS(1 << 29);- return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)imm >> 12) << 10) | (1 << 22));- }- if (nimm > 0 && nimm <= 0xffffff && !(nimm & 0xfff)) {- CHECK_FLAGS(1 << 29);- return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)nimm >> 12) << 10) | (1 << 22));- }- if (imm > 0 && imm <= 0xffffff && !(flags & SET_FLAGS)) {- FAIL_IF(push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)imm >> 12) << 10) | (1 << 22)));- return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(dst) | (((sljit_ins)imm & 0xfff) << 10));- }- if (nimm > 0 && nimm <= 0xffffff && !(flags & SET_FLAGS)) {- FAIL_IF(push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)nimm >> 12) << 10) | (1 << 22)));- return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(dst) | (((sljit_ins)nimm & 0xfff) << 10));- }- break;- case SLJIT_AND:- inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));- if (!inst_bits)- break;- CHECK_FLAGS(3 << 29);- return push_inst(compiler, (ANDI ^ inv_bits) | RD(dst) | RN(reg) | inst_bits);- case SLJIT_OR:- case SLJIT_XOR:- inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));- if (!inst_bits)- break;- if (op == SLJIT_OR)- inst_bits |= ORRI;- else- inst_bits |= EORI;- FAIL_IF(push_inst(compiler, (inst_bits ^ inv_bits) | RD(dst) | RN(reg)));- goto set_flags;- case SLJIT_SHL:- if (flags & ARG1_IMM)- break;- if (flags & INT_OP) {- imm &= 0x1f;- FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1)- | (((sljit_ins)-imm & 0x1f) << 16) | ((31 - (sljit_ins)imm) << 10)));- }- else {- imm &= 0x3f;- FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22)- | (((sljit_ins)-imm & 0x3f) << 16) | ((63 - (sljit_ins)imm) << 10)));- }- goto set_flags;- case SLJIT_LSHR:- case SLJIT_ASHR:- if (flags & ARG1_IMM)- break;- if (op == SLJIT_ASHR)- inv_bits |= 1 << 30;- if (flags & INT_OP) {- imm &= 0x1f;- FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1)- | ((sljit_ins)imm << 16) | (31 << 10)));- }- else {- imm &= 0x3f;- FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1)- | (1 << 22) | ((sljit_ins)imm << 16) | (63 << 10)));- }- goto set_flags;- default:- SLJIT_UNREACHABLE();- break;- }-- if (flags & ARG2_IMM) {- if (arg2 == 0)- arg2 = TMP_ZERO;- else {- FAIL_IF(load_immediate(compiler, TMP_REG2, arg2));- arg2 = TMP_REG2;- }- }- else {- if (arg1 == 0)- arg1 = TMP_ZERO;- else {- FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));- arg1 = TMP_REG1;- }- }- }-- /* Both arguments are registers. */- switch (op) {- case SLJIT_MOV:- case SLJIT_MOV_P:- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);- if (dst == arg2)- return SLJIT_SUCCESS;- return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(arg2));- case SLJIT_MOV_U8:- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);- return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (7 << 10));- case SLJIT_MOV_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_U16:- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);- return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (15 << 10));- case SLJIT_MOV_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_MOV32:- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);- if (dst == arg2)- return SLJIT_SUCCESS;- /* fallthrough */- case SLJIT_MOV_U32:- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);- return push_inst(compiler, (ORR ^ W_OP) | RD(dst) | RN(TMP_ZERO) | RM(arg2));- case SLJIT_MOV_S32:- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);- return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10));- case SLJIT_NOT:- SLJIT_ASSERT(arg1 == TMP_REG1);- FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)));- break; /* Set flags. */- case SLJIT_CLZ:- SLJIT_ASSERT(arg1 == TMP_REG1);- return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2));- case SLJIT_ADD:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- CHECK_FLAGS(1 << 29);- return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));- case SLJIT_ADDC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- CHECK_FLAGS(1 << 29);- return push_inst(compiler, (ADC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));- case SLJIT_SUB:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- CHECK_FLAGS(1 << 29);- return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));- case SLJIT_SUBC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- CHECK_FLAGS(1 << 29);- return push_inst(compiler, (SBC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));- case SLJIT_MUL:- compiler->status_flags_state = 0;- if (!(flags & SET_FLAGS))- return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO));- if (flags & INT_OP) {- FAIL_IF(push_inst(compiler, SMADDL | RD(dst) | RN(arg1) | RM(arg2) | (31 << 10)));- FAIL_IF(push_inst(compiler, ADD | RD(TMP_LR) | RN(TMP_ZERO) | RM(dst) | (2 << 22) | (31 << 10)));- return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10));- }- FAIL_IF(push_inst(compiler, SMULH | RD(TMP_LR) | RN(arg1) | RM(arg2)));- FAIL_IF(push_inst(compiler, MADD | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO)));- return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10));- case SLJIT_AND:- CHECK_FLAGS(3 << 29);- 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)));- break; /* Set flags. */- case SLJIT_XOR:- FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));- break; /* Set flags. */- case SLJIT_SHL:- FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));- break; /* Set flags. */- case SLJIT_LSHR:- FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));- break; /* Set flags. */- case SLJIT_ASHR:- FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));- break; /* Set flags. */- default:- SLJIT_UNREACHABLE();- return SLJIT_SUCCESS;- }--set_flags:- if (flags & SET_FLAGS)- return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO));- return SLJIT_SUCCESS;-}--#define STORE 0x10-#define SIGNED 0x20--#define BYTE_SIZE 0x0-#define HALF_SIZE 0x1-#define INT_SIZE 0x2-#define WORD_SIZE 0x3--#define MEM_SIZE_SHIFT(flags) ((sljit_ins)(flags) & 0x3)--static 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_u32 shift = MEM_SIZE_SHIFT(flags);- sljit_u32 type = (shift << 30);-- if (!(flags & STORE))- type |= (flags & SIGNED) ? 0x00800000 : 0x00400000;-- SLJIT_ASSERT(arg & SLJIT_MEM);-- if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {- argw &= 0x3;-- if (argw == 0 || argw == shift)- return push_inst(compiler, STRB | type | RT(reg)- | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));-- FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)argw << 10)));- return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg));- }-- arg &= REG_MASK;-- if (!arg) {- FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~(0xfff << shift)));-- argw = (argw >> shift) & 0xfff;-- return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));- }-- if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) {- if ((argw >> shift) <= 0xfff)- return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift)));-- if (argw <= 0xffffff) {- FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));-- argw = ((argw & 0xfff) >> shift);- return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));- }- }-- if (argw <= 255 && argw >= -256)- return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12));-- FAIL_IF(load_immediate(compiler, tmp_reg, argw));-- return push_inst(compiler, STRB | type | RT(reg) | RN(arg) | RM(tmp_reg));-}--/* --------------------------------------------------------------------- */-/* Entry, exit */-/* --------------------------------------------------------------------- */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 prev, fprev, saved_regs_size, i, tmp;- sljit_s32 word_arg_count = 0;- sljit_ins offs;-- CHECK_ERROR();- CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);- saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, SSIZE_OF(f64));-- local_size = (local_size + saved_regs_size + 0xf) & ~0xf;- compiler->local_size = local_size;-- if (local_size <= 512) {- FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)- | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));- offs = (sljit_ins)(local_size - 2 * SSIZE_OF(sw)) << (15 - 3);- local_size = 0;- } else {- saved_regs_size = ((saved_regs_size - 2 * SSIZE_OF(sw)) + 0xf) & ~0xf;-- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)saved_regs_size << 10)));- offs = (sljit_ins)(saved_regs_size - 2 * SSIZE_OF(sw)) << (15 - 3);- local_size -= saved_regs_size;- SLJIT_ASSERT(local_size > 0);- }-- prev = -1;-- tmp = SLJIT_S0 - saveds;- for (i = SLJIT_S0; i > tmp; i--) {- if (prev == -1) {- prev = i;- continue;- }- FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));- offs -= (sljit_ins)2 << 15;- prev = -1;- }-- for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {- if (prev == -1) {- prev = i;- continue;- }- FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));- offs -= (sljit_ins)2 << 15;- prev = -1;- }-- fprev = -1;-- tmp = SLJIT_FS0 - fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- if (fprev == -1) {- fprev = i;- continue;- }- FAIL_IF(push_inst(compiler, STP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));- offs -= (sljit_ins)2 << 15;- fprev = -1;- }-- for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- if (fprev == -1) {- fprev = i;- continue;- }- FAIL_IF(push_inst(compiler, STP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));- offs -= (sljit_ins)2 << 15;- fprev = -1;- }-- if (fprev != -1)- FAIL_IF(push_inst(compiler, STRI_F64 | VT(fprev) | RN(SLJIT_SP) | (offs >> 5) | (1 << 10)));-- if (prev != -1)- FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));-- arg_types >>= SLJIT_ARG_SHIFT;--#ifdef _WIN32- if (local_size > 4096)- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));-#endif /* _WIN32 */-- tmp = 0;- while (arg_types > 0) {- if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - tmp) | RN(TMP_ZERO) | RM(SLJIT_R0 + word_arg_count)));- tmp++;- }- word_arg_count++;- }- arg_types >>= SLJIT_ARG_SHIFT;- }--#ifdef _WIN32- if (local_size > 4096) {- if (local_size < 4 * 4096) {- /* No need for a loop. */-- if (local_size >= 2 * 4096) {- if (local_size >= 3 * 4096) {- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));- }-- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));- }- }- else {- FAIL_IF(push_inst(compiler, MOVZ | RD(TMP_REG1) | ((((sljit_ins)local_size >> 12) - 1) << 5)));- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));- FAIL_IF(push_inst(compiler, SUBI | (1 << 29) | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10)));- FAIL_IF(push_inst(compiler, B_CC | ((((sljit_ins) -3) & 0x7ffff) << 5) | 0x1 /* not-equal */));- }-- local_size &= 0xfff;-- if (local_size > 0)- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));- else- FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));- }-- if (local_size > 0) {- if (local_size <= 512)- FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)- | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));- else {- if (local_size >= 4096)- local_size = (1 << (22 - 10));-- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));- FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));- }- }--#else /* !_WIN32 */-- /* The local_size does not include saved registers size. */- if (local_size != 0) {- if (local_size > 0xfff) {- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (((sljit_ins)local_size >> 12) << 10) | (1 << 22)));- local_size &= 0xfff;- }-- if (local_size > 512 || local_size == 0) {- if (local_size != 0)- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));-- FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));- } else- FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)- | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));- }--#endif /* _WIN32 */-- return push_inst(compiler, ADDI | RD(TMP_FP) | RN(SLJIT_SP) | (0 << 10));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 saved_regs_size;-- CHECK_ERROR();- CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);- saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, SSIZE_OF(f64));-- compiler->local_size = (local_size + saved_regs_size + 0xf) & ~0xf;- return SLJIT_SUCCESS;-}--static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)-{- sljit_s32 local_size, prev, fprev, i, tmp;- sljit_ins offs;-- local_size = compiler->local_size;-- if (local_size > 512 && local_size <= 512 + 496) {- FAIL_IF(push_inst(compiler, LDP_POST | RT(TMP_FP) | RT2(TMP_LR)- | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << (15 - 3))));- local_size = 512;- } else- FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));-- if (local_size > 512) {- local_size -= 512;- if (local_size > 0xfff) {- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP)- | (((sljit_ins)local_size >> 12) << 10) | (1 << 22)));- local_size &= 0xfff;- }-- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));- local_size = 512;- }-- offs = (sljit_ins)(local_size - 2 * SSIZE_OF(sw)) << (15 - 3);- prev = -1;-- tmp = SLJIT_S0 - compiler->saveds;- for (i = SLJIT_S0; i > tmp; i--) {- if (prev == -1) {- prev = i;- continue;- }- FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));- offs -= (sljit_ins)2 << 15;- prev = -1;- }-- for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {- if (prev == -1) {- prev = i;- continue;- }- FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));- offs -= (sljit_ins)2 << 15;- prev = -1;- }-- fprev = -1;-- tmp = SLJIT_FS0 - compiler->fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- if (fprev == -1) {- fprev = i;- continue;- }- FAIL_IF(push_inst(compiler, LDP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));- offs -= (sljit_ins)2 << 15;- fprev = -1;- }-- for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- if (fprev == -1) {- fprev = i;- continue;- }- FAIL_IF(push_inst(compiler, LDP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));- offs -= (sljit_ins)2 << 15;- fprev = -1;- }-- if (fprev != -1)- FAIL_IF(push_inst(compiler, LDRI_F64 | VT(fprev) | RN(SLJIT_SP) | (offs >> 5) | (1 << 10)));-- if (prev != -1)- FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));-- /* This and the next call/jump instruction can be executed parallelly. */- return push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (sljit_ins)(local_size << 10));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)-{- CHECK_ERROR();- CHECK(check_sljit_emit_return_void(compiler));-- FAIL_IF(emit_stack_frame_release(compiler));-- return push_inst(compiler, RET | RN(TMP_LR));-}--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)-{- sljit_ins inv_bits = (op & SLJIT_32) ? W_OP : 0;-- CHECK_ERROR();- CHECK(check_sljit_emit_op0(compiler, op));-- op = GET_OPCODE(op);- switch (op) {- case SLJIT_BREAKPOINT:- return push_inst(compiler, BRK);- case SLJIT_NOP:- return push_inst(compiler, NOP);- 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_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_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_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));- case SLJIT_ENDBR:- case SLJIT_SKIP_FRAMES_BEFORE_RETURN:- return SLJIT_SUCCESS;- }-- return SLJIT_SUCCESS;-}--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_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));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src, srcw);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;-- op = GET_OPCODE(op);- if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {- /* Both operands are registers. */- if (dst_r != TMP_REG1 && FAST_IS_REG(src))- return emit_op_imm(compiler, op | ((op_flags & SLJIT_32) ? INT_OP : 0), dst_r, TMP_REG1, src);-- switch (op) {- case SLJIT_MOV:- case SLJIT_MOV_P:- mem_flags = WORD_SIZE;- break;- case SLJIT_MOV_U8:- mem_flags = BYTE_SIZE;- if (src & SLJIT_IMM)- srcw = (sljit_u8)srcw;- break;- case SLJIT_MOV_S8:- mem_flags = BYTE_SIZE | SIGNED;- if (src & SLJIT_IMM)- srcw = (sljit_s8)srcw;- break;- case SLJIT_MOV_U16:- mem_flags = HALF_SIZE;- if (src & SLJIT_IMM)- srcw = (sljit_u16)srcw;- break;- case SLJIT_MOV_S16:- mem_flags = HALF_SIZE | SIGNED;- if (src & SLJIT_IMM)- srcw = (sljit_s16)srcw;- break;- case SLJIT_MOV_U32:- mem_flags = INT_SIZE;- if (src & SLJIT_IMM)- srcw = (sljit_u32)srcw;- break;- case SLJIT_MOV_S32:- case SLJIT_MOV32:- mem_flags = INT_SIZE | SIGNED;- if (src & SLJIT_IMM)- srcw = (sljit_s32)srcw;- break;- default:- SLJIT_UNREACHABLE();- mem_flags = 0;- break;- }-- if (src & SLJIT_IMM)- FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw));- else if (!(src & SLJIT_MEM))- dst_r = src;- else- FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, src, srcw, TMP_REG1));-- if (dst & SLJIT_MEM)- return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);- return SLJIT_SUCCESS;- }-- flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;- mem_flags = WORD_SIZE;-- if (op_flags & SLJIT_32) {- flags |= INT_OP;- mem_flags = INT_SIZE;- }-- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src, srcw, TMP_REG2));- src = TMP_REG2;- }-- emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, src);-- if (SLJIT_UNLIKELY(dst & SLJIT_MEM))- return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);- return SLJIT_SUCCESS;-}--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_s32 dst_r, flags, mem_flags;-- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;- flags = HAS_FLAGS(op) ? SET_FLAGS : 0;- mem_flags = WORD_SIZE;-- if (op & SLJIT_32) {- flags |= INT_OP;- mem_flags = INT_SIZE;- }-- if (dst == TMP_REG1)- flags |= UNUSED_RETURN;-- if (src1 & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, src1, src1w, TMP_REG1));- src1 = TMP_REG1;- }-- if (src2 & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src2, src2w, TMP_REG2));- src2 = TMP_REG2;- }-- if (src1 & SLJIT_IMM)- flags |= ARG1_IMM;- else- src1w = src1;-- if (src2 & SLJIT_IMM)- flags |= ARG2_IMM;- else- src2w = src2;-- emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);-- if (dst & SLJIT_MEM)- return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 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_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- switch (op) {- case SLJIT_FAST_RETURN:- if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src)));- else- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1));-- return push_inst(compiler, RET | RN(TMP_LR));- case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:- return SLJIT_SUCCESS;- case SLJIT_PREFETCH_L1:- case SLJIT_PREFETCH_L2:- case SLJIT_PREFETCH_L3:- case SLJIT_PREFETCH_ONCE:- SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4);-- /* The reg_map[op] should provide the appropriate constant. */- if (op == SLJIT_PREFETCH_L1)- op = 1;- else if (op == SLJIT_PREFETCH_L2)- op = 3;- else if (op == SLJIT_PREFETCH_L3)- op = 5;- else- op = 2;-- /* Signed word sized load is the prefetch instruction. */- return emit_op_mem(compiler, WORD_SIZE | SIGNED, op, src, srcw, TMP_REG1);- }-- return SLJIT_SUCCESS;-}--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_s32 sljit_get_float_register_index(sljit_s32 reg)-{- CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));- return freg_map[reg];-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{- SLJIT_UNUSED_ARG(size);- CHECK_ERROR();- CHECK(check_sljit_emit_op_custom(compiler, instruction, size));-- return push_inst(compiler, *(sljit_ins*)instruction);-}--/* --------------------------------------------------------------------- */-/* Floating point operators */-/* --------------------------------------------------------------------- */--static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)-{- sljit_u32 shift = MEM_SIZE_SHIFT(flags);- sljit_ins type = (shift << 30);-- SLJIT_ASSERT(arg & SLJIT_MEM);-- if (!(flags & STORE))- type |= 0x00400000;-- if (arg & OFFS_REG_MASK) {- argw &= 3;- if (argw == 0 || argw == shift)- return push_inst(compiler, STR_FR | type | VT(reg)- | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));-- FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)argw << 10)));- return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1));- }-- arg &= REG_MASK;-- if (!arg) {- FAIL_IF(load_immediate(compiler, TMP_REG1, argw & ~(0xfff << shift)));-- argw = (argw >> shift) & 0xfff;-- return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | ((sljit_ins)argw << 10));- }-- if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) {- if ((argw >> shift) <= 0xfff)- return push_inst(compiler, STR_FI | type | VT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift)));-- if (argw <= 0xffffff) {- FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(TMP_REG1) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));-- argw = ((argw & 0xfff) >> shift);- return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | ((sljit_ins)argw << 10));- }- }-- if (argw <= 255 && argw >= -256)- return push_inst(compiler, STUR_FI | type | VT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12));-- FAIL_IF(load_immediate(compiler, TMP_REG1, argw));- return push_inst(compiler, STR_FR | type | VT(reg) | RN(arg) | RM(TMP_REG1));-}--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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;- sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;-- if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64)- inv_bits |= W_OP;-- if (src & SLJIT_MEM) {- emit_fop_mem(compiler, (op & SLJIT_32) ? 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 & SLJIT_MEM)- return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw, TMP_REG2);- return SLJIT_SUCCESS;-}--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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;- sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;-- if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)- inv_bits |= W_OP;-- if (src & SLJIT_MEM) {- emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw, TMP_REG1);- src = TMP_REG1;- } else if (src & SLJIT_IMM) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- 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;- }-- FAIL_IF(push_inst(compiler, (SCVTF ^ inv_bits) | VD(dst_r) | RN(src)));-- if (dst & SLJIT_MEM)- return emit_fop_mem(compiler, ((op & SLJIT_32) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw);- return SLJIT_SUCCESS;-}--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_s32 mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;- sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;-- if (src1 & SLJIT_MEM) {- emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w);- src1 = TMP_FREG1;- }-- if (src2 & SLJIT_MEM) {- emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w);- src2 = TMP_FREG2;- }-- return push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2));-}--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_s32 dst_r, mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;- sljit_ins inv_bits;-- CHECK_ERROR();-- SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x1) == WORD_SIZE, must_be_one_bit_difference);- SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);-- inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- if (src & SLJIT_MEM) {- emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x1) : mem_flags, dst_r, src, srcw);- src = dst_r;- }-- switch (GET_OPCODE(op)) {- 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)));- else- dst_r = src;- }- break;- case SLJIT_NEG_F64:- FAIL_IF(push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(src)));- break;- case SLJIT_ABS_F64:- FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src)));- break;- case SLJIT_CONV_F64_FROM_F32:- FAIL_IF(push_inst(compiler, FCVT | (sljit_ins)((op & SLJIT_32) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src)));- break;- }-- if (dst & SLJIT_MEM)- return emit_fop_mem(compiler, mem_flags | STORE, dst_r, dst, dstw);- return SLJIT_SUCCESS;-}--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_s32 dst_r, mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;- sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;-- CHECK_ERROR();- CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;- if (src1 & SLJIT_MEM) {- emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w);- src1 = TMP_FREG1;- }- if (src2 & SLJIT_MEM) {- emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w);- src2 = TMP_FREG2;- }-- switch (GET_OPCODE(op)) {- case SLJIT_ADD_F64:- FAIL_IF(push_inst(compiler, (FADD ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));- break;- case SLJIT_SUB_F64:- FAIL_IF(push_inst(compiler, (FSUB ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));- break;- case SLJIT_MUL_F64:- FAIL_IF(push_inst(compiler, (FMUL ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));- break;- case SLJIT_DIV_F64:- FAIL_IF(push_inst(compiler, (FDIV ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));- break;- }-- if (!(dst & SLJIT_MEM))- return SLJIT_SUCCESS;- return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw);-}--/* --------------------------------------------------------------------- */-/* Other instructions */-/* --------------------------------------------------------------------- */--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);-- if (FAST_IS_REG(dst))- return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR));-- /* Memory. */- return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw, TMP_REG1);-}--/* --------------------------------------------------------------------- */-/* Conditional instructions */-/* --------------------------------------------------------------------- */--static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)-{- switch (type) {- case SLJIT_EQUAL:- case SLJIT_EQUAL_F64:- return 0x1;-- case SLJIT_NOT_EQUAL:- case SLJIT_NOT_EQUAL_F64:- return 0x0;-- case SLJIT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)- return 0x3;- /* fallthrough */-- case SLJIT_LESS:- case SLJIT_LESS_F64:- return 0x2;-- case SLJIT_NOT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)- return 0x2;- /* fallthrough */-- case SLJIT_GREATER_EQUAL:- case SLJIT_GREATER_EQUAL_F64:- return 0x3;-- case SLJIT_GREATER:- case SLJIT_GREATER_F64:- return 0x9;-- case SLJIT_LESS_EQUAL:- case SLJIT_LESS_EQUAL_F64:- return 0x8;-- case SLJIT_SIG_LESS:- return 0xa;-- case SLJIT_SIG_GREATER_EQUAL:- return 0xb;-- case SLJIT_SIG_GREATER:- return 0xd;-- case SLJIT_SIG_LESS_EQUAL:- return 0xc;-- case SLJIT_OVERFLOW:- if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))- return 0x0;- /* fallthrough */-- case SLJIT_UNORDERED_F64:- return 0x7;-- case SLJIT_NOT_OVERFLOW:- if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))- return 0x1;- /* fallthrough */-- case SLJIT_ORDERED_F64:- return 0x6;-- default:- SLJIT_UNREACHABLE();- return 0xe;- }-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)-{- struct sljit_label *label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_label(compiler));-- if (compiler->last_label && compiler->last_label->size == compiler->size)- return compiler->last_label;-- label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));- PTR_FAIL_IF(!label);- set_label(label, compiler);- return label;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)-{- struct sljit_jump *jump;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_jump(compiler, type));-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);- type &= 0xff;-- if (type < SLJIT_JUMP) {- jump->flags |= IS_COND;- PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(compiler, type)));- }- else if (type >= SLJIT_FAST_CALL)- jump->flags |= IS_BL;-- PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));- jump->addr = compiler->size;- PTR_FAIL_IF(push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1)));-- return jump;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types)-{- SLJIT_UNUSED_ARG(arg_types);- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));-- if (type & SLJIT_CALL_RETURN) {- PTR_FAIL_IF(emit_stack_frame_release(compiler));- type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);- }--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_jump(compiler, type);-}--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_32) ? W_OP : 0;-- SLJIT_ASSERT((type & 0xff) == SLJIT_EQUAL || (type & 0xff) == SLJIT_NOT_EQUAL);- ADJUST_LOCAL_OFFSET(src, srcw);-- 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_CBZ | IS_COND;-- if (src & SLJIT_MEM) {- PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));- src = TMP_REG1;- }- else if (src & SLJIT_IMM) {- PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));- src = TMP_REG1;- }-- SLJIT_ASSERT(FAST_IS_REG(src));-- if ((type & 0xff) == SLJIT_EQUAL)- inv_bits |= 1 << 24;-- PTR_FAIL_IF(push_inst(compiler, (CBZ ^ inv_bits) | (6 << 5) | RT(src)));- PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));- jump->addr = compiler->size;- PTR_FAIL_IF(push_inst(compiler, BR | RN(TMP_REG1)));- return jump;-}--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;-- CHECK_ERROR();- CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- if (!(src & SLJIT_IMM)) {- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));- src = TMP_REG1;- }- return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(src));- }-- /* These jumps are converted to jump/call instructions when possible. */- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- FAIL_IF(!jump);- set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));- jump->u.target = (sljit_uw)srcw;-- FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));- jump->addr = compiler->size;- return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{- SLJIT_UNUSED_ARG(arg_types);- CHECK_ERROR();- CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));- src = TMP_REG1;- }-- if (type & SLJIT_CALL_RETURN) {- if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {- FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src)));- src = TMP_REG1;- }-- FAIL_IF(emit_stack_frame_release(compiler));- type = SLJIT_JUMP;- }--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_ijump(compiler, type, src, srcw);-}--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_s32 dst_r, src_r, flags, mem_flags;- sljit_ins cc;-- CHECK_ERROR();- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));- ADJUST_LOCAL_OFFSET(dst, dstw);-- cc = get_cc(compiler, type & 0xff);- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;-- if (GET_OPCODE(op) < SLJIT_ADD) {- FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(dst_r) | RN(TMP_ZERO) | RM(TMP_ZERO)));-- if (dst_r == TMP_REG1) {- mem_flags = (GET_OPCODE(op) == SLJIT_MOV ? WORD_SIZE : INT_SIZE) | STORE;- return emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG2);- }-- return SLJIT_SUCCESS;- }-- flags = HAS_FLAGS(op) ? SET_FLAGS : 0;- mem_flags = WORD_SIZE;-- if (op & SLJIT_32) {- flags |= INT_OP;- mem_flags = INT_SIZE;- }-- src_r = dst;-- if (dst & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG1));- 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_mem(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, TMP_REG2);- 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_32) ? W_OP : 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_32)- srcw = (sljit_s32)srcw;- FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));- src = TMP_REG1;- srcw = 0;- }-- cc = get_cc(compiler, type & 0xff);- dst_reg &= ~SLJIT_32;-- return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 reg,- sljit_s32 mem, sljit_sw memw)-{- sljit_u32 sign = 0, inst;-- CHECK_ERROR();- CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));-- if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))- return SLJIT_ERR_UNSUPPORTED;-- if (type & SLJIT_MEM_SUPP)- return SLJIT_SUCCESS;-- switch (type & 0xff) {- case SLJIT_MOV:- case SLJIT_MOV_P:- inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400;- break;- case SLJIT_MOV_S8:- sign = 1;- /* fallthrough */- case SLJIT_MOV_U8:- inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400;- break;- case SLJIT_MOV_S16:- sign = 1;- /* fallthrough */- case SLJIT_MOV_U16:- inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400;- break;- case SLJIT_MOV_S32:- sign = 1;- /* fallthrough */- case SLJIT_MOV_U32:- case SLJIT_MOV32:- inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400;- break;- default:- SLJIT_UNREACHABLE();- inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400;- break;- }-- if (!(type & SLJIT_MEM_STORE))- inst |= sign ? 0x00800000 : 0x00400000;-- if (type & SLJIT_MEM_PRE)- inst |= 0x800;-- return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 freg,- sljit_s32 mem, sljit_sw memw)-{- sljit_u32 inst;-- CHECK_ERROR();- CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));-- if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))- return SLJIT_ERR_UNSUPPORTED;-- if (type & SLJIT_MEM_SUPP)- return SLJIT_SUCCESS;-- inst = STUR_FI | 0x80000400;-- if (!(type & SLJIT_32))- inst |= 0x40000000;-- if (!(type & SLJIT_MEM_STORE))- inst |= 0x00400000;-- if (type & SLJIT_MEM_PRE)- inst |= 0x800;-- return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)-{- sljit_s32 dst_reg;- sljit_ins ins;-- CHECK_ERROR();- CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));- ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);-- dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;-- /* Not all instruction forms support accessing SP register. */- if (offset <= 0xffffff && offset >= -0xffffff) {- ins = ADDI;- if (offset < 0) {- offset = -offset;- ins = SUBI;- }-- if (offset <= 0xfff)- FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)(offset << 10)));- else {- FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)((offset & 0xfff000) >> (12 - 10)) | (1 << 22)));-- offset &= 0xfff;- if (offset != 0)- FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (sljit_ins)(offset << 10)));- }- }- else {- FAIL_IF(load_immediate (compiler, dst_reg, offset));- /* Add extended register form. */- FAIL_IF(push_inst(compiler, ADDE | (0x3 << 13) | RD(dst_reg) | RN(SLJIT_SP) | RM(dst_reg)));- }-- if (SLJIT_UNLIKELY(dst & SLJIT_MEM))- return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1);- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)-{- struct sljit_const *const_;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));- ADJUST_LOCAL_OFFSET(dst, dstw);-- const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));- PTR_FAIL_IF(!const_);- set_const(const_, compiler);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;- PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, (sljit_uw)init_value));-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));- return const_;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- struct sljit_put_label *put_label;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;- PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, 0));-- put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));- PTR_FAIL_IF(!put_label);- set_put_label(put_label, compiler, 1);-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));-- return put_label;+#define ADC 0x9a000000+#define ADD 0x8b000000+#define ADDE 0x8b200000+#define ADDI 0x91000000+#define ADR 0x10000000+#define ADRP 0x90000000+#define AND 0x8a000000+#define ANDI 0x92000000+#define AND_v 0x0e201c00+#define ASRV 0x9ac02800+#define B 0x14000000+#define B_CC 0x54000000+#define BL 0x94000000+#define BLR 0xd63f0000+#define BR 0xd61f0000+#define BRK 0xd4200000+#define CAS 0xc8a07c00+#define CASB 0x08a07c00+#define CASH 0x48a07c00+#define CBZ 0xb4000000+#define CCMPI 0xfa400800+#define CLZ 0xdac01000+#define CSEL 0x9a800000+#define CSINC 0x9a800400+#define DUP_e 0x0e000400+#define DUP_g 0x0e000c00+#define EOR 0xca000000+#define EOR_v 0x2e201c00+#define EORI 0xd2000000+#define EXTR 0x93c00000+#define FABS 0x1e60c000+#define FADD 0x1e602800+#define FCMP 0x1e602000+#define FCSEL 0x1e600c00+#define FCVT 0x1e224000+#define FCVTL 0x0e217800+#define FCVTZS 0x9e780000+#define FDIV 0x1e601800+#define FMOV 0x1e604000+#define FMOV_R 0x9e660000+#define FMOV_I 0x1e601000+#define FMUL 0x1e600800+#define FNEG 0x1e614000+#define FSUB 0x1e603800+#define INS 0x4e001c00+#define INS_e 0x6e000400+#define LD1 0x0c407000+#define LD1_s 0x0d400000+#define LD1R 0x0d40c000+#define LDRI 0xf9400000+#define LDRI_F64 0xfd400000+#define LDRI_POST 0xf8400400+#define LDP 0xa9400000+#define LDP_F64 0x6d400000+#define LDP_POST 0xa8c00000+#define LDR_PRE 0xf8400c00+#define LDXR 0xc85f7c00+#define LDXRB 0x085f7c00+#define LDXRH 0x485f7c00+#define LSLV 0x9ac02000+#define LSRV 0x9ac02400+#define MADD 0x9b000000+#define MOVI 0x0f000400+#define MOVK 0xf2800000+#define MOVN 0x92800000+#define MOVZ 0xd2800000+#define NOP 0xd503201f+#define ORN 0xaa200000+#define ORR 0xaa000000+#define ORR_v 0x0ea01c00+#define ORRI 0xb2000000+#define RBIT 0xdac00000+#define RET 0xd65f0000+#define REV 0xdac00c00+#define REV16 0xdac00400+#define RORV 0x9ac02c00+#define SBC 0xda000000+#define SBFM 0x93400000+#define SCVTF 0x9e620000+#define SDIV 0x9ac00c00+#define SMADDL 0x9b200000+#define SMOV 0x0e002c00+#define SMULH 0x9b403c00+#define SSHLL 0x0f00a400+#define ST1 0x0c007000+#define ST1_s 0x0d000000+#define STP 0xa9000000+#define STP_F64 0x6d000000+#define STP_PRE 0xa9800000+#define STRB 0x38206800+#define STRBI 0x39000000+#define STRI 0xf9000000+#define STRI_F64 0xfd000000+#define STR_FI 0x3d000000+#define STR_FR 0x3c206800+#define STUR_FI 0x3c000000+#define STURBI 0x38000000+#define STXR 0xc8007c00+#define STXRB 0x8007c00+#define STXRH 0x48007c00+#define SUB 0xcb000000+#define SUBI 0xd1000000+#define SUBS 0xeb000000+#define TBZ 0x36000000+#define UBFM 0xd3400000+#define UCVTF 0x9e630000+#define UDIV 0x9ac00800+#define UMOV 0x0e003c00+#define UMULH 0x9bc03c00+#define USHLL 0x2f00a400+#define USHR 0x2f000400+#define USRA 0x2f001400+#define XTN 0x0e212800++#define CSET (CSINC | RM(TMP_ZERO) | RN(TMP_ZERO))+#define LDR (STRI | (1 << 22))+#define LDRB (STRBI | (1 << 22))+#define LDRH (LDRB | (1 << 30))+#define MOV (ORR | RN(TMP_ZERO))++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);+ *ptr = ins;+ compiler->size++;+ return SLJIT_SUCCESS;+}++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) | ((sljit_ins)(imm & 0xffff) << 5)));+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)(imm >> 16) & 0xffff) << 5) | (1 << 21)));+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)(imm >> 32) & 0xffff) << 5) | (2 << 21)));+ return push_inst(compiler, MOVK | RD(dst) | ((sljit_ins)(imm >> 48) << 5) | (3 << 21));+}++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;++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ goto exit;++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->u.label != NULL);+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;+ }++ diff = (sljit_sw)target_addr - (sljit_sw)code_ptr - executable_offset;++ if (jump->flags & IS_COND) {+ diff += SSIZE_OF(ins);+ if (diff <= 0xfffff && diff >= -0x100000) {+ *(--code_ptr) ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1;+ jump->flags |= PATCH_COND;+ jump->addr -= sizeof(sljit_ins);+ return code_ptr;+ }+ diff -= SSIZE_OF(ins);+ }++ if (diff <= 0x7ffffff && diff >= -0x8000000) {+ if (jump->flags & IS_COND)+ code_ptr[-1] -= (4 << 5);+ jump->flags |= PATCH_B;+ return code_ptr;+ }++ if (target_addr < 0x100000000l) {+ if (jump->flags & IS_COND)+ code_ptr[-1] -= (2 << 5);+ code_ptr[2] = code_ptr[0];+ return code_ptr + 2;+ }++ if (diff <= 0xfffff000l && diff >= -0x100000000l) {+ if (jump->flags & IS_COND)+ code_ptr[-1] -= (2 << 5);+ jump->flags |= PATCH_B32;+ code_ptr[2] = code_ptr[0];+ return code_ptr + 2;+ }++ if (target_addr < 0x1000000000000l) {+ if (jump->flags & IS_COND)+ code_ptr[-1] -= (1 << 5);+ jump->flags |= PATCH_ABS48;+ code_ptr[3] = code_ptr[0];+ return code_ptr + 3;+ }++exit:+ jump->flags |= PATCH_ABS64;+ code_ptr[4] = code_ptr[0];+ return code_ptr + 4;+}++static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_uw addr;+ sljit_sw diff;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_ASSERT(jump->flags < ((sljit_uw)4 << JUMP_SIZE_SHIFT));+ if (jump->flags & JUMP_ADDR)+ addr = jump->u.target;+ else+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ if (diff <= 0xfffff && diff >= -0x100000) {+ jump->flags |= PATCH_B;+ return 0;+ }++ if (diff <= 0xfffff000l && diff >= -0x100000000l) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_B32;+ return 1;+ }++ if (addr < 0x100000000l) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));+ return 1;+ }++ if (addr < 0x1000000000000l) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)2 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS48;+ return 2;+ }++ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS64;+ return 3;+}++static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)+{+ sljit_sw addr = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr);+ sljit_ins* buf_ptr = (sljit_ins*)jump->addr;+ sljit_u32 dst;+ SLJIT_UNUSED_ARG(executable_offset);++ if (!(jump->flags & JUMP_MOV_ADDR)) {+ if (jump->flags & PATCH_COND) {+ addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;+ SLJIT_ASSERT(addr <= 0x3ffff && addr >= -0x40000);+ buf_ptr[0] = (buf_ptr[0] & ~(sljit_ins)0xffffe0) | (sljit_ins)((addr & 0x7ffff) << 5);+ return;+ }++ if (jump->flags & PATCH_B) {+ addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;+ SLJIT_ASSERT(addr <= 0x1ffffff && addr >= -0x2000000);+ buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (sljit_ins)(addr & 0x3ffffff);+ return;+ }++ dst = (buf_ptr[0] >> 5) & 0x1f;++ if (jump->flags & PATCH_B32) {+ addr -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) & ~(sljit_sw)0xfff;+ SLJIT_ASSERT(addr <= 0xfffff000l && addr >= -0x100000000l);+ buf_ptr[0] = ADRP | (((sljit_ins)(addr >> 12) & 0x3) << 29) | (((sljit_ins)(addr >> 14) & 0x7ffff) << 5) | dst;+ buf_ptr[1] = ADDI | dst | (dst << 5) | ((sljit_ins)(addr & 0xfff) << 10);+ return;+ }+ } else {+ dst = *buf_ptr;++ if (jump->flags & PATCH_B) {+ addr -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);+ SLJIT_ASSERT(addr <= 0xfffff && addr >= -0x100000);+ buf_ptr[0] = ADR | (((sljit_ins)addr & 0x3) << 29) | (((sljit_ins)(addr >> 2) & 0x7ffff) << 5) | dst;+ return;+ }++ if (jump->flags & PATCH_B32) {+ addr -= ((sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) & ~(sljit_sw)0xfff;+ SLJIT_ASSERT(addr <= 0xffffffffl && addr >= -0x100000000l);+ buf_ptr[0] = ADRP | (((sljit_ins)(addr >> 12) & 0x3) << 29) | (((sljit_ins)(addr >> 14) & 0x7ffff) << 5) | dst;+ buf_ptr[1] = ADDI | dst | (dst << 5) | ((sljit_ins)(addr & 0xfff) << 10);+ return;+ }+ }++ SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || (sljit_uw)addr <= (sljit_uw)0xffffffff);+ SLJIT_ASSERT((jump->flags & PATCH_ABS64) || (sljit_uw)addr <= (sljit_uw)0xffffffffffff);++ buf_ptr[0] = MOVZ | (((sljit_ins)addr & 0xffff) << 5) | dst;+ buf_ptr[1] = MOVK | (((sljit_ins)(addr >> 16) & 0xffff) << 5) | (1 << 21) | dst;+ if (jump->flags & (PATCH_ABS48 | PATCH_ABS64))+ buf_ptr[2] = MOVK | (((sljit_ins)(addr >> 32) & 0xffff) << 5) | (2 << 21) | dst;++ if (jump->flags & PATCH_ABS64)+ buf_ptr[3] = MOVK | ((sljit_ins)((sljit_uw)addr >> 48) << 5) | (3 << 21) | dst;+}++static void reduce_code_size(struct sljit_compiler *compiler)+{+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_uw total_size;+ sljit_uw size_reduce = 0;+ sljit_sw diff;++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();++ while (1) {+ SLJIT_GET_NEXT_MIN();++ if (next_min_addr == SLJIT_MAX_ADDRESS)+ break;++ if (next_min_addr == next_label_size) {+ label->size -= size_reduce;++ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_const_addr) {+ const_->addr -= size_reduce;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ continue;+ }++ if (next_min_addr != next_jump_addr)+ continue;++ jump->addr -= size_reduce;+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ total_size = JUMP_MAX_SIZE;++ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {+ if (jump->flags & JUMP_ADDR) {+ if (jump->u.target < 0x100000000l)+ total_size = 3;+ else if (jump->u.target < 0x1000000000000l)+ total_size = 4;+ } else {+ /* Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;++ if ((jump->flags & IS_COND) && (diff + 1) <= (0xfffff / SSIZE_OF(ins)) && (diff + 1) >= (-0x100000 / SSIZE_OF(ins)))+ total_size = 0;+ else if (diff <= (0x7ffffff / SSIZE_OF(ins)) && diff >= (-0x8000000 / SSIZE_OF(ins)))+ total_size = 1;+ else if (diff <= (0xfffff000l / SSIZE_OF(ins)) && diff >= (-0x100000000l / SSIZE_OF(ins)))+ total_size = 3;+ }+ }++ size_reduce += JUMP_MAX_SIZE - total_size;+ } else {+ /* Real size minus 1. Unit size: instruction. */+ total_size = 3;++ if (!(jump->flags & JUMP_ADDR)) {+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;++ if (diff <= (0xfffff / SSIZE_OF(ins)) && diff >= (-0x100000 / SSIZE_OF(ins)))+ total_size = 0;+ else if (diff <= (0xfffff000l / SSIZE_OF(ins)) && diff >= (-0x100000000l / SSIZE_OF(ins)))+ total_size = 1;+ } else if (jump->u.target < 0x100000000l)+ total_size = 1;+ else if (jump->u.target < 0x1000000000000l)+ total_size = 2;++ size_reduce += 3 - total_size;+ }++ jump->flags |= total_size << JUMP_SIZE_SHIFT;+ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ }++ compiler->size -= size_reduce;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_sw executable_offset;+ sljit_sw addr;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));++ reduce_code_size(compiler);++ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);+ PTR_FAIL_WITH_EXEC_IF(code);++ reverse_buf(compiler);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();+ SLJIT_GET_NEXT_MIN();++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ *code_ptr = *buf_ptr++;+ if (next_min_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);++ /* These structures are ordered by their address. */+ if (next_min_addr == next_label_size) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_jump_addr) {+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);+ jump->addr = (sljit_uw)code_ptr;+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);+ SLJIT_ASSERT((jump->flags & PATCH_COND) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));+ } else {+ word_count += jump->flags >> JUMP_SIZE_SHIFT;+ addr = (sljit_sw)code_ptr;+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);+ jump->addr = (sljit_uw)addr;+ }++ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ } else if (next_min_addr == next_const_addr) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ }++ SLJIT_GET_NEXT_MIN();+ }+ code_ptr++;+ word_count++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ generate_jump_or_mov_addr(jump, executable_offset);+ jump = jump->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (sljit_uw)(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);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ return code;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ switch (feature_type) {+ case SLJIT_HAS_FPU:+ case SLJIT_HAS_SIMD:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return (SLJIT_IS_FPU_AVAILABLE) != 0;+#else+ /* Available by default. */+ return 1;+#endif++ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CTZ:+ case SLJIT_HAS_REV:+ case SLJIT_HAS_ROT:+ case SLJIT_HAS_CMOV:+ case SLJIT_HAS_PREFETCH:+ case SLJIT_HAS_COPY_F32:+ case SLJIT_HAS_COPY_F64:+ case SLJIT_HAS_ATOMIC:+ return 1;++ default:+ return 0;+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)+{+ switch (type) {+ case SLJIT_UNORDERED_OR_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ return 2;+ }++ return 0;+}++/* --------------------------------------------------------------------- */+/* Core code generator functions. */+/* --------------------------------------------------------------------- */++#define COUNT_TRAILING_ZERO(value, result) \+ result = 0; \+ if (!(value & 0xffffffff)) { \+ result += 32; \+ value >>= 32; \+ } \+ if (!(value & 0xffff)) { \+ result += 16; \+ value >>= 16; \+ } \+ if (!(value & 0xff)) { \+ result += 8; \+ value >>= 8; \+ } \+ if (!(value & 0xf)) { \+ result += 4; \+ value >>= 4; \+ } \+ if (!(value & 0x3)) { \+ result += 2; \+ value >>= 2; \+ } \+ if (!(value & 0x1)) { \+ result += 1; \+ value >>= 1; \+ }++#define LOGICAL_IMM_CHECK (sljit_ins)0x100++static sljit_ins logical_imm(sljit_sw imm, sljit_u32 len)+{+ sljit_s32 negated;+ sljit_u32 ones, right;+ sljit_uw mask, uimm;+ sljit_ins ins;++ if (len & LOGICAL_IMM_CHECK) {+ len &= ~LOGICAL_IMM_CHECK;+ if (len == 32 && (imm == 0 || imm == -1))+ return 0;+ if (len == 16 && ((sljit_s32)imm == 0 || (sljit_s32)imm == -1))+ return 0;+ }++ SLJIT_ASSERT((len == 32 && imm != 0 && imm != -1)+ || (len == 16 && (sljit_s32)imm != 0 && (sljit_s32)imm != -1));++ uimm = (sljit_uw)imm;+ while (1) {+ if (len <= 0) {+ SLJIT_UNREACHABLE();+ return 0;+ }++ mask = ((sljit_uw)1 << len) - 1;+ if ((uimm & mask) != ((uimm >> len) & mask))+ break;+ len >>= 1;+ }++ len <<= 1;++ negated = 0;+ if (uimm & 0x1) {+ negated = 1;+ uimm = ~uimm;+ }++ if (len < 64)+ uimm &= ((sljit_uw)1 << len) - 1;++ /* Unsigned right shift. */+ COUNT_TRAILING_ZERO(uimm, right);++ /* Signed shift. We also know that the highest bit is set. */+ imm = (sljit_sw)~uimm;+ SLJIT_ASSERT(imm < 0);++ COUNT_TRAILING_ZERO(imm, ones);++ if (~imm)+ return 0;++ if (len == 64)+ ins = 1 << 22;+ else+ ins = (0x3f - ((len << 1) - 1)) << 10;++ if (negated)+ return ins | ((len - ones - 1) << 10) | ((len - ones - right) << 16);++ return ins | ((ones - 1) << 10) | ((len - right) << 16);+}++#undef COUNT_TRAILING_ZERO++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw simm)+{+ sljit_uw imm = (sljit_uw)simm;+ sljit_u32 i, zeros, ones, first;+ sljit_ins bitmask;++ /* Handling simple immediates first. */+ if (imm <= 0xffff)+ return push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)imm << 5));++ if (simm < 0 && simm >= -0x10000)+ return push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5));++ if (imm <= 0xffffffffl) {+ if ((imm & 0xffff) == 0)+ return push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)(imm >> 16) << 5) | (1 << 21));+ if ((imm & 0xffff0000l) == 0xffff0000)+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5));+ if ((imm & 0xffff) == 0xffff)+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | (((sljit_ins)~imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));++ bitmask = logical_imm(simm, 16);+ if (bitmask != 0)+ return push_inst(compiler, (ORRI ^ W_OP) | RD(dst) | RN(TMP_ZERO) | bitmask);++ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | (((sljit_ins)imm & 0xffff) << 5)));+ return push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));+ }++ bitmask = logical_imm(simm, 32);+ if (bitmask != 0)+ return push_inst(compiler, ORRI | RD(dst) | RN(TMP_ZERO) | bitmask);++ if (simm < 0 && simm >= -0x100000000l) {+ if ((imm & 0xffff) == 0xffff)+ return push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));++ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5)));+ return push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));+ }++ /* A large amount of number can be constructed from ORR and MOVx, but computing them is costly. */++ zeros = 0;+ ones = 0;+ for (i = 4; i > 0; i--) {+ if ((simm & 0xffff) == 0)+ zeros++;+ if ((simm & 0xffff) == 0xffff)+ ones++;+ simm >>= 16;+ }++ simm = (sljit_sw)imm;+ first = 1;+ if (ones > zeros) {+ simm = ~simm;+ for (i = 0; i < 4; i++) {+ if (!(simm & 0xffff)) {+ simm >>= 16;+ continue;+ }+ if (first) {+ first = 0;+ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));+ }+ else+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)~simm & 0xffff) << 5) | (i << 21)));+ simm >>= 16;+ }+ return SLJIT_SUCCESS;+ }++ for (i = 0; i < 4; i++) {+ if (!(simm & 0xffff)) {+ simm >>= 16;+ continue;+ }+ if (first) {+ first = 0;+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));+ }+ else+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));+ simm >>= 16;+ }+ return SLJIT_SUCCESS;+}++#define ARG1_IMM 0x0010000+#define ARG2_IMM 0x0020000+#define INT_OP 0x0040000+#define SET_FLAGS 0x0080000+#define UNUSED_RETURN 0x0100000++#define CHECK_FLAGS(flag_bits) \+ if (flags & SET_FLAGS) { \+ inv_bits |= flag_bits; \+ if (flags & UNUSED_RETURN) \+ dst = TMP_ZERO; \+ }++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) ? W_OP : 0;+ sljit_ins inst_bits;+ sljit_s32 op = (flags & 0xffff);+ sljit_s32 reg;+ sljit_sw imm, nimm;++ if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {+ /* Both are immediates. */+ flags &= ~ARG1_IMM;+ if (arg1 == 0 && op != SLJIT_ADD && op != SLJIT_SUB)+ arg1 = TMP_ZERO;+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));+ arg1 = TMP_REG1;+ }+ }++ if (flags & (ARG1_IMM | ARG2_IMM)) {+ reg = (sljit_s32)((flags & ARG2_IMM) ? arg1 : arg2);+ imm = (flags & ARG2_IMM) ? arg2 : arg1;++ switch (op) {+ case SLJIT_CLZ:+ case SLJIT_CTZ:+ case SLJIT_REV:+ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ case SLJIT_ADDC:+ case SLJIT_SUBC:+ case SLJIT_MUL:+ case SLJIT_MULADD:+ /* No form with immediate operand (except imm 0, which+ is represented by a ZERO register). */+ break;+ case SLJIT_MOV:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);+ return load_immediate(compiler, dst, imm);+ case SLJIT_SUB:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ if (flags & ARG1_IMM)+ break;+ imm = -imm;+ /* Fall through. */+ case SLJIT_ADD:+ if (op != SLJIT_SUB)+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;++ if (imm == 0) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, ((op == SLJIT_ADD ? ADDI : SUBI) ^ inv_bits) | RD(dst) | RN(reg));+ }+ if (imm > 0 && imm <= 0xfff) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((sljit_ins)imm << 10));+ }+ nimm = -imm;+ if (nimm > 0 && nimm <= 0xfff) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((sljit_ins)nimm << 10));+ }+ if (imm > 0 && imm <= 0xffffff && !(imm & 0xfff)) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)imm >> 12) << 10) | (1 << 22));+ }+ if (nimm > 0 && nimm <= 0xffffff && !(nimm & 0xfff)) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)nimm >> 12) << 10) | (1 << 22));+ }+ if (imm > 0 && imm <= 0xffffff && !(flags & SET_FLAGS)) {+ FAIL_IF(push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)imm >> 12) << 10) | (1 << 22)));+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(dst) | (((sljit_ins)imm & 0xfff) << 10));+ }+ if (nimm > 0 && nimm <= 0xffffff && !(flags & SET_FLAGS)) {+ FAIL_IF(push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)nimm >> 12) << 10) | (1 << 22)));+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(dst) | (((sljit_ins)nimm & 0xfff) << 10));+ }+ break;+ case SLJIT_AND:+ inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));+ if (!inst_bits)+ break;+ CHECK_FLAGS(3 << 29);+ return push_inst(compiler, (ANDI ^ inv_bits) | RD(dst) | RN(reg) | inst_bits);+ case SLJIT_XOR:+ if (imm == -1) {+ FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(reg)));+ goto set_flags;+ }+ /* fallthrough */+ case SLJIT_OR:+ inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));+ if (!inst_bits)+ break;+ if (op == SLJIT_OR)+ inst_bits |= ORRI;+ else+ inst_bits |= EORI;+ FAIL_IF(push_inst(compiler, (inst_bits ^ inv_bits) | RD(dst) | RN(reg)));+ goto set_flags;+ case SLJIT_SHL:+ case SLJIT_MSHL:+ if (flags & ARG1_IMM)+ break;++ if (flags & INT_OP) {+ imm &= 0x1f;+ inst_bits = (((sljit_ins)-imm & 0x1f) << 16) | ((31 - (sljit_ins)imm) << 10);+ } else {+ imm &= 0x3f;+ inst_bits = ((sljit_ins)1 << 22) | (((sljit_ins)-imm & 0x3f) << 16) | ((63 - (sljit_ins)imm) << 10);+ }++ inv_bits |= inv_bits >> 9;+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | inst_bits));+ goto set_flags;+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ if (flags & ARG1_IMM)+ break;++ inv_bits |= inv_bits >> 9;+ if (op >= SLJIT_ASHR)+ inv_bits |= 1 << 30;++ if (flags & INT_OP) {+ imm &= 0x1f;+ inst_bits = ((sljit_ins)imm << 16) | (31 << 10);+ } else {+ imm &= 0x3f;+ inst_bits = ((sljit_ins)1 << 22) | ((sljit_ins)imm << 16) | (63 << 10);+ }++ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | inst_bits));+ goto set_flags;+ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (flags & ARG1_IMM)+ break;++ if (op == SLJIT_ROTL)+ imm = -imm;++ imm &= (flags & INT_OP) ? 0x1f : 0x3f;+ return push_inst(compiler, (EXTR ^ (inv_bits | (inv_bits >> 9))) | RD(dst) | RN(arg1) | RM(arg1) | ((sljit_ins)imm << 10));+ default:+ SLJIT_UNREACHABLE();+ break;+ }++ if (flags & ARG2_IMM) {+ if (arg2 == 0)+ arg2 = TMP_ZERO;+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG2, arg2));+ arg2 = TMP_REG2;+ }+ }+ else {+ if (arg1 == 0)+ arg1 = TMP_ZERO;+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));+ arg1 = TMP_REG1;+ }+ }+ }++ /* Both arguments are registers. */+ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ if (dst == arg2)+ return SLJIT_SUCCESS;+ return push_inst(compiler, MOV | RD(dst) | RM(arg2));+ case SLJIT_MOV_U8:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ inv_bits |= inv_bits >> 9;+ return push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10));+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ inv_bits |= inv_bits >> 9;+ return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10));+ case SLJIT_MOV_U16:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ inv_bits |= inv_bits >> 9;+ return push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10));+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ inv_bits |= inv_bits >> 9;+ return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10));+ case SLJIT_MOV32:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ if (dst == arg2)+ return SLJIT_SUCCESS;+ /* fallthrough */+ case SLJIT_MOV_U32:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ return push_inst(compiler, (MOV ^ W_OP) | RD(dst) | RM(arg2));+ case SLJIT_MOV_S32:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10));+ case SLJIT_CLZ:+ SLJIT_ASSERT(arg1 == TMP_REG1);+ return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2));+ case SLJIT_CTZ:+ SLJIT_ASSERT(arg1 == TMP_REG1);+ FAIL_IF(push_inst(compiler, (RBIT ^ inv_bits) | RD(dst) | RN(arg2)));+ return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(dst));+ case SLJIT_REV:+ SLJIT_ASSERT(arg1 == TMP_REG1);+ inv_bits |= inv_bits >> 21;+ return push_inst(compiler, (REV ^ inv_bits) | RD(dst) | RN(arg2));+ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ SLJIT_ASSERT(arg1 == TMP_REG1 && dst != TMP_REG2);+ FAIL_IF(push_inst(compiler, (REV16 ^ (sljit_ins)0x80000000) | RD(dst) | RN(arg2)));+ if (dst == TMP_REG1 || (arg2 == TMP_REG2 && op == SLJIT_REV_U16))+ return SLJIT_SUCCESS;+ inv_bits |= inv_bits >> 9;+ return push_inst(compiler, ((op == SLJIT_REV_U16 ? UBFM : SBFM) ^ inv_bits) | RD(dst) | RN(dst) | (15 << 10));+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ SLJIT_ASSERT(arg1 == TMP_REG1 && dst != TMP_REG2);+ FAIL_IF(push_inst(compiler, (REV ^ (sljit_ins)0x80000400) | RD(dst) | RN(arg2)));+ if (op == SLJIT_REV_U32 || dst == TMP_REG1)+ return SLJIT_SUCCESS;+ return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(dst) | (31 << 10));+ case SLJIT_ADD:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_ADDC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (ADC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_SUB:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_SUBC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (SBC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_MUL:+ compiler->status_flags_state = 0;+ if (!(flags & SET_FLAGS))+ return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO));+ if (flags & INT_OP) {+ FAIL_IF(push_inst(compiler, SMADDL | RD(dst) | RN(arg1) | RM(arg2) | (31 << 10)));+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_LR) | RN(TMP_ZERO) | RM(dst) | (2 << 22) | (31 << 10)));+ return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10));+ }+ FAIL_IF(push_inst(compiler, SMULH | RD(TMP_LR) | RN(arg1) | RM(arg2)));+ FAIL_IF(push_inst(compiler, MADD | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO)));+ return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10));+ case SLJIT_AND:+ CHECK_FLAGS(3 << 29);+ 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)));+ break; /* Set flags. */+ case SLJIT_XOR:+ FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));+ break; /* Set flags. */+ case SLJIT_SHL:+ case SLJIT_MSHL:+ FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));+ break; /* Set flags. */+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));+ break; /* Set flags. */+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));+ break; /* Set flags. */+ case SLJIT_ROTL:+ FAIL_IF(push_inst(compiler, (SUB ^ inv_bits) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(arg2)));+ arg2 = TMP_REG2;+ /* fallthrough */+ case SLJIT_ROTR:+ return push_inst(compiler, (RORV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_MULADD:+ compiler->status_flags_state = 0;+ return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(dst));+ default:+ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+ }++set_flags:+ if (flags & SET_FLAGS)+ return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO));+ return SLJIT_SUCCESS;+}++#define STORE 0x10+#define SIGNED 0x20++#define BYTE_SIZE 0x0+#define HALF_SIZE 0x1+#define INT_SIZE 0x2+#define WORD_SIZE 0x3++#define MEM_SIZE_SHIFT(flags) ((sljit_ins)(flags) & 0x3)++static 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_u32 shift = MEM_SIZE_SHIFT(flags);+ sljit_u32 type = (shift << 30);++ if (!(flags & STORE))+ type |= (flags & SIGNED) ? 0x00800000 : 0x00400000;++ SLJIT_ASSERT(arg & SLJIT_MEM);++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ if (argw == 0 || argw == shift)+ return push_inst(compiler, STRB | type | RT(reg)+ | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));++ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)argw << 10)));+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg));+ }++ arg &= REG_MASK;++ if (!arg) {+ FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~(0xfff << shift)));++ argw = (argw >> shift) & 0xfff;++ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));+ }++ if ((argw & ((1 << shift) - 1)) == 0) {+ if (argw >= 0) {+ if ((argw >> shift) <= 0xfff)+ return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift)));++ if (argw <= 0xffffff) {+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));++ argw = ((argw & 0xfff) >> shift);+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));+ }+ } else if (argw < -256 && argw >= -0xfff000) {+ FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)(-argw + 0xfff) >> 12) << 10)));+ argw = ((0x1000 + argw) & 0xfff) >> shift;+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));+ }+ }++ if (argw <= 0xff && argw >= -0x100)+ return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12));++ if (((argw + 0x100) & 0xfff) <= 0x1ff && argw <= 0xfff0ff && argw >= -0xfff100) {+ if (argw >= 0) {+ if (argw & 0x100)+ argw += 0x1000;++ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));+ return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12));+ } else {+ if (!(argw & 0x100))+ argw -= 0x1000;++ FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)-argw >> 12) << 10)));+ return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12));+ }+ }++ FAIL_IF(load_immediate(compiler, tmp_reg, argw));++ return push_inst(compiler, STRB | type | RT(reg) | RN(arg) | RM(tmp_reg));+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 prev, fprev, saved_regs_size, i, tmp;+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);+ sljit_ins offs;++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 2);+ saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);++ local_size = (local_size + saved_regs_size + 0xf) & ~0xf;+ compiler->local_size = local_size;++ if (local_size <= 512) {+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)+ | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));+ offs = (sljit_ins)(local_size - 2 * SSIZE_OF(sw)) << (15 - 3);+ local_size = 0;+ } else {+ saved_regs_size = ((saved_regs_size - 2 * SSIZE_OF(sw)) + 0xf) & ~0xf;++ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)saved_regs_size << 10)));+ offs = (sljit_ins)(saved_regs_size - 2 * SSIZE_OF(sw)) << (15 - 3);+ local_size -= saved_regs_size;+ SLJIT_ASSERT(local_size > 0);+ }++ prev = -1;++ tmp = SLJIT_S0 - saveds;+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {+ if (prev == -1) {+ prev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));+ offs -= (sljit_ins)2 << 15;+ prev = -1;+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ if (prev == -1) {+ prev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));+ offs -= (sljit_ins)2 << 15;+ prev = -1;+ }++ fprev = -1;++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ if (fprev == -1) {+ fprev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, STP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));+ offs -= (sljit_ins)2 << 15;+ fprev = -1;+ }++ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ if (fprev == -1) {+ fprev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, STP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));+ offs -= (sljit_ins)2 << 15;+ fprev = -1;+ }++ if (fprev != -1)+ FAIL_IF(push_inst(compiler, STRI_F64 | VT(fprev) | RN(SLJIT_SP) | (offs >> 5) | (1 << 10)));++ if (prev != -1)+ FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));+++#ifdef _WIN32+ if (local_size > 4096)+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));+#endif /* _WIN32 */++ if (!(options & SLJIT_ENTER_REG_ARG)) {+ arg_types >>= SLJIT_ARG_SHIFT;+ saved_arg_count = 0;+ tmp = SLJIT_R0;++ while (arg_types) {+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0 - saved_arg_count) | RM(tmp)));+ saved_arg_count++;+ }+ tmp++;+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }+ }++#ifdef _WIN32+ if (local_size > 4096) {+ if (local_size < 4 * 4096) {+ /* No need for a loop. */++ if (local_size >= 2 * 4096) {+ if (local_size >= 3 * 4096) {+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));+ }++ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));+ }+ }+ else {+ FAIL_IF(push_inst(compiler, MOVZ | RD(TMP_REG1) | ((((sljit_ins)local_size >> 12) - 1) << 5)));+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));+ FAIL_IF(push_inst(compiler, SUBI | (1 << 29) | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10)));+ FAIL_IF(push_inst(compiler, B_CC | ((((sljit_ins) -3) & 0x7ffff) << 5) | 0x1 /* not-equal */));+ }++ local_size &= 0xfff;++ if (local_size > 0)+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));+ else+ FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));+ }++ if (local_size > 0) {+ if (local_size <= 512)+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)+ | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));+ else {+ if (local_size >= 4096)+ local_size = (1 << (22 - 10));++ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));+ FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));+ }+ }++#else /* !_WIN32 */++ /* The local_size does not include saved registers size. */+ if (local_size != 0) {+ if (local_size > 0xfff) {+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (((sljit_ins)local_size >> 12) << 10) | (1 << 22)));+ local_size &= 0xfff;+ }++ if (local_size > 512 || local_size == 0) {+ if (local_size != 0)+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));++ FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));+ } else+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)+ | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));+ }++#endif /* _WIN32 */++ return push_inst(compiler, ADDI | RD(TMP_FP) | RN(SLJIT_SP) | (0 << 10));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 saved_regs_size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 2);+ saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);++ compiler->local_size = (local_size + saved_regs_size + 0xf) & ~0xf;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)+{+ sljit_s32 local_size, prev, fprev, i, tmp;+ sljit_ins offs;++ local_size = compiler->local_size;++ if (!is_return_to) {+ if (local_size > 512 && local_size <= 512 + 496) {+ FAIL_IF(push_inst(compiler, LDP_POST | RT(TMP_FP) | RT2(TMP_LR)+ | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << (15 - 3))));+ local_size = 512;+ } else+ FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));+ } else {+ if (local_size > 512 && local_size <= 512 + 248) {+ FAIL_IF(push_inst(compiler, LDRI_POST | RT(TMP_FP) | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << 12)));+ local_size = 512;+ } else+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_FP) | RN(SLJIT_SP) | 0));+ }++ if (local_size > 512) {+ local_size -= 512;+ if (local_size > 0xfff) {+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP)+ | (((sljit_ins)local_size >> 12) << 10) | (1 << 22)));+ local_size &= 0xfff;+ }++ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));+ local_size = 512;+ }++ offs = (sljit_ins)(local_size - 2 * SSIZE_OF(sw)) << (15 - 3);+ prev = -1;++ tmp = SLJIT_S0 - compiler->saveds;+ for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {+ if (prev == -1) {+ prev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));+ offs -= (sljit_ins)2 << 15;+ prev = -1;+ }++ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ if (prev == -1) {+ prev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));+ offs -= (sljit_ins)2 << 15;+ prev = -1;+ }++ fprev = -1;++ tmp = SLJIT_FS0 - compiler->fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ if (fprev == -1) {+ fprev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, LDP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));+ offs -= (sljit_ins)2 << 15;+ fprev = -1;+ }++ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ if (fprev == -1) {+ fprev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, LDP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));+ offs -= (sljit_ins)2 << 15;+ fprev = -1;+ }++ if (fprev != -1)+ FAIL_IF(push_inst(compiler, LDRI_F64 | VT(fprev) | RN(SLJIT_SP) | (offs >> 5) | (1 << 10)));++ if (prev != -1)+ FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));++ /* This and the next call/jump instruction can be executed parallelly. */+ return push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (sljit_ins)(local_size << 10));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ FAIL_IF(emit_stack_frame_release(compiler, 0));++ return push_inst(compiler, RET | RN(TMP_LR));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ srcw = 0;+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));+ src = TMP_REG1;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 1));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+ sljit_ins inv_bits = (op & SLJIT_32) ? W_OP : 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ return push_inst(compiler, BRK);+ case SLJIT_NOP:+ return push_inst(compiler, NOP);+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | 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_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, (MOV ^ inv_bits) | RD(TMP_REG1) | RM(SLJIT_R0)));+ 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_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));+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++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_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));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ op = GET_OPCODE(op);+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {+ /* Both operands are registers. */+ if (FAST_IS_REG(dst) && FAST_IS_REG(src))+ return emit_op_imm(compiler, op | ((op_flags & SLJIT_32) ? INT_OP : 0), dst_r, TMP_REG1, src);++ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ mem_flags = WORD_SIZE;+ break;+ case SLJIT_MOV_U8:+ mem_flags = BYTE_SIZE;+ if (src == SLJIT_IMM)+ srcw = (sljit_u8)srcw;+ break;+ case SLJIT_MOV_S8:+ mem_flags = BYTE_SIZE | SIGNED;+ if (src == SLJIT_IMM)+ srcw = (sljit_s8)srcw;+ break;+ case SLJIT_MOV_U16:+ mem_flags = HALF_SIZE;+ if (src == SLJIT_IMM)+ srcw = (sljit_u16)srcw;+ break;+ case SLJIT_MOV_S16:+ mem_flags = HALF_SIZE | SIGNED;+ if (src == SLJIT_IMM)+ srcw = (sljit_s16)srcw;+ break;+ case SLJIT_MOV_U32:+ mem_flags = INT_SIZE;+ if (src == SLJIT_IMM)+ srcw = (sljit_u32)srcw;+ break;+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ mem_flags = INT_SIZE | SIGNED;+ if (src == SLJIT_IMM)+ srcw = (sljit_s32)srcw;+ break;+ default:+ SLJIT_UNREACHABLE();+ mem_flags = 0;+ break;+ }++ if (src == SLJIT_IMM)+ FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw));+ else if (!(src & SLJIT_MEM))+ dst_r = src;+ else+ FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, src, srcw, TMP_REG2));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+ }++ flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;++ switch (op) {+ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ mem_flags = HALF_SIZE;+ break;+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ mem_flags = INT_SIZE;+ break;+ default:+ mem_flags = WORD_SIZE;++ if (op_flags & SLJIT_32) {+ flags |= INT_OP;+ mem_flags = INT_SIZE;+ }+ break;+ }++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src, srcw, TMP_REG2));+ src = TMP_REG2;+ }++ emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, src);++ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))+ return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+}++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_s32 dst_r, flags, mem_flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;+ mem_flags = WORD_SIZE;++ if (op & SLJIT_32) {+ flags |= INT_OP;+ mem_flags = INT_SIZE;+ }++ if (dst == TMP_REG2)+ flags |= UNUSED_RETURN;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, src1, src1w, TMP_REG1));+ src1 = TMP_REG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src2, src2w, TMP_REG2));+ src2 = TMP_REG2;+ }++ if (src1 == SLJIT_IMM)+ flags |= ARG1_IMM;+ else+ src1w = src1;++ if (src2 == SLJIT_IMM)+ flags |= ARG2_IMM;+ else+ src2w = src2;++ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));++ switch (GET_OPCODE(op)) {+ case SLJIT_MULADD:+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, dst_reg, 0, src1, src1w, src2, src2w);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+ sljit_ins inv_bits, imm;+ sljit_s32 is_left;+ sljit_sw mask;++ CHECK_ERROR();+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));++ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);++ if (src1_reg == src2_reg) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);+ }++ ADJUST_LOCAL_OFFSET(src3, src3w);++ inv_bits = (op & SLJIT_32) ? W_OP : 0;++ if (src3 == SLJIT_IMM) {+ mask = inv_bits ? 0x1f : 0x3f;+ src3w &= mask;++ if (src3w == 0)+ return SLJIT_SUCCESS;++ if (is_left)+ src3w = (src3w ^ mask) + 1;++ return push_inst(compiler, (EXTR ^ (inv_bits | (inv_bits >> 9))) | RD(dst_reg)+ | RN(is_left ? src1_reg : src2_reg) | RM(is_left ? src2_reg : src1_reg) | ((sljit_ins)src3w << 10));+ }++ if (src3 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG2, src3, src3w, TMP_REG2));+ src3 = TMP_REG2;+ } else if (dst_reg == src3) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src3)));+ src3 = TMP_REG2;+ }++ FAIL_IF(push_inst(compiler, ((is_left ? LSLV : LSRV) ^ inv_bits) | RD(dst_reg) | RN(src1_reg) | RM(src3)));++ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {+ /* Shift left/right by 1. */+ if (is_left)+ imm = (sljit_ins)(inv_bits ? ((1 << 16) | (31 << 10)) : ((1 << 16) | (63 << 10) | (1 << 22)));+ else+ imm = (sljit_ins)(inv_bits ? ((31 << 16) | (30 << 10)) : ((63 << 16) | (62 << 10) | (1 << 22)));++ FAIL_IF(push_inst(compiler, (UBFM ^ (inv_bits | (inv_bits >> 9))) | RD(TMP_REG1) | RN(src2_reg) | imm));++ /* Set imm to mask. */+ imm = (sljit_ins)(inv_bits ? (4 << 10) : ((5 << 10) | (1 << 22)));+ FAIL_IF(push_inst(compiler, (EORI ^ inv_bits) | RD(TMP_REG2) | RN(src3) | imm));++ src2_reg = TMP_REG1;+ } else+ FAIL_IF(push_inst(compiler, (SUB ^ inv_bits) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(src3)));++ FAIL_IF(push_inst(compiler, ((is_left ? LSRV : LSLV) ^ inv_bits) | RD(TMP_REG1) | RN(src2_reg) | RM(TMP_REG2)));+ return push_inst(compiler, (ORR ^ inv_bits) | RD(dst_reg) | RN(dst_reg) | RM(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_LR) | RM(src)));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1));++ return push_inst(compiler, RET | RN(TMP_LR));+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4);++ /* The reg_map[op] should provide the appropriate constant. */+ if (op == SLJIT_PREFETCH_L1)+ op = 1;+ else if (op == SLJIT_PREFETCH_L2)+ op = 3;+ else if (op == SLJIT_PREFETCH_L3)+ op = 5;+ else+ op = 2;++ /* Signed word sized load is the prefetch instruction. */+ return emit_op_mem(compiler, WORD_SIZE | SIGNED, op, src, srcw, TMP_REG1);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 dst_r = TMP_LR;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ switch (op) {+ case SLJIT_FAST_ENTER:+ if (FAST_IS_REG(dst))+ return push_inst(compiler, MOV | RD(dst) | RM(TMP_LR));+ break;+ case SLJIT_GET_RETURN_ADDRESS:+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, dst_r, SLJIT_MEM1(SLJIT_SP), 0x8, TMP_REG2));+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));++ if (type == SLJIT_GP_REGISTER)+ return reg_map[reg];++ if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_64 && type != SLJIT_SIMD_REG_128)+ return -1;++ return freg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+ SLJIT_UNUSED_ARG(size);+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ sljit_u32 shift = MEM_SIZE_SHIFT(flags);+ sljit_ins type = (shift << 30);++ SLJIT_ASSERT(arg & SLJIT_MEM);++ if (!(flags & STORE))+ type |= 0x00400000;++ if (arg & OFFS_REG_MASK) {+ argw &= 3;+ if (argw == 0 || argw == shift)+ return push_inst(compiler, STR_FR | type | VT(reg)+ | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));++ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)argw << 10)));+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG2));+ }++ arg &= REG_MASK;++ if (!arg) {+ FAIL_IF(load_immediate(compiler, TMP_REG2, argw & ~(0xfff << shift)));++ argw = (argw >> shift) & 0xfff;++ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG2) | ((sljit_ins)argw << 10));+ }++ if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) {+ if ((argw >> shift) <= 0xfff)+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift)));++ if (argw <= 0xffffff) {+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(TMP_REG2) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));++ argw = ((argw & 0xfff) >> shift);+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG2) | ((sljit_ins)argw << 10));+ }+ }++ if (argw <= 255 && argw >= -256)+ return push_inst(compiler, STUR_FI | type | VT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12));++ FAIL_IF(load_immediate(compiler, TMP_REG2, argw));+ return push_inst(compiler, STR_FR | type | VT(reg) | RN(arg) | RM(TMP_REG2));+}++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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;++ if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64)+ inv_bits |= W_OP;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) ? 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 & SLJIT_MEM)+ return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+}++static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ emit_op_mem(compiler, (ins & W_OP) ? WORD_SIZE : INT_SIZE, TMP_REG1, src, srcw, TMP_REG1);+ src = TMP_REG1;+ } else if (src == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, ins | VD(dst_r) | RN(src)));++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, ((ins & (1 << 22)) ? WORD_SIZE : INT_SIZE) | STORE, TMP_FREG1, dst, dstw);+ return SLJIT_SUCCESS;+}++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_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {+ inv_bits |= W_OP;++ if (src == SLJIT_IMM)+ srcw = (sljit_s32)srcw;+ }++ return sljit_emit_fop1_conv_f64_from_w(compiler, SCVTF ^ inv_bits, dst, dstw, src, srcw);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {+ inv_bits |= W_OP;++ if (src == SLJIT_IMM)+ srcw = (sljit_u32)srcw;+ }++ return sljit_emit_fop1_conv_f64_from_w(compiler, UCVTF ^ inv_bits, dst, dstw, src, srcw);+}++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_s32 mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w));+ src2 = TMP_FREG2;+ }++ FAIL_IF(push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2)));++ if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, CSINC | (0x0 << 12) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(TMP_ZERO)));+ return push_inst(compiler, CCMPI | (0x0 << 16) | (0x7 << 12) | RN(TMP_REG1) | 0x4);+}++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_s32 dst_r, mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;+ sljit_ins inv_bits;++ CHECK_ERROR();++ SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x1) == WORD_SIZE, must_be_one_bit_difference);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x1) : mem_flags, dst_r, src, srcw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (!(dst & SLJIT_MEM))+ FAIL_IF(push_inst(compiler, (FMOV ^ inv_bits) | VD(dst_r) | VN(src)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(src)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src)));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ FAIL_IF(push_inst(compiler, FCVT | (sljit_ins)((op & SLJIT_32) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src)));+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, mem_flags | STORE, dst_r, dst, dstw);+ return SLJIT_SUCCESS;+}++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_s32 dst_r, mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;+ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w));+ src1 = TMP_FREG1;+ }+ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w));+ src2 = TMP_FREG2;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, (FADD ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));+ break;+ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, (FSUB ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));+ break;+ case SLJIT_MUL_F64:+ FAIL_IF(push_inst(compiler, (FMUL ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));+ break;+ case SLJIT_DIV_F64:+ FAIL_IF(push_inst(compiler, (FDIV ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));+ break;+ case SLJIT_COPYSIGN_F64:+ FAIL_IF(push_inst(compiler, (FMOV_R ^ ((op & SLJIT_32) ? (W_OP | (1 << 22)) : 0)) | VN(src2) | RD(TMP_REG1)));+ FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src1)));+ FAIL_IF(push_inst(compiler, TBZ | ((op & SLJIT_32) ? 0 : ((sljit_ins)1 << 31)) | (0x1f << 19) | (2 << 5) | RT(TMP_REG1)));+ return push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(dst_r));+ }++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+ sljit_u32 exp;+ union {+ sljit_u32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++ if (u.imm == 0)+ return push_inst(compiler, (FMOV_R ^ (W_OP | (1 << 22))) | RN(TMP_ZERO) | VD(freg) | (1 << 16));++ if ((u.imm << (32 - 19)) == 0) {+ exp = (u.imm >> (23 + 2)) & 0x3f;++ if (exp == 0x20 || exp == 0x1f)+ return push_inst(compiler, (FMOV_I ^ (1 << 22)) | (sljit_ins)((((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f)) << 13) | VD(freg));+ }++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_s32)u.imm));+ return push_inst(compiler, (FMOV_R ^ (W_OP | (1 << 22))) | RN(TMP_REG1) | VD(freg) | (1 << 16));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ sljit_uw exp;+ union {+ sljit_uw imm;+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ if (u.imm == 0)+ return push_inst(compiler, FMOV_R | RN(TMP_ZERO) | VD(freg) | (sljit_ins)1 << 16);++ if ((u.imm << (64 - 48)) == 0) {+ exp = (u.imm >> (52 + 2)) & 0x1ff;++ if (exp == 0x100 || exp == 0xff)+ return push_inst(compiler, FMOV_I | (sljit_ins)((((u.imm >> 56) & 0x80) | ((u.imm >> 48) & 0x7f)) << 13) | VD(freg));+ }++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_sw)u.imm));+ return push_inst(compiler, FMOV_R | RN(TMP_REG1) | VD(freg) | (1 << 16));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)+ inst = FMOV_R | RN(reg) | VD(freg) | (1 << 16);+ else+ inst = FMOV_R | VN(freg) | RD(reg);++ if (op & SLJIT_32)+ inst ^= W_OP | (1 << 22);++ return push_inst(compiler, inst);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_ATOMIC_STORED:+ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ return 0x1;++ case SLJIT_NOT_EQUAL:+ case SLJIT_ATOMIC_NOT_STORED:+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ return 0x0;++ case SLJIT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)+ return 0x3;+ /* fallthrough */++ case SLJIT_LESS:+ return 0x2;++ case SLJIT_NOT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)+ return 0x2;+ /* fallthrough */++ case SLJIT_GREATER_EQUAL:+ return 0x3;++ case SLJIT_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ return 0x9;++ case SLJIT_LESS_EQUAL:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ return 0x8;++ case SLJIT_SIG_LESS:+ case SLJIT_UNORDERED_OR_LESS:+ return 0xa;++ case SLJIT_SIG_GREATER_EQUAL:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ return 0xb;++ case SLJIT_SIG_GREATER:+ case SLJIT_F_GREATER:+ case SLJIT_ORDERED_GREATER:+ return 0xd;++ case SLJIT_SIG_LESS_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ return 0xc;++ case SLJIT_OVERFLOW:+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))+ return 0x0;+ /* fallthrough */++ case SLJIT_UNORDERED:+ return 0x7;++ case SLJIT_NOT_OVERFLOW:+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))+ return 0x1;+ /* fallthrough */++ case SLJIT_ORDERED:+ return 0x6;++ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ return 0x5;++ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ return 0x4;++ default:+ SLJIT_UNREACHABLE();+ return 0xe;+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ if (type < SLJIT_JUMP) {+ jump->flags |= IS_COND;+ PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(compiler, type)));+ } else if (type >= SLJIT_FAST_CALL)+ jump->flags |= IS_BL;++ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG2)));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ SLJIT_UNUSED_ARG(arg_types);+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ if (type & SLJIT_CALL_RETURN) {+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, type);+}++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_32) ? W_OP : 0;++ SLJIT_ASSERT((type & 0xff) == SLJIT_EQUAL || (type & 0xff) == SLJIT_NOT_EQUAL);+ ADJUST_LOCAL_OFFSET(src, srcw);++ 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_CBZ | IS_COND;++ if (src & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }+ else if (src == SLJIT_IMM) {+ PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ }++ SLJIT_ASSERT(FAST_IS_REG(src));++ if ((type & 0xff) == SLJIT_EQUAL)+ inv_bits |= 1 << 24;++ PTR_FAIL_IF(push_inst(compiler, (CBZ ^ inv_bits) | (6 << 5) | RT(src)));+ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, BR | RN(TMP_REG2)));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return jump;+}++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;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));++ if (src != SLJIT_IMM) {+ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));+ src = TMP_REG2;+ }+ return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(src));+ }++ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));+ jump->u.target = (sljit_uw)srcw;++ jump->addr = compiler->size;+ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG2));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(arg_types);+ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ if (type & SLJIT_CALL_RETURN) {+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));+ src = TMP_REG1;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 0));+ type = SLJIT_JUMP;+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+}++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_s32 dst_r, src_r, flags, mem_flags;+ sljit_ins cc;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ cc = get_cc(compiler, type);+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (GET_OPCODE(op) < SLJIT_ADD) {+ FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(dst_r) | RN(TMP_ZERO) | RM(TMP_ZERO)));++ if (dst & SLJIT_MEM) {+ mem_flags = (GET_OPCODE(op) == SLJIT_MOV ? WORD_SIZE : INT_SIZE) | STORE;+ return emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG2);+ }++ return SLJIT_SUCCESS;+ }++ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;+ mem_flags = WORD_SIZE;++ if (op & SLJIT_32) {+ flags |= INT_OP;+ mem_flags = INT_SIZE;+ }++ src_r = dst;++ if (dst & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG1));+ 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_mem(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+ sljit_ins inv_bits = (type & SLJIT_32) ? W_OP : 0;+ sljit_ins cc;++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (src1 == SLJIT_IMM) {+ if (type & SLJIT_32)+ src1w = (sljit_s32)src1w;+ FAIL_IF(load_immediate(compiler, TMP_REG2, src1w));+ src1 = TMP_REG2;+ } else if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src1, src1w, TMP_REG2));+ src1 = TMP_REG2;+ }++ cc = get_cc(compiler, type & ~SLJIT_32);+ return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(src2_reg) | RM(src1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+ sljit_ins inv_bits = (type & SLJIT_32) ? (1 << 22) : 0;+ sljit_ins cc;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) ? INT_SIZE : WORD_SIZE, TMP_FREG2, src1, src1w));+ src1 = TMP_FREG2;+ }++ cc = get_cc(compiler, type & ~SLJIT_32);+ return push_inst(compiler, (FCSEL ^ inv_bits) | (cc << 12) | VD(dst_freg) | VN(src2_freg) | VM(src1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_u32 inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (!(reg & REG_PAIR_MASK))+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);++ ADJUST_LOCAL_OFFSET(mem, memw);++ if (!(mem & REG_MASK)) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw & ~0x1f8));++ mem = SLJIT_MEM1(TMP_REG1);+ memw &= 0x1f8;+ } else if (mem & OFFS_REG_MASK) {+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 10)));++ mem = SLJIT_MEM1(TMP_REG1);+ memw = 0;+ } else if ((memw & 0x7) != 0 || memw > 0x1f8 || memw < -0x200) {+ inst = ADDI;++ if (memw < 0) {+ /* Remains negative for integer min. */+ memw = -memw;+ inst = SUBI;+ } else if ((memw & 0x7) == 0 && memw <= 0x7ff0) {+ if (!(type & SLJIT_MEM_STORE) && (mem & REG_MASK) == REG_PAIR_FIRST(reg)) {+ FAIL_IF(push_inst(compiler, LDRI | RD(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | ((sljit_ins)memw << 7)));+ return push_inst(compiler, LDRI | RD(REG_PAIR_FIRST(reg)) | RN(mem & REG_MASK) | ((sljit_ins)(memw + 0x8) << 7));+ }++ inst = (type & SLJIT_MEM_STORE) ? STRI : LDRI;++ FAIL_IF(push_inst(compiler, inst | RD(REG_PAIR_FIRST(reg)) | RN(mem & REG_MASK) | ((sljit_ins)memw << 7)));+ return push_inst(compiler, inst | RD(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | ((sljit_ins)(memw + 0x8) << 7));+ }++ if ((sljit_uw)memw <= 0xfff) {+ FAIL_IF(push_inst(compiler, inst | RD(TMP_REG1) | RN(mem & REG_MASK) | ((sljit_ins)memw << 10)));+ memw = 0;+ } else if ((sljit_uw)memw <= 0xffffff) {+ FAIL_IF(push_inst(compiler, inst | (1 << 22) | RD(TMP_REG1) | RN(mem & REG_MASK) | (((sljit_ins)memw >> 12) << 10)));++ if ((memw & 0xe07) != 0) {+ FAIL_IF(push_inst(compiler, inst | RD(TMP_REG1) | RN(TMP_REG1) | (((sljit_ins)memw & 0xfff) << 10)));+ memw = 0;+ } else {+ memw &= 0xfff;+ }+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw));+ FAIL_IF(push_inst(compiler, (inst == ADDI ? ADD : SUB) | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(TMP_REG1)));+ memw = 0;+ }++ mem = SLJIT_MEM1(TMP_REG1);++ if (inst == SUBI)+ memw = -memw;+ }++ SLJIT_ASSERT((memw & 0x7) == 0 && memw <= 0x1f8 && memw >= -0x200);+ return push_inst(compiler, ((type & SLJIT_MEM_STORE) ? STP : LDP) | RT(REG_PAIR_FIRST(reg)) | RT2(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x3f8) << 12));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_u32 sign = 0, inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));++ if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ switch (type & 0xff) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400;+ break;+ case SLJIT_MOV_S8:+ sign = 1;+ /* fallthrough */+ case SLJIT_MOV_U8:+ inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400;+ break;+ case SLJIT_MOV_S16:+ sign = 1;+ /* fallthrough */+ case SLJIT_MOV_U16:+ inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400;+ break;+ case SLJIT_MOV_S32:+ sign = 1;+ /* fallthrough */+ case SLJIT_MOV_U32:+ case SLJIT_MOV32:+ inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400;+ break;+ default:+ SLJIT_UNREACHABLE();+ inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400;+ break;+ }++ if (!(type & SLJIT_MEM_STORE))+ inst |= sign ? 0x00800000 : 0x00400000;++ if (!(type & SLJIT_MEM_POST))+ inst |= 0x800;++ return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_u32 inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));++ if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ inst = STUR_FI | 0x80000400;++ if (!(type & SLJIT_32))+ inst |= 0x40000000;++ if (!(type & SLJIT_MEM_STORE))+ inst |= 0x00400000;++ if (!(type & SLJIT_MEM_POST))+ inst |= 0x800;++ return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12));+}++static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw)+{+ sljit_ins ins;+ sljit_s32 mem = *mem_ptr;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ *mem_ptr = TMP_REG2;+ return push_inst(compiler, ADD | RD(TMP_REG2) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 10));+ }++ if (!(mem & REG_MASK)) {+ *mem_ptr = TMP_REG2;+ return load_immediate(compiler, TMP_REG2, memw);+ }++ mem &= REG_MASK;++ if (memw == 0) {+ *mem_ptr = mem;+ return SLJIT_SUCCESS;+ }++ *mem_ptr = TMP_REG2;++ if (memw < -0xffffff || memw > 0xffffff) {+ FAIL_IF(load_immediate(compiler, TMP_REG2, memw));+ return push_inst(compiler, ADD | RD(TMP_REG2) | RN(TMP_REG2) | RM(mem));+ }++ ins = ADDI;++ if (memw < 0) {+ memw = -memw;+ ins = SUBI;+ }++ if (memw > 0xfff) {+ FAIL_IF(push_inst(compiler, ins | (1 << 22) | RD(TMP_REG2) | RN(mem) | ((sljit_ins)(memw >> 12) << 10)));++ memw &= 0xfff;+ if (memw == 0)+ return SLJIT_SUCCESS;++ mem = TMP_REG2;+ }++ return push_inst(compiler, ins | RD(TMP_REG2) | RN(mem) | ((sljit_ins)memw << 10));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (!(srcdst & SLJIT_MEM)) {+ if (type & SLJIT_SIMD_STORE)+ ins = VD(srcdst) | VN(freg) | VM(freg);+ else+ ins = VD(freg) | VN(srcdst) | VM(srcdst);++ if (reg_size == 4)+ ins |= (1 << 30);++ return push_inst(compiler, ORR_v | ins);+ }++ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));++ if (elem_size > 3)+ elem_size = 3;++ ins = (type & SLJIT_SIMD_STORE) ? ST1 : LD1;++ if (reg_size == 4)+ ins |= (1 << 30);++ return push_inst(compiler, ins | ((sljit_ins)elem_size << 10) | RN(srcdst) | VT(freg));+}++static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value)+{+ sljit_ins result;++ if (elem_size > 2 && (sljit_u32)value == (value >> 32)) {+ elem_size = 2;+ value = (sljit_u32)value;+ }++ if (elem_size == 2 && (sljit_u16)value == (value >> 16)) {+ elem_size = 1;+ value = (sljit_u16)value;+ }++ if (elem_size == 1 && (sljit_u8)value == (value >> 8)) {+ elem_size = 0;+ value = (sljit_u8)value;+ }++ switch (elem_size) {+ case 0:+ SLJIT_ASSERT(value <= 0xff);+ result = 0xe000;+ break;+ case 1:+ SLJIT_ASSERT(value <= 0xffff);+ result = 0;++ while (1) {+ if (value <= 0xff) {+ result |= 0x8000;+ break;+ }++ if ((value & 0xff) == 0) {+ value >>= 8;+ result |= 0xa000;+ break;+ }++ if (result != 0)+ return ~(sljit_ins)0;++ value ^= (sljit_uw)0xffff;+ result = (1 << 29);+ }+ break;+ case 2:+ SLJIT_ASSERT(value <= 0xffffffff);+ result = 0;++ while (1) {+ if (value <= 0xff) {+ result |= 0x0000;+ break;+ }++ if ((value & ~(sljit_uw)0xff00) == 0) {+ value >>= 8;+ result |= 0x2000;+ break;+ }++ if ((value & ~(sljit_uw)0xff0000) == 0) {+ value >>= 16;+ result |= 0x4000;+ break;+ }++ if ((value & ~(sljit_uw)0xff000000) == 0) {+ value >>= 24;+ result |= 0x6000;+ break;+ }++ if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) {+ value >>= 8;+ result |= 0xc000;+ break;+ }++ if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) {+ value >>= 16;+ result |= 0xd000;+ break;+ }++ if (result != 0)+ return ~(sljit_ins)0;++ value ^= (sljit_uw)0xffffffff;+ result = (1 << 29);+ }+ break;+ default:+ return ~(sljit_ins)0;+ }++ return (((sljit_ins)value & 0x1f) << 5) | (((sljit_ins)value & 0xe0) << 11) | result;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins, imm;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (src & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));++ ins = (sljit_ins)elem_size << 10;++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 30;++ return push_inst(compiler, LD1R | ins | RN(src) | VT(freg));+ }++ ins = (sljit_ins)1 << (16 + elem_size);++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 30;++ if (type & SLJIT_SIMD_FLOAT) {+ if (src == SLJIT_IMM)+ return push_inst(compiler, MOVI | (ins & ((sljit_ins)1 << 30)) | VD(freg));++ return push_inst(compiler, DUP_e | ins | VD(freg) | VN(src));+ }++ if (src == SLJIT_IMM) {+ if (elem_size < 3)+ srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;++ imm = simd_get_imm(elem_size, (sljit_uw)srcw);++ if (imm != ~(sljit_ins)0) {+ imm |= ins & ((sljit_ins)1 << 30);++ return push_inst(compiler, MOVI | imm | VD(freg));+ }++ FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));+ src = TMP_REG2;+ }++ return push_inst(compiler, DUP_g | ins | VD(freg) | RN(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (type & SLJIT_SIMD_LANE_ZERO) {+ ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 30);++ if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) {+ FAIL_IF(push_inst(compiler, ORR_v | ins | VD(TMP_FREG1) | VN(freg) | VM(freg)));+ srcdst = TMP_FREG1;+ srcdstw = 0;+ }++ FAIL_IF(push_inst(compiler, MOVI | ins | VD(freg)));+ }++ if (srcdst & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));++ if (elem_size == 3)+ ins = 0x8400;+ else if (elem_size == 0)+ ins = 0;+ else+ ins = (sljit_ins)0x2000 << elem_size;++ lane_index = lane_index << elem_size;+ ins |= (sljit_ins)(((lane_index & 0x8) << 27) | ((lane_index & 0x7) << 10));++ return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? ST1_s : LD1_s) | ins | RN(srcdst) | VT(freg));+ }++ if (type & SLJIT_SIMD_FLOAT) {+ if (type & SLJIT_SIMD_STORE)+ ins = INS_e | ((sljit_ins)1 << (16 + elem_size)) | ((sljit_ins)lane_index << (11 + elem_size)) | VD(srcdst) | VN(freg);+ else+ ins = INS_e | ((((sljit_ins)lane_index << 1) | 1) << (16 + elem_size)) | VD(freg) | VN(srcdst);++ return push_inst(compiler, ins);+ }++ if (srcdst == SLJIT_IMM) {+ if (elem_size < 3)+ srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;++ FAIL_IF(load_immediate(compiler, TMP_REG2, srcdstw));+ srcdst = TMP_REG2;+ }++ if (type & SLJIT_SIMD_STORE) {+ ins = RD(srcdst) | VN(freg);++ if ((type & SLJIT_SIMD_LANE_SIGNED) && (elem_size < 2 || (elem_size == 2 && !(type & SLJIT_32)))) {+ ins |= SMOV;++ if (!(type & SLJIT_32))+ ins |= (sljit_ins)1 << 30;+ } else+ ins |= UMOV;+ } else+ ins = INS | VD(freg) | RN(srcdst);++ if (elem_size == 3)+ ins |= (sljit_ins)1 << 30;++ return push_inst(compiler, ins | ((((sljit_ins)lane_index << 1) | 1) << (16 + elem_size)));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_s32 src_lane_index)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index));++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ ins = (((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size);++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 30;++ return push_inst(compiler, DUP_e | ins | VD(freg) | VN(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (src & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));++ if (reg_size == 4 && elem2_size - elem_size == 1)+ FAIL_IF(push_inst(compiler, LD1 | ((sljit_ins)elem_size << 10) | RN(src) | VT(freg)));+ else+ FAIL_IF(push_inst(compiler, LD1_s | ((sljit_ins)0x2000 << (reg_size - elem2_size + elem_size)) | RN(src) | VT(freg)));+ src = freg;+ }++ if (type & SLJIT_SIMD_FLOAT) {+ SLJIT_ASSERT(reg_size == 4);+ return push_inst(compiler, FCVTL | (1 << 22) | VD(freg) | VN(src));+ }++ do {+ FAIL_IF(push_inst(compiler, ((type & SLJIT_SIMD_EXTEND_SIGNED) ? SSHLL : USHLL)+ | ((sljit_ins)1 << (19 + elem_size)) | VD(freg) | VN(src)));+ src = freg;+ } while (++elem_size < elem2_size);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins, imms;+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw));++ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ switch (elem_size) {+ case 0:+ imms = 0x643219;+ ins = USHR | (0x9 << 16);+ break;+ case 1:+ imms = (reg_size == 4) ? 0x643219 : 0x6231;+ ins = USHR | (0x11 << 16);+ break;+ case 2:+ imms = (reg_size == 4) ? 0x6231 : 0x61;+ ins = USHR | (0x21 << 16);+ break;+ default:+ imms = 0x61;+ ins = USHR | (0x41 << 16);+ break;+ }++ if (reg_size == 4)+ ins |= (1 << 30);++ FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG1) | VN(freg)));++ if (reg_size == 4 && elem_size > 0)+ FAIL_IF(push_inst(compiler, XTN | ((sljit_ins)(elem_size - 1) << 22) | VD(TMP_FREG1) | VN(TMP_FREG1)));++ if (imms >= 0x100) {+ ins = (reg_size == 4 && elem_size == 0) ? (1 << 30) : 0;++ do {+ FAIL_IF(push_inst(compiler, USRA | ins | ((imms & 0xff) << 16) | VD(TMP_FREG1) | VN(TMP_FREG1)));+ imms >>= 8;+ } while (imms >= 0x100);+ }++ FAIL_IF(push_inst(compiler, USRA | (1 << 30) | (imms << 16) | VD(TMP_FREG1) | VN(TMP_FREG1)));++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ ins = (0x1 << 16);++ if (reg_size == 4 && elem_size == 0) {+ FAIL_IF(push_inst(compiler, INS_e | (0x3 << 16) | (0x8 << 11) | VD(TMP_FREG1) | VN(TMP_FREG1)));+ ins = (0x2 << 16);+ }++ FAIL_IF(push_inst(compiler, UMOV | ins | RD(dst_r) | VN(TMP_FREG1)));++ if (dst_r == TMP_REG2)+ return emit_op_mem(compiler, STORE | ((type & SLJIT_32) ? INT_SIZE : WORD_SIZE), TMP_REG2, dst, dstw, TMP_REG1);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg));++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ switch (SLJIT_SIMD_GET_OPCODE(type)) {+ case SLJIT_SIMD_OP2_AND:+ ins = AND_v;+ break;+ case SLJIT_SIMD_OP2_OR:+ ins = ORR_v;+ break;+ case SLJIT_SIMD_OP2_XOR:+ ins = EOR_v;+ break;+ }++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 30;++ return push_inst(compiler, ins | VD(dst_freg) | VN(src1_freg) | VM(src2_freg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 mem_reg)+{+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));++#ifdef __ARM_FEATURE_ATOMICS+ switch (GET_OPCODE(op)) {+ case SLJIT_MOV32:+ case SLJIT_MOV_U32:+ ins = LDR ^ (1 << 30);+ break;+ case SLJIT_MOV_U16:+ ins = LDRH;+ break;+ case SLJIT_MOV_U8:+ ins = LDRB;+ break;+ default:+ ins = LDR;+ break;+ }+#else /* !__ARM_FEATURE_ATOMICS */+ switch (GET_OPCODE(op)) {+ case SLJIT_MOV32:+ case SLJIT_MOV_U32:+ ins = LDXR ^ (1 << 30);+ break;+ case SLJIT_MOV_U8:+ ins = LDXRB;+ break;+ case SLJIT_MOV_U16:+ ins = LDXRH;+ break;+ default:+ ins = LDXR;+ break;+ }+#endif /* ARM_FEATURE_ATOMICS */+ return push_inst(compiler, ins | RN(mem_reg) | RT(dst_reg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src_reg,+ sljit_s32 mem_reg,+ sljit_s32 temp_reg)+{+ sljit_ins ins;+ sljit_s32 tmp = temp_reg;+ sljit_ins cmp = 0;+ sljit_ins inv_bits = W_OP;++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));++#ifdef __ARM_FEATURE_ATOMICS+ if (op & SLJIT_SET_ATOMIC_STORED)+ cmp = (SUBS ^ W_OP) | RD(TMP_ZERO);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV32:+ case SLJIT_MOV_U32:+ ins = CAS ^ (1 << 30);+ break;+ case SLJIT_MOV_U16:+ ins = CASH;+ break;+ case SLJIT_MOV_U8:+ ins = CASB;+ break;+ default:+ ins = CAS;+ inv_bits = 0;+ if (cmp)+ cmp ^= W_OP;+ break;+ }++ if (cmp) {+ FAIL_IF(push_inst(compiler, (MOV ^ inv_bits) | RM(temp_reg) | RD(TMP_REG1)));+ tmp = TMP_REG1;+ }+ FAIL_IF(push_inst(compiler, ins | RM(tmp) | RN(mem_reg) | RD(src_reg)));+ if (!cmp)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, cmp | RM(tmp) | RN(temp_reg)));+ FAIL_IF(push_inst(compiler, (CSET ^ inv_bits) | RD(tmp)));+ return push_inst(compiler, cmp | RM(tmp) | RN(TMP_ZERO));+#else /* !__ARM_FEATURE_ATOMICS */+ SLJIT_UNUSED_ARG(tmp);+ SLJIT_UNUSED_ARG(inv_bits);++ if (op & SLJIT_SET_ATOMIC_STORED)+ cmp = (SUBI ^ W_OP) | (1 << 29);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV32:+ case SLJIT_MOV_U32:+ ins = STXR ^ (1 << 30);+ break;+ case SLJIT_MOV_U8:+ ins = STXRB;+ break;+ case SLJIT_MOV_U16:+ ins = STXRH;+ break;+ default:+ ins = STXR;+ break;+ }++ FAIL_IF(push_inst(compiler, ins | RM(TMP_REG1) | RN(mem_reg) | RT(src_reg)));+ return cmp ? push_inst(compiler, cmp | RD(TMP_ZERO) | RN(TMP_REG1)) : SLJIT_SUCCESS;+#endif /* __ARM_FEATURE_ATOMICS */+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)+{+ sljit_s32 dst_reg;+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));+ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);++ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ /* Not all instruction forms support accessing SP register. */+ if (offset <= 0xffffff && offset >= -0xffffff) {+ ins = ADDI;+ if (offset < 0) {+ offset = -offset;+ ins = SUBI;+ }++ if (offset <= 0xfff)+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)(offset << 10)));+ else {+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)((offset & 0xfff000) >> (12 - 10)) | (1 << 22)));++ offset &= 0xfff;+ if (offset != 0)+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (sljit_ins)(offset << 10)));+ }+ }+ else {+ FAIL_IF(load_immediate (compiler, dst_reg, offset));+ /* Add extended register form. */+ FAIL_IF(push_inst(compiler, ADDE | (0x3 << 13) | RD(dst_reg) | RN(SLJIT_SP) | RM(dst_reg)));+ }++ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, (sljit_uw)init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ PTR_FAIL_IF(push_inst(compiler, RD(dst_r)));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 1);++ compiler->size += 3;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));++ return jump; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
src/c/pcre2/src/sljit/sljitNativeARM_T2_32.c view
@@ -49,2591 +49,4239 @@ 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15 }; -static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {- 0, 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7-};--#define COPY_BITS(src, from, to, bits) \- ((from >= to ? ((sljit_ins)(src) >> (from - to)) : ((sljit_ins)(src) << (to - from))) & (((1 << bits) - 1) << to))--#define NEGATE(uimm) ((sljit_uw)-(sljit_sw)(uimm))--/* Thumb16 encodings. */-#define RD3(rd) ((sljit_ins)reg_map[rd])-#define RN3(rn) ((sljit_ins)reg_map[rn] << 3)-#define RM3(rm) ((sljit_ins)reg_map[rm] << 6)-#define RDN3(rdn) ((sljit_ins)reg_map[rdn] << 8)-#define IMM3(imm) ((sljit_ins)imm << 6)-#define IMM8(imm) ((sljit_ins)imm)--/* Thumb16 helpers. */-#define SET_REGS44(rd, rn) \- (((sljit_ins)reg_map[rn] << 3) | ((sljit_ins)reg_map[rd] & 0x7) | (((sljit_ins)reg_map[rd] & 0x8) << 4))-#define IS_2_LO_REGS(reg1, reg2) \- (reg_map[reg1] <= 7 && reg_map[reg2] <= 7)-#define IS_3_LO_REGS(reg1, reg2, reg3) \- (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7)--/* Thumb32 encodings. */-#define RD4(rd) ((sljit_ins)reg_map[rd] << 8)-#define RN4(rn) ((sljit_ins)reg_map[rn] << 16)-#define RM4(rm) ((sljit_ins)reg_map[rm])-#define RT4(rt) ((sljit_ins)reg_map[rt] << 12)-#define DD4(dd) ((sljit_ins)freg_map[dd] << 12)-#define DN4(dn) ((sljit_ins)freg_map[dn] << 16)-#define DM4(dm) ((sljit_ins)freg_map[dm])-#define IMM5(imm) \- (COPY_BITS(imm, 2, 12, 3) | (((sljit_ins)imm & 0x3) << 6))-#define IMM12(imm) \- (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | ((sljit_ins)imm & 0xff))--/* --------------------------------------------------------------------- */-/* Instrucion forms */-/* --------------------------------------------------------------------- */--/* dot '.' changed to _- I immediate form (possibly followed by number of immediate bits). */-#define ADCI 0xf1400000-#define ADCS 0x4140-#define ADC_W 0xeb400000-#define ADD 0x4400-#define ADDS 0x1800-#define ADDSI3 0x1c00-#define ADDSI8 0x3000-#define ADD_W 0xeb000000-#define ADDWI 0xf2000000-#define ADD_SP 0x4485-#define ADD_SP_I 0xb000-#define ADD_W 0xeb000000-#define ADD_WI 0xf1000000-#define ANDI 0xf0000000-#define ANDS 0x4000-#define AND_W 0xea000000-#define ASRS 0x4100-#define ASRSI 0x1000-#define ASR_W 0xfa40f000-#define ASR_WI 0xea4f0020-#define BCC 0xd000-#define BICI 0xf0200000-#define BKPT 0xbe00-#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-#define EOR_W 0xea800000-#define IT 0xbf00-#define LDR_SP 0x9800-#define LDR 0xf8d00000-#define LDRI 0xf8500800-#define LSLS 0x4080-#define LSLSI 0x0000-#define LSL_W 0xfa00f000-#define LSL_WI 0xea4f0000-#define LSRS 0x40c0-#define LSRSI 0x0800-#define LSR_W 0xfa20f000-#define LSR_WI 0xea4f0010-#define MOV 0x4600-#define MOVS 0x0000-#define MOVSI 0x2000-#define MOVT 0xf2c00000-#define MOVW 0xf2400000-#define MOV_W 0xea4f0000-#define MOV_WI 0xf04f0000-#define MUL 0xfb00f000-#define MVNS 0x43c0-#define MVN_W 0xea6f0000-#define MVN_WI 0xf06f0000-#define NOP 0xbf00-#define ORNI 0xf0600000-#define ORRI 0xf0400000-#define ORRS 0x4300-#define ORR_W 0xea400000-#define POP 0xbc00-#define POP_W 0xe8bd0000-#define PUSH 0xb400-#define PUSH_W 0xe92d0000-#define RSB_WI 0xf1c00000-#define RSBSI 0x4240-#define SBCI 0xf1600000-#define SBCS 0x4180-#define SBC_W 0xeb600000-#define SDIV 0xfb90f0f0-#define SMULL 0xfb800000-#define STR_SP 0x9000-#define SUBS 0x1a00-#define SUBSI3 0x1e00-#define SUBSI8 0x3800-#define SUB_W 0xeba00000-#define SUBWI 0xf2a00000-#define SUB_SP_I 0xb080-#define SUB_WI 0xf1a00000-#define SXTB 0xb240-#define SXTB_W 0xfa4ff080-#define SXTH 0xb200-#define SXTH_W 0xfa0ff080-#define TST 0x4200-#define TSTI 0xf0000f00-#define TST_W 0xea000f00-#define UDIV 0xfbb0f0f0-#define UMULL 0xfba00000-#define UXTB 0xb2c0-#define UXTB_W 0xfa5ff080-#define UXTH 0xb280-#define UXTH_W 0xfa1ff080-#define VABS_F32 0xeeb00ac0-#define VADD_F32 0xee300a00-#define VCMP_F32 0xeeb40a40-#define VCVT_F32_S32 0xeeb80ac0-#define VCVT_F64_F32 0xeeb70ac0-#define VCVT_S32_F32 0xeebd0ac0-#define VDIV_F32 0xee800a00-#define VLDR_F32 0xed100a00-#define VMOV_F32 0xeeb00a40-#define VMOV 0xee000a10-#define VMOV2 0xec400a10-#define VMRS 0xeef1fa10-#define VMUL_F32 0xee200a00-#define VNEG_F32 0xeeb10a40-#define VPOP 0xecbd0b00-#define VPUSH 0xed2d0b00-#define VSTR_F32 0xed000a00-#define VSUB_F32 0xee300a40--static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_ins inst)-{- sljit_u16 *ptr;- SLJIT_ASSERT(!(inst & 0xffff0000));-- ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16));- FAIL_IF(!ptr);- *ptr = (sljit_u16)(inst);- compiler->size++;- return SLJIT_SUCCESS;-}--static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst)-{- sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins));- FAIL_IF(!ptr);- *ptr++ = (sljit_u16)(inst >> 16);- *ptr = (sljit_u16)(inst);- compiler->size += 2;- return SLJIT_SUCCESS;-}--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)));- return push_inst32(compiler, MOVT | RD4(dst)- | 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_u16 *inst, sljit_uw new_imm)-{- sljit_ins dst = inst[1] & 0x0f00;- SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));- inst[0] = (sljit_u16)((MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1));- inst[1] = (sljit_u16)(dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff));- inst[2] = (sljit_u16)((MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1));- inst[3] = (sljit_u16)(dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16));-}--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;-- if (jump->flags & SLJIT_REWRITABLE_JUMP)- return 0;-- if (jump->flags & JUMP_ADDR) {- /* 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) - executable_offset) >> 1;- }- else {- SLJIT_ASSERT(jump->flags & JUMP_LABEL);- diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)) >> 1;- }-- if (jump->flags & IS_COND) {- SLJIT_ASSERT(!(jump->flags & IS_BL));- if (diff <= 127 && diff >= -128) {- jump->flags |= PATCH_TYPE1;- return 5;- }- if (diff <= 524287 && diff >= -524288) {- jump->flags |= PATCH_TYPE2;- return 4;- }- /* +1 comes from the prefix IT instruction. */- diff--;- if (diff <= 8388607 && diff >= -8388608) {- jump->flags |= PATCH_TYPE3;- return 3;- }- }- else if (jump->flags & IS_BL) {- if (diff <= 8388607 && diff >= -8388608) {- jump->flags |= PATCH_BL;- return 3;- }- }- else {- if (diff <= 1023 && diff >= -1024) {- jump->flags |= PATCH_TYPE4;- return 4;- }- if (diff <= 8388607 && diff >= -8388608) {- jump->flags |= PATCH_TYPE5;- return 3;- }- }-- return 0;-}--static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw executable_offset)-{- sljit_s32 type = (jump->flags >> 4) & 0xf;- sljit_sw diff;- sljit_u16 *jump_inst;- sljit_s32 s, j1, j2;-- if (SLJIT_UNLIKELY(type == 0)) {- 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 + sizeof(sljit_u32)) - executable_offset) >> 1;- }- 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:- /* Encoding T1 of 'B' instruction */- SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_COND));- jump_inst[0] = (sljit_u16)(0xd000 | (jump->flags & 0xf00) | ((sljit_ins)diff & 0xff));- return;- case 2:- /* Encoding T3 of 'B' instruction */- SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_COND));- jump_inst[0] = (sljit_u16)(0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1));- jump_inst[1] = (sljit_u16)(0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | ((sljit_ins)diff & 0x7ff));- return;- case 3:- SLJIT_ASSERT(jump->flags & IS_COND);- *jump_inst++ = (sljit_u16)(IT | ((jump->flags >> 4) & 0xf0) | 0x8);- diff--;- type = 5;- break;- case 4:- /* Encoding T2 of 'B' instruction */- SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_COND));- jump_inst[0] = (sljit_u16)(0xe000 | (diff & 0x7ff));- return;- }-- SLJIT_ASSERT(diff <= 8388607 && diff >= -8388608);-- /* Really complex instruction form for branches. */- s = (diff >> 23) & 0x1;- j1 = (~(diff >> 22) ^ s) & 0x1;- j2 = (~(diff >> 21) ^ s) & 0x1;- jump_inst[0] = (sljit_u16)(0xf000 | ((sljit_ins)s << 10) | COPY_BITS(diff, 11, 0, 10));- jump_inst[1] = (sljit_u16)((j1 << 13) | (j2 << 11) | (diff & 0x7ff));-- /* The others have a common form. */- if (type == 5) /* Encoding T4 of 'B' instruction */- jump_inst[1] |= 0x9000;- else if (type == 6) /* Encoding T1 of 'BL' instruction */- jump_inst[1] |= 0xd000;- else- SLJIT_UNREACHABLE();-}--SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)-{- struct sljit_memory_fragment *buf;- sljit_u16 *code;- sljit_u16 *code_ptr;- sljit_u16 *buf_ptr;- sljit_u16 *buf_end;- sljit_uw half_count;- sljit_uw next_addr;- sljit_sw executable_offset;-- struct sljit_label *label;- struct sljit_jump *jump;- struct sljit_const *const_;- struct sljit_put_label *put_label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_generate_code(compiler));- reverse_buf(compiler);-- code = (sljit_u16*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_u16), compiler->exec_allocator_data);- PTR_FAIL_WITH_EXEC_IF(code);- buf = compiler->buf;-- code_ptr = code;- half_count = 0;- next_addr = 0;- executable_offset = SLJIT_EXEC_OFFSET(code);-- label = compiler->labels;- jump = compiler->jumps;- const_ = compiler->consts;- put_label = compiler->put_labels;-- do {- buf_ptr = (sljit_u16*)buf->memory;- buf_end = buf_ptr + (buf->used_size >> 1);- do {- *code_ptr = *buf_ptr++;- if (next_addr == half_count) {- SLJIT_ASSERT(!label || label->size >= half_count);- SLJIT_ASSERT(!jump || jump->addr >= half_count);- SLJIT_ASSERT(!const_ || const_->addr >= half_count);- SLJIT_ASSERT(!put_label || put_label->addr >= half_count);-- /* These structures are ordered by their address. */- if (label && label->size == half_count) {- label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }- if (jump && jump->addr == half_count) {- jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);- code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);- jump = jump->next;- }- if (const_ && const_->addr == half_count) {- const_->addr = (sljit_uw)code_ptr;- const_ = const_->next;- }- if (put_label && put_label->addr == half_count) {- SLJIT_ASSERT(put_label->label);- put_label->addr = (sljit_uw)code_ptr;- put_label = put_label->next;- }- next_addr = compute_next_addr(label, jump, const_, put_label);- }- code_ptr ++;- half_count ++;- } while (buf_ptr < buf_end);-- buf = buf->next;- } while (buf);-- if (label && label->size == half_count) {- label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }-- SLJIT_ASSERT(!label);- SLJIT_ASSERT(!jump);- SLJIT_ASSERT(!const_);- SLJIT_ASSERT(!put_label);- SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);-- jump = compiler->jumps;- while (jump) {- set_jump_instruction(jump, executable_offset);- jump = jump->next;- }-- put_label = compiler->put_labels;- while (put_label) {- modify_imm32_const((sljit_u16 *)put_label->addr, put_label->label->addr);- put_label = put_label->next;- }-- compiler->error = SLJIT_ERR_COMPILED;- compiler->executable_offset = executable_offset;- compiler->executable_size = (sljit_uw)(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);- SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);-- /* 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_CLZ:- case SLJIT_HAS_CMOV:- case SLJIT_HAS_PREFETCH:- return 1;-- default:- return 0;- }-}--/* --------------------------------------------------------------------- */-/* Core code generator functions. */-/* --------------------------------------------------------------------- */--#define INVALID_IMM 0x80000000-static sljit_uw get_imm(sljit_uw imm)-{- /* Thumb immediate form. */- sljit_s32 counter;-- if (imm <= 0xff)- return imm;-- if ((imm & 0xffff) == (imm >> 16)) {- /* Some special cases. */- if (!(imm & 0xff00))- return (1 << 12) | (imm & 0xff);- if (!(imm & 0xff))- return (2 << 12) | ((imm >> 8) & 0xff);- if ((imm & 0xff00) == ((imm & 0xff) << 8))- return (3 << 12) | (imm & 0xff);- }-- /* Assembly optimization: count leading zeroes? */- counter = 8;- if (!(imm & 0xffff0000)) {- counter += 16;- imm <<= 16;- }- if (!(imm & 0xff000000)) {- counter += 8;- imm <<= 8;- }- if (!(imm & 0xf0000000)) {- counter += 4;- imm <<= 4;- }- if (!(imm & 0xc0000000)) {- counter += 2;- imm <<= 2;- }- if (!(imm & 0x80000000)) {- counter += 1;- imm <<= 1;- }- /* Since imm >= 128, this must be true. */- SLJIT_ASSERT(counter <= 31);-- if (imm & 0x00ffffff)- return INVALID_IMM; /* Cannot be encoded. */-- return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1);-}--static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)-{- sljit_uw tmp;-- /* MOVS cannot be used since it destroy flags. */-- if (imm >= 0x10000) {- tmp = get_imm(imm);- if (tmp != INVALID_IMM)- return push_inst32(compiler, MOV_WI | RD4(dst) | tmp);- tmp = get_imm(~imm);- if (tmp != INVALID_IMM)- return push_inst32(compiler, MVN_WI | RD4(dst) | tmp);- }-- /* set low 16 bits, set hi 16 bits to 0. */- 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)));-- /* set hi 16 bit if needed. */- if (imm >= 0x10000)- return push_inst32(compiler, MOVT | RD4(dst)- | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));- return SLJIT_SUCCESS;-}--#define ARG1_IMM 0x0010000-#define ARG2_IMM 0x0020000-/* 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--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, 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, no temporaries are used. */- flags &= ~ARG1_IMM;- FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));- arg1 = TMP_REG1;- }-- if (flags & (ARG1_IMM | ARG2_IMM)) {- reg = (sljit_s32)((flags & ARG2_IMM) ? arg1 : arg2);- imm = (flags & ARG2_IMM) ? arg2 : arg1;-- switch (flags & 0xffff) {- case SLJIT_CLZ:- case SLJIT_MUL:- /* No form with immediate operand. */- break;- case SLJIT_MOV:- SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG2);- return load_immediate(compiler, dst, imm);- case SLJIT_NOT:- if (!(flags & SET_FLAGS))- return load_immediate(compiler, dst, ~imm);- /* Since the flags should be set, we just fallback to the register mode.- Although some clever things could be done here, "NOT IMM" does not worth the efforts. */- break;- case SLJIT_ADD:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- nimm = NEGATE(imm);- if (IS_2_LO_REGS(reg, dst)) {- if (imm <= 0x7)- return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));- if (nimm <= 0x7)- return push_inst16(compiler, SUBSI3 | IMM3(nimm) | RD3(dst) | RN3(reg));- if (reg == dst) {- if (imm <= 0xff)- return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst));- if (nimm <= 0xff)- return push_inst16(compiler, SUBSI8 | IMM8(nimm) | RDN3(dst));- }- }- if (!(flags & SET_FLAGS)) {- if (imm <= 0xfff)- return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm));- if (nimm <= 0xfff)- return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm));- }- 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(NEGATE(imm));- if (nimm != INVALID_IMM)- return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);- break;- case SLJIT_ADDC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- imm = get_imm(imm);- if (imm != INVALID_IMM)- return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);- break;- case SLJIT_SUB:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- if (flags & ARG1_IMM) {- 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(NEGATE(imm));- if (nimm != INVALID_IMM)- return push_inst32(compiler, CMNI_W | RN4(reg) | nimm);- break;- }- nimm = NEGATE(imm);- if (IS_2_LO_REGS(reg, dst)) {- if (imm <= 0x7)- return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));- if (nimm <= 0x7)- return push_inst16(compiler, ADDSI3 | IMM3(nimm) | RD3(dst) | RN3(reg));- if (reg == dst) {- if (imm <= 0xff)- return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));- if (nimm <= 0xff)- return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst));- }- }- if (!(flags & SET_FLAGS)) {- if (imm <= 0xfff)- return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));- if (nimm <= 0xfff)- return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm));- }- 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(NEGATE(imm));- if (nimm != INVALID_IMM)- return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);- break;- case SLJIT_SUBC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- if (flags & ARG1_IMM)- break;- imm = get_imm(imm);- if (imm != INVALID_IMM)- return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);- break;- case SLJIT_AND:- nimm = get_imm(imm);- if (nimm != INVALID_IMM)- return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TSTI : ANDI) | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);- imm = get_imm(~imm);- if (imm != INVALID_IMM)- return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);- break;- case SLJIT_OR:- nimm = get_imm(imm);- if (nimm != INVALID_IMM)- return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);- imm = get_imm(~imm);- if (imm != INVALID_IMM)- return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);- break;- case SLJIT_XOR:- imm = get_imm(imm);- if (imm != INVALID_IMM)- return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);- break;- case SLJIT_SHL:- case SLJIT_LSHR:- case SLJIT_ASHR:- if (flags & ARG1_IMM)- break;- imm &= 0x1f;- if (imm == 0) {- if (!(flags & SET_FLAGS))- return push_inst16(compiler, MOV | SET_REGS44(dst, reg));- if (IS_2_LO_REGS(dst, reg))- return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));- return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));- }- switch (flags & 0xffff) {- case SLJIT_SHL:- 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 (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 (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_UNREACHABLE();- break;- }-- if (flags & ARG2_IMM) {- imm = arg2;- arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;- FAIL_IF(load_immediate(compiler, (sljit_s32)arg2, imm));- }- else {- imm = arg1;- arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1;- FAIL_IF(load_immediate(compiler, (sljit_s32)arg1, imm));- }-- SLJIT_ASSERT(arg1 != arg2);- }-- /* Both arguments are registers. */- switch (flags & 0xffff) {- case SLJIT_MOV:- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:- case SLJIT_MOV_P:- SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);- if (dst == (sljit_s32)arg2)- return SLJIT_SUCCESS;- return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));- case SLJIT_MOV_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_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_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_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_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_REG2);- FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)));- return SLJIT_SUCCESS;- case SLJIT_ADD:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- if (IS_3_LO_REGS(dst, arg1, arg2))- return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2));- if (dst == (sljit_s32)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:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- if (dst == (sljit_s32)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:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- 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:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- if (dst == (sljit_s32)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:- compiler->status_flags_state = 0;- if (!(flags & SET_FLAGS))- return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2));- 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 (dst == (sljit_s32)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, ((flags & UNUSED_RETURN) ? TST_W : AND_W) | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));- case SLJIT_OR:- if (dst == (sljit_s32)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 == (sljit_s32)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 == (sljit_s32)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 == (sljit_s32)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 == (sljit_s32)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_UNREACHABLE();- return SLJIT_SUCCESS;-}--#define STORE 0x01-#define SIGNED 0x02--#define WORD_SIZE 0x00-#define BYTE_SIZE 0x04-#define HALF_SIZE 0x08-#define PRELOAD 0x0c--#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE)))-#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift)))--/*- 1st letter:- w = word- b = byte- h = half-- 2nd letter:- s = signed- u = unsigned-- 3rd letter:- l = load- s = store-*/--static const sljit_ins sljit_mem16[12] = {-/* w u l */ 0x5800 /* ldr */,-/* w u s */ 0x5000 /* str */,-/* w s l */ 0x5800 /* ldr */,-/* w s s */ 0x5000 /* str */,--/* b u l */ 0x5c00 /* ldrb */,-/* b u s */ 0x5400 /* strb */,-/* b s l */ 0x5600 /* ldrsb */,-/* b s s */ 0x5400 /* strb */,--/* h u l */ 0x5a00 /* ldrh */,-/* h u s */ 0x5200 /* strh */,-/* h s l */ 0x5e00 /* ldrsh */,-/* h s s */ 0x5200 /* strh */,-};--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 */,-/* w s s */ 0x6000 /* str imm5 */,--/* b u l */ 0x7800 /* ldrb imm5 */,-/* b u s */ 0x7000 /* strb imm5 */,-/* b s l */ 0x0000 /* not allowed */,-/* b s s */ 0x7000 /* strb imm5 */,--/* h u l */ 0x8800 /* ldrh imm5 */,-/* h u s */ 0x8000 /* strh imm5 */,-/* h s l */ 0x0000 /* not allowed */,-/* h s s */ 0x8000 /* strh imm5 */,-};--#define MEM_IMM8 0xc00-#define MEM_IMM12 0x800000-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 */,-/* w s s */ 0xf8400000 /* str.w */,--/* b u l */ 0xf8100000 /* ldrb.w */,-/* b u s */ 0xf8000000 /* strb.w */,-/* b s l */ 0xf9100000 /* ldrsb.w */,-/* b s s */ 0xf8000000 /* strb.w */,--/* h u l */ 0xf8300000 /* ldrh.w */,-/* 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_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value)-{- sljit_uw imm;-- if (value >= 0) {- if (value <= 0xfff)- return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(value));- imm = get_imm((sljit_uw)value);- if (imm != INVALID_IMM)- return push_inst32(compiler, ADD_WI | RD4(dst) | RN4(reg) | imm);- }- else {- value = -value;- if (value <= 0xfff)- return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(value));- imm = get_imm((sljit_uw)value);- if (imm != INVALID_IMM)- return push_inst32(compiler, SUB_WI | RD4(dst) | RN4(reg) | imm);- }- return SLJIT_ERR_UNSUPPORTED;-}--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_s32 other_r;- sljit_uw tmp;-- SLJIT_ASSERT(arg & SLJIT_MEM);- SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);- arg &= ~SLJIT_MEM;-- if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {- tmp = get_imm((sljit_uw)argw & ~(sljit_uw)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, (sljit_uw)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(arg & OFFS_REG_MASK)) {- argw &= 0x3;- other_r = OFFS_REG(arg);- arg &= 0xf;-- if (!argw && IS_3_LO_REGS(reg, arg, other_r))- 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) | ((sljit_ins)argw << 4));- }-- if (argw > 0xfff) {- tmp = get_imm((sljit_uw)argw & ~(sljit_uw)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((sljit_uw)-argw & ~(sljit_uw)0xff);- if (tmp != INVALID_IMM) {- push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp);- arg = tmp_reg;- argw = -(-argw & 0xff);- }- }-- if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {- tmp = 3;- if (IS_WORD_SIZE(flags)) {- if (OFFSET_CHECK(0x1f, 2))- tmp = 2;- }- else if (flags & BYTE_SIZE)- {- if (OFFSET_CHECK(0x1f, 0))- tmp = 0;- }- else {- SLJIT_ASSERT(flags & HALF_SIZE);- if (OFFSET_CHECK(0x1f, 1))- tmp = 1;- }-- if (tmp < 3)- return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | ((sljit_ins)argw << (6 - tmp)));- }- 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 | (sljit_ins)((flags & STORE) ? 0 : 0x800) | RDN3(reg) | ((sljit_ins)argw >> 2));- }-- if (argw >= 0 && argw <= 0xfff)- return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | (sljit_ins)argw);- else if (argw < 0 && argw >= -0xff)- return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | (sljit_ins)-argw);-- SLJIT_ASSERT(arg != tmp_reg);-- FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)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_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 size, i, tmp, word_arg_count, saved_arg_count;- sljit_uw offset;- sljit_uw imm = 0;-#ifdef __SOFTFP__- sljit_u32 float_arg_count;-#else- sljit_u32 old_offset, f32_offset;- sljit_u32 remap[3];- sljit_u32 *remap_ptr = remap;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- tmp = SLJIT_S0 - saveds;- for (i = SLJIT_S0; i > tmp; i--)- imm |= (sljit_uw)1 << reg_map[i];-- for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)- imm |= (sljit_uw)1 << reg_map[i];-- /* At least two registers must be set for PUSH_W and one for PUSH instruction. */- FAIL_IF((imm & 0xff00)- ? push_inst32(compiler, PUSH_W | (1 << 14) | imm)- : push_inst16(compiler, PUSH | (1 << 8) | imm));-- /* Stack must be aligned to 8 bytes: (LR, R4) */- size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);-- if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {- if ((size & SSIZE_OF(sw)) != 0) {- FAIL_IF(push_inst16(compiler, SUB_SP_I | (sizeof(sljit_sw) >> 2)));- size += SSIZE_OF(sw);- }-- if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {- FAIL_IF(push_inst32(compiler, VPUSH | DD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));- } else {- if (fsaveds > 0)- FAIL_IF(push_inst32(compiler, VPUSH | DD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));- if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)- FAIL_IF(push_inst32(compiler, VPUSH | DD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));- }- }-- local_size = ((size + local_size + 0x7) & ~0x7) - size;- compiler->local_size = local_size;-- arg_types >>= SLJIT_ARG_SHIFT;- word_arg_count = 0;- saved_arg_count = 0;-#ifdef __SOFTFP__- SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);-- offset = 0;- float_arg_count = 0;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (offset & 0x7)- offset += sizeof(sljit_sw);-- if (offset < 4 * sizeof(sljit_sw))- FAIL_IF(push_inst32(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));- else- FAIL_IF(push_inst32(compiler, VLDR_F32 | 0x800100 | RN4(SLJIT_SP)- | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));- float_arg_count++;- offset += sizeof(sljit_f64) - sizeof(sljit_sw);- break;- case SLJIT_ARG_TYPE_F32:- if (offset < 4 * sizeof(sljit_sw))- FAIL_IF(push_inst32(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));- else- FAIL_IF(push_inst32(compiler, VLDR_F32 | 0x800000 | RN4(SLJIT_SP)- | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));- float_arg_count++;- break;- default:- word_arg_count++;-- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- tmp = SLJIT_S0 - saved_arg_count;- saved_arg_count++;- } else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))- tmp = word_arg_count;- else- break;-- SLJIT_ASSERT(reg_map[tmp] <= 7);-- if (offset < 4 * sizeof(sljit_sw))- FAIL_IF(push_inst16(compiler, MOV | RD3(tmp) | (offset << 1)));- else- FAIL_IF(push_inst16(compiler, LDR_SP | RDN3(tmp)- | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));- break;- }-- offset += sizeof(sljit_sw);- arg_types >>= SLJIT_ARG_SHIFT;- }-- compiler->args_size = offset;-#else- offset = SLJIT_FR0;- old_offset = SLJIT_FR0;- f32_offset = 0;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (offset != old_offset)- *remap_ptr++ = VMOV_F32 | SLJIT_32 | DD4(offset) | DM4(old_offset);- old_offset++;- offset++;- break;- case SLJIT_ARG_TYPE_F32:- if (f32_offset != 0) {- *remap_ptr++ = VMOV_F32 | 0x20 | DD4(offset) | DM4(f32_offset);- f32_offset = 0;- } else {- if (offset != old_offset)- *remap_ptr++ = VMOV_F32 | DD4(offset) | DM4(old_offset);- f32_offset = old_offset;- old_offset++;- }- offset++;- break;- default:- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0 - saved_arg_count, SLJIT_R0 + word_arg_count)));- saved_arg_count++;- }-- word_arg_count++;- break;- }- arg_types >>= SLJIT_ARG_SHIFT;- }-- SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));-- while (remap_ptr > remap)- FAIL_IF(push_inst32(compiler, *(--remap_ptr)));-#endif--#ifdef _WIN32- if (local_size >= 4096) {- imm = get_imm(4096);- SLJIT_ASSERT(imm != INVALID_IMM);-- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));-- if (local_size < 4 * 4096) {- if (local_size > 2 * 4096) {- if (local_size > 3 * 4096) {- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));- }-- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));- }- } else {- FAIL_IF(load_immediate(compiler, TMP_REG2, ((sljit_uw)local_size >> 12) - 1));- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));- FAIL_IF(push_inst32(compiler, SUB_WI | SET_FLAGS | RD4(TMP_REG2) | RN4(TMP_REG2) | 1));- FAIL_IF(push_inst16(compiler, BCC | (0x1 << 8) /* not-equal */ | (-8 & 0xff)));- }-- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));- local_size &= 0xfff;- }-- if (local_size >= 256) {- SLJIT_ASSERT(local_size < 4096);-- if (local_size <= (127 << 2))- FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)local_size >> 2)));- else- FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, (sljit_uw)local_size));-- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));- } else if (local_size > 0)- FAIL_IF(push_inst32(compiler, LDRI | 0x500 | RT4(TMP_REG1) | RN4(SLJIT_SP) | (sljit_uw)local_size));-#else /* !_WIN32 */- if (local_size > 0) {- if (local_size <= (127 << 2))- FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)local_size >> 2)));- else- FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, (sljit_uw)local_size));- }-#endif /* _WIN32 */-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 size;-- CHECK_ERROR();- CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);-- if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))- size += SSIZE_OF(sw);-- compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;- return SLJIT_SUCCESS;-}--static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)-{- sljit_uw imm2;-- /* The TMP_REG1 register must keep its value. */- if (imm <= (127u << 2))- return push_inst16(compiler, ADD_SP_I | (imm >> 2));-- if (imm <= 0xfff)- return push_inst32(compiler, ADDWI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | IMM12(imm));-- imm2 = get_imm(imm);-- if (imm2 != INVALID_IMM)- return push_inst32(compiler, ADD_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm2);-- FAIL_IF(load_immediate(compiler, TMP_REG2, imm));- return push_inst16(compiler, ADD_SP | RN3(TMP_REG2));-}--static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)-{- sljit_s32 local_size, fscratches, fsaveds, i, tmp;- sljit_s32 lr_dst = TMP_PC;- sljit_uw reg_list;-- SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128);-- local_size = compiler->local_size;- fscratches = compiler->fscratches;- fsaveds = compiler->fsaveds;-- if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {- if (local_size > 0)- FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));-- if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {- FAIL_IF(push_inst32(compiler, VPOP | DD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));- } else {- if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)- FAIL_IF(push_inst32(compiler, VPOP | DD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));- if (fsaveds > 0)- FAIL_IF(push_inst32(compiler, VPOP | DD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));- }-- local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;- }-- if (frame_size < 0) {- lr_dst = TMP_REG2;- frame_size = 0;- } else if (frame_size > 0)- lr_dst = 0;-- reg_list = 0;- tmp = SLJIT_S0 - compiler->saveds;- for (i = SLJIT_S0; i > tmp; i--)- reg_list |= (sljit_uw)1 << reg_map[i];-- for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)- reg_list |= (sljit_uw)1 << reg_map[i];-- if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {- /* The local_size does not include the saved registers. */- local_size += SSIZE_OF(sw);-- if (reg_list != 0)- local_size += SSIZE_OF(sw);-- if (frame_size > local_size)- FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)(frame_size - local_size) >> 2)));- else if (frame_size < local_size)- FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));-- if (reg_list == 0)- return SLJIT_SUCCESS;-- if (compiler->saveds > 0) {- SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_S0]));- lr_dst = SLJIT_S0;- } else {- SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_FIRST_SAVED_REG]));- lr_dst = SLJIT_FIRST_SAVED_REG;- }-- frame_size -= 2 * SSIZE_OF(sw);-- if (reg_map[lr_dst] <= 7)- return push_inst16(compiler, STR_SP | 0x800 | RDN3(lr_dst) | (sljit_uw)(frame_size >> 2));-- return push_inst32(compiler, LDR | RT4(lr_dst) | RN4(SLJIT_SP) | (sljit_uw)frame_size);- }-- if (local_size > 0)- FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));-- if (!(reg_list & 0xff00) && lr_dst != TMP_REG2) {- if (lr_dst == TMP_PC)- reg_list |= 1u << 8;-- /* At least one register must be set for POP instruction. */- SLJIT_ASSERT(reg_list != 0);-- FAIL_IF(push_inst16(compiler, POP | reg_list));- } else {- if (lr_dst != 0) {- if (reg_list == 0)- return push_inst32(compiler, 0xf85d0b04 | RT4(lr_dst));-- reg_list |= (sljit_uw)1 << reg_map[lr_dst];- }-- /* At least two registers must be set for POP_W instruction. */- SLJIT_ASSERT((reg_list & (reg_list - 1)) != 0);-- FAIL_IF(push_inst32(compiler, POP_W | reg_list));- }-- if (frame_size > 0)- return push_inst16(compiler, SUB_SP_I | (((sljit_uw)frame_size - sizeof(sljit_sw)) >> 2));- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)-{- CHECK_ERROR();- CHECK(check_sljit_emit_return_void(compiler));-- return emit_stack_frame_release(compiler, 0);-}--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)--#ifdef __cplusplus-extern "C" {-#endif--#ifdef _WIN32-extern unsigned long long __rt_udiv(unsigned int denominator, unsigned int numerator);-extern long long __rt_sdiv(int denominator, int numerator);-#elif defined(__GNUC__)-extern unsigned int __aeabi_uidivmod(unsigned int numerator, int unsigned denominator);-extern int __aeabi_idivmod(int numerator, int denominator);-#else-#error "Software divmod functions are needed"-#endif--#ifdef __cplusplus-}-#endif--#endif /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)-{-#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)- sljit_uw saved_reg_list[3];- sljit_uw saved_reg_count;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_op0(compiler, op));-- op = GET_OPCODE(op);- switch (op) {- case SLJIT_BREAKPOINT:- return push_inst16(compiler, BKPT);- case SLJIT_NOP:- return push_inst16(compiler, NOP);- case SLJIT_LMUL_UW:- case SLJIT_LMUL_SW:- return push_inst32(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)- | RD4(SLJIT_R1) | RT4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1));-#if (defined __ARM_FEATURE_IDIV) || (defined __ARM_ARCH_EXT_IDIV__)- case SLJIT_DIVMOD_UW:- case SLJIT_DIVMOD_SW:- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));- FAIL_IF(push_inst32(compiler, (op == SLJIT_DIVMOD_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));- FAIL_IF(push_inst32(compiler, MUL | RD4(SLJIT_R1) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));- return push_inst32(compiler, SUB_W | RD4(SLJIT_R1) | RN4(TMP_REG1) | RM4(SLJIT_R1));- case SLJIT_DIV_UW:- case SLJIT_DIV_SW:- return push_inst32(compiler, (op == SLJIT_DIV_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1));-#else /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */- 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_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8)- | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));- if (saved_reg_count >= 2) {- SLJIT_ASSERT(saved_reg_list[1] < 8);- FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */));- }- if (saved_reg_count >= 3) {- SLJIT_ASSERT(saved_reg_list[2] < 8);- FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */));- }- }--#ifdef _WIN32- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R0, SLJIT_R1)));- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R1, TMP_REG1)));- FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,- ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__rt_udiv) : SLJIT_FUNC_ADDR(__rt_sdiv))));-#elif defined(__GNUC__)- FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,- ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));-#else-#error "Software divmod functions are needed"-#endif-- if (saved_reg_count > 0) {- if (saved_reg_count >= 3) {- SLJIT_ASSERT(saved_reg_list[2] < 8);- FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */));- }- if (saved_reg_count >= 2) {- SLJIT_ASSERT(saved_reg_list[1] < 8);- FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */));- }- return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8)- | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);- }- return SLJIT_SUCCESS;-#endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */- case SLJIT_ENDBR:- case SLJIT_SKIP_FRAMES_BEFORE_RETURN:- return SLJIT_SUCCESS;- }-- return SLJIT_SUCCESS;-}--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_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);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;-- op = GET_OPCODE(op);- if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {- switch (op) {- case SLJIT_MOV:- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:- case SLJIT_MOV_P:- flags = WORD_SIZE;- break;- case SLJIT_MOV_U8:- flags = BYTE_SIZE;- if (src & SLJIT_IMM)- srcw = (sljit_u8)srcw;- break;- case SLJIT_MOV_S8:- flags = BYTE_SIZE | SIGNED;- if (src & SLJIT_IMM)- srcw = (sljit_s8)srcw;- break;- case SLJIT_MOV_U16:- flags = HALF_SIZE;- if (src & SLJIT_IMM)- srcw = (sljit_u16)srcw;- break;- case SLJIT_MOV_S16:- flags = HALF_SIZE | SIGNED;- if (src & SLJIT_IMM)- srcw = (sljit_s16)srcw;- break;- default:- SLJIT_UNREACHABLE();- flags = 0;- break;- }-- if (src & SLJIT_IMM)- FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, (sljit_uw)srcw));- else if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1));- } else {- if (dst_r != TMP_REG1)- return emit_op_imm(compiler, op, dst_r, TMP_REG2, (sljit_uw)src);- dst_r = src;- }-- if (!(dst & SLJIT_MEM))- return SLJIT_SUCCESS;-- return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);- }-- flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;-- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));- src = TMP_REG1;- }-- emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, (sljit_uw)src);-- if (SLJIT_UNLIKELY(dst & SLJIT_MEM))- return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);- return SLJIT_SUCCESS;-}--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_s32 dst_reg, flags, src2_reg;-- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;- flags = HAS_FLAGS(op) ? SET_FLAGS : 0;-- if (dst == TMP_REG1)- flags |= UNUSED_RETURN;-- 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;-- emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, (sljit_uw)src1w, (sljit_uw)src2w);-- 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_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 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_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- switch (op) {- case SLJIT_FAST_RETURN:- SLJIT_ASSERT(reg_map[TMP_REG2] == 14);-- if (FAST_IS_REG(src))- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));- else- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));-- return push_inst16(compiler, BX | RN3(TMP_REG2));- case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:- return SLJIT_SUCCESS;- case SLJIT_PREFETCH_L1:- case SLJIT_PREFETCH_L2:- case SLJIT_PREFETCH_L3:- case SLJIT_PREFETCH_ONCE:- return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1);- }-- return SLJIT_SUCCESS;-}--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_s32 sljit_get_float_register_index(sljit_s32 reg)-{- CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));- return (freg_map[reg] << 1);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_custom(compiler, instruction, size));-- if (size == 2)- return push_inst16(compiler, *(sljit_u16*)instruction);- return push_inst32(compiler, *(sljit_ins*)instruction);-}--/* --------------------------------------------------------------------- */-/* Floating point operators */-/* --------------------------------------------------------------------- */--#define FPU_LOAD (1 << 20)--static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)-{- sljit_uw imm;- sljit_ins inst = VSTR_F32 | (flags & (SLJIT_32 | 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_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | (((sljit_uw)argw & 0x3) << 6)));- arg = SLJIT_MEM | TMP_REG1;- argw = 0;- }-- if ((arg & REG_MASK) && (argw & 0x3) == 0) {- if (!(argw & ~0x3fc))- return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | DD4(reg) | ((sljit_uw)argw >> 2));- if (!(-argw & ~0x3fc))- return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | ((sljit_uw)-argw >> 2));- }-- if (arg & REG_MASK) {- if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {- FAIL_IF(compiler->error);- return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));- }-- imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);- if (imm != INVALID_IMM) {- FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));- return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2));- }-- imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);- if (imm != INVALID_IMM) {- argw = -argw;- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));- return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2));- }- }-- FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));- if (arg & REG_MASK)- 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_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_32;-- if (src & SLJIT_MEM) {- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));- src = TMP_FREG1;- }-- FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_32) | DD4(TMP_FREG1) | DM4(src)));-- if (FAST_IS_REG(dst))- return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1));-- /* Store the integer value from a VFP register. */- return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);-}--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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- op ^= SLJIT_32;-- if (FAST_IS_REG(src))- FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1)));- else if (src & SLJIT_MEM) {- /* Load the integer value into a VFP register. */- FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));- }- else {- FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));- FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | DN4(TMP_FREG1)));- }-- FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_32) | DD4(dst_r) | DM4(TMP_FREG1)));-- if (dst & SLJIT_MEM)- return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);- return SLJIT_SUCCESS;-}--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_32;-- if (src1 & SLJIT_MEM) {- emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w);- src1 = TMP_FREG1;- }-- if (src2 & SLJIT_MEM) {- emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w);- src2 = TMP_FREG2;- }-- FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_32) | DD4(src1) | DM4(src2)));- return push_inst32(compiler, VMRS);-}--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_s32 dst_r;-- CHECK_ERROR();-- SLJIT_COMPILE_ASSERT((SLJIT_32 == 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_32;-- if (src & SLJIT_MEM) {- emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw);- src = dst_r;- }-- switch (GET_OPCODE(op)) {- case SLJIT_MOV_F64:- if (src != dst_r) {- if (dst_r != TMP_FREG1)- FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src)));- else- dst_r = src;- }- break;- case SLJIT_NEG_F64:- FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src)));- break;- case SLJIT_ABS_F64:- FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src)));- break;- case SLJIT_CONV_F64_FROM_F32:- FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src)));- op ^= SLJIT_32;- break;- }-- if (dst & SLJIT_MEM)- return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);- return SLJIT_SUCCESS;-}--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_s32 dst_r;-- CHECK_ERROR();- CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- op ^= SLJIT_32;-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;- if (src1 & SLJIT_MEM) {- emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w);- src1 = TMP_FREG1;- }- if (src2 & SLJIT_MEM) {- emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w);- src2 = TMP_FREG2;- }-- switch (GET_OPCODE(op)) {- case SLJIT_ADD_F64:- FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2)));- break;- case SLJIT_SUB_F64:- FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2)));- break;- case SLJIT_MUL_F64:- FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2)));- break;- case SLJIT_DIV_F64:- FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2)));- break;- }-- if (!(dst & SLJIT_MEM))- return SLJIT_SUCCESS;- return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);-}--#undef FPU_LOAD--/* --------------------------------------------------------------------- */-/* Other instructions */-/* --------------------------------------------------------------------- */--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);-- SLJIT_ASSERT(reg_map[TMP_REG2] == 14);-- if (FAST_IS_REG(dst))- return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2));-- /* Memory. */- return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1);-}--/* --------------------------------------------------------------------- */-/* Conditional instructions */-/* --------------------------------------------------------------------- */--static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)-{- switch (type) {- case SLJIT_EQUAL:- case SLJIT_EQUAL_F64:- return 0x0;-- case SLJIT_NOT_EQUAL:- case SLJIT_NOT_EQUAL_F64:- return 0x1;-- case SLJIT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)- return 0x2;- /* fallthrough */-- case SLJIT_LESS:- case SLJIT_LESS_F64:- return 0x3;-- case SLJIT_NOT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)- return 0x3;- /* fallthrough */-- case SLJIT_GREATER_EQUAL:- case SLJIT_GREATER_EQUAL_F64:- return 0x2;-- case SLJIT_GREATER:- case SLJIT_GREATER_F64:- return 0x8;-- case SLJIT_LESS_EQUAL:- case SLJIT_LESS_EQUAL_F64:- return 0x9;-- case SLJIT_SIG_LESS:- return 0xb;-- case SLJIT_SIG_GREATER_EQUAL:- return 0xa;-- case SLJIT_SIG_GREATER:- return 0xc;-- case SLJIT_SIG_LESS_EQUAL:- return 0xd;-- case SLJIT_OVERFLOW:- if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))- return 0x1;- /* fallthrough */-- case SLJIT_UNORDERED_F64:- return 0x6;-- case SLJIT_NOT_OVERFLOW:- if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))- return 0x0;- /* fallthrough */-- case SLJIT_ORDERED_F64:- return 0x7;-- default: /* SLJIT_JUMP */- SLJIT_UNREACHABLE();- return 0xe;- }-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)-{- struct sljit_label *label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_label(compiler));-- if (compiler->last_label && compiler->last_label->size == compiler->size)- return compiler->last_label;-- label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));- PTR_FAIL_IF(!label);- set_label(label, compiler);- return label;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)-{- struct sljit_jump *jump;- sljit_ins cc;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_jump(compiler, type));-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);- type &= 0xff;-- PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));- if (type < SLJIT_JUMP) {- jump->flags |= IS_COND;- cc = get_cc(compiler, type);- jump->flags |= cc << 8;- PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));- }-- jump->addr = compiler->size;- if (type <= SLJIT_JUMP)- PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG1)));- else {- jump->flags |= IS_BL;- PTR_FAIL_IF(push_inst16(compiler, BLX | RN3(TMP_REG1)));- }-- return jump;-}--#ifdef __SOFTFP__--static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)-{- sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;- sljit_u32 offset = 0;- sljit_u32 word_arg_offset = 0;- sljit_u32 float_arg_count = 0;- sljit_s32 types = 0;- sljit_u32 src_offset = 4 * sizeof(sljit_sw);- sljit_u8 offsets[4];- sljit_u8 *offset_ptr = offsets;-- if (src && FAST_IS_REG(*src))- src_offset = (sljit_u32)reg_map[*src] * sizeof(sljit_sw);-- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types) {- types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);-- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (offset & 0x7)- offset += sizeof(sljit_sw);- *offset_ptr++ = (sljit_u8)offset;- offset += sizeof(sljit_f64);- float_arg_count++;- break;- case SLJIT_ARG_TYPE_F32:- *offset_ptr++ = (sljit_u8)offset;- offset += sizeof(sljit_f32);- float_arg_count++;- break;- default:- *offset_ptr++ = (sljit_u8)offset;- offset += sizeof(sljit_sw);- word_arg_offset += sizeof(sljit_sw);- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {- /* Keep lr register on the stack. */- if (is_tail_call)- offset += sizeof(sljit_sw);-- offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_uw)0x7;-- *extra_space = offset;-- if (is_tail_call)- FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));- else- FAIL_IF(push_inst16(compiler, SUB_SP_I | (offset >> 2)));- } else {- if (is_tail_call)- FAIL_IF(emit_stack_frame_release(compiler, -1));- *extra_space = 0;- }-- SLJIT_ASSERT(reg_map[TMP_REG1] == 12);-- /* Process arguments in reversed direction. */- while (types) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- float_arg_count--;- offset = *(--offset_ptr);-- SLJIT_ASSERT((offset & 0x7) == 0);-- if (offset < 4 * sizeof(sljit_sw)) {- if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {- FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));- *src = TMP_REG1;- }- FAIL_IF(push_inst32(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));- } else- FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800100 | RN4(SLJIT_SP)- | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));- break;- case SLJIT_ARG_TYPE_F32:- float_arg_count--;- offset = *(--offset_ptr);-- if (offset < 4 * sizeof(sljit_sw)) {- if (src_offset == offset) {- FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));- *src = TMP_REG1;- }- FAIL_IF(push_inst32(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));- } else- FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800000 | RN4(SLJIT_SP)- | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));- break;- default:- word_arg_offset -= sizeof(sljit_sw);- offset = *(--offset_ptr);-- SLJIT_ASSERT(offset >= word_arg_offset);-- if (offset != word_arg_offset) {- if (offset < 4 * sizeof(sljit_sw)) {- if (src_offset == offset) {- FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));- *src = TMP_REG1;- }- else if (src_offset == word_arg_offset) {- *src = (sljit_s32)(1 + (offset >> 2));- src_offset = offset;- }- FAIL_IF(push_inst16(compiler, MOV | (offset >> 2) | (word_arg_offset << 1)));- } else- FAIL_IF(push_inst16(compiler, STR_SP | (word_arg_offset << 6) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));- }- break;- }-- types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)-{- if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)- FAIL_IF(push_inst32(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));- if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)- FAIL_IF(push_inst32(compiler, VMOV | (0 << 16) | (0 << 12)));-- return SLJIT_SUCCESS;-}--#else--static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)-{- sljit_u32 offset = SLJIT_FR0;- sljit_u32 new_offset = SLJIT_FR0;- sljit_u32 f32_offset = 0;-- /* Remove return value. */- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (offset != new_offset)- FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_32 | DD4(new_offset) | DM4(offset)));-- new_offset++;- offset++;- break;- case SLJIT_ARG_TYPE_F32:- if (f32_offset != 0) {- FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | DD4(f32_offset) | DM4(offset)));- f32_offset = 0;- } else {- if (offset != new_offset)- FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | DD4(new_offset) | DM4(offset)));- f32_offset = new_offset;- new_offset++;- }- offset++;- break;- }- arg_types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--#endif--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types)-{-#ifdef __SOFTFP__- struct sljit_jump *jump;- sljit_u32 extra_space = (sljit_u32)type;-#endif-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));--#ifdef __SOFTFP__- PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));- SLJIT_ASSERT((extra_space & 0x7) == 0);-- if ((type & SLJIT_CALL_RETURN) && extra_space == 0)- type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- jump = sljit_emit_jump(compiler, type);- PTR_FAIL_IF(jump == NULL);-- if (extra_space > 0) {- if (type & SLJIT_CALL_RETURN)- PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)- | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));-- PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));-- if (type & SLJIT_CALL_RETURN) {- PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2)));- return jump;- }- }-- SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));- PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));- return jump;-#else- if (type & SLJIT_CALL_RETURN) {- /* ldmia sp!, {..., lr} */- PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));- type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);- }-- PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_jump(compiler, type);-#endif-}--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;-- CHECK_ERROR();- CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- SLJIT_ASSERT(reg_map[TMP_REG1] != 14);-- if (!(src & SLJIT_IMM)) {- if (FAST_IS_REG(src)) {- SLJIT_ASSERT(reg_map[src] != 14);- 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, TMP_REG1));- if (type >= SLJIT_FAST_CALL)- return push_inst16(compiler, BLX | RN3(TMP_REG1));- }-- /* These jumps are converted to jump/call instructions when possible. */- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- FAIL_IF(!jump);- set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));- jump->u.target = (sljit_uw)srcw;-- FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));- jump->addr = compiler->size;- return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{-#ifdef __SOFTFP__- sljit_u32 extra_space = (sljit_u32)type;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));-- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));- src = TMP_REG1;- }-- if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) {- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src)));- src = TMP_REG1;- }--#ifdef __SOFTFP__- FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));- SLJIT_ASSERT((extra_space & 0x7) == 0);-- if ((type & SLJIT_CALL_RETURN) && extra_space == 0)- type = SLJIT_JUMP;--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));-- if (extra_space > 0) {- if (type & SLJIT_CALL_RETURN)- FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)- | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));-- FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));-- if (type & SLJIT_CALL_RETURN)- return push_inst16(compiler, BX | RN3(TMP_REG2));- }-- SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));- return softfloat_post_call_with_args(compiler, arg_types);-#else /* !__SOFTFP__ */- if (type & SLJIT_CALL_RETURN) {- /* ldmia sp!, {..., lr} */- FAIL_IF(emit_stack_frame_release(compiler, -1));- type = SLJIT_JUMP;- }-- FAIL_IF(hardfloat_call_with_args(compiler, arg_types));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_ijump(compiler, type, src, srcw);-#endif /* __SOFTFP__ */-}--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_s32 dst_r, flags = GET_ALL_FLAGS(op);- sljit_ins cc;-- CHECK_ERROR();- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));- ADJUST_LOCAL_OFFSET(dst, dstw);-- op = GET_OPCODE(op);- cc = get_cc(compiler, type & 0xff);- 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));- if (reg_map[dst_r] > 7) {- 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 & SLJIT_MEM))- return SLJIT_SUCCESS;- return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2);- }-- 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, ((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. */- 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_32;-- cc = get_cc(compiler, 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));- }-- 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));- }-- tmp = get_imm((sljit_uw)srcw);- if (tmp != INVALID_IMM) {- FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));- return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);- }-- tmp = get_imm(~(sljit_uw)srcw);- if (tmp != INVALID_IMM) {- FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));- return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);- }-- FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4));-- 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 sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 reg,- sljit_s32 mem, sljit_sw memw)-{- sljit_s32 flags;- sljit_ins inst;-- CHECK_ERROR();- CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));-- if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255))- return SLJIT_ERR_UNSUPPORTED;-- if (type & SLJIT_MEM_SUPP)- return SLJIT_SUCCESS;-- switch (type & 0xff) {- case SLJIT_MOV:- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:- case SLJIT_MOV_P:- flags = WORD_SIZE;- break;- case SLJIT_MOV_U8:- flags = BYTE_SIZE;- break;- case SLJIT_MOV_S8:- flags = BYTE_SIZE | SIGNED;- break;- case SLJIT_MOV_U16:- flags = HALF_SIZE;- break;- case SLJIT_MOV_S16:- flags = HALF_SIZE | SIGNED;- break;- default:- SLJIT_UNREACHABLE();- flags = WORD_SIZE;- break;- }-- if (type & SLJIT_MEM_STORE)- flags |= STORE;-- inst = sljit_mem32[flags] | 0x900;-- if (type & SLJIT_MEM_PRE)- inst |= 0x400;-- if (memw >= 0)- inst |= 0x200;- else- memw = -memw;-- return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | (sljit_ins)memw);-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)-{- struct sljit_const *const_;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));- ADJUST_LOCAL_OFFSET(dst, dstw);-- const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));- PTR_FAIL_IF(!const_);- set_const(const_, compiler);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;- PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, (sljit_uw)init_value));-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));- return const_;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- struct sljit_put_label *put_label;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);-- put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));- PTR_FAIL_IF(!put_label);- set_put_label(put_label, compiler, 0);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;- PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, 0));-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));- return put_label;+static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {+ 0,+ 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,+ 7, 6,+ 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,+ 7, 6+};++static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {+ 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1+};++#define COPY_BITS(src, from, to, bits) \+ ((from >= to ? ((sljit_ins)(src) >> (from - to)) : ((sljit_ins)(src) << (to - from))) & (((1 << bits) - 1) << to))++#define NEGATE(uimm) ((sljit_uw)-(sljit_sw)(uimm))++/* Thumb16 encodings. */+#define RD3(rd) ((sljit_ins)reg_map[rd])+#define RN3(rn) ((sljit_ins)reg_map[rn] << 3)+#define RM3(rm) ((sljit_ins)reg_map[rm] << 6)+#define RDN3(rdn) ((sljit_ins)reg_map[rdn] << 8)+#define IMM3(imm) ((sljit_ins)imm << 6)+#define IMM8(imm) ((sljit_ins)imm)++/* Thumb16 helpers. */+#define SET_REGS44(rd, rn) \+ (((sljit_ins)reg_map[rn] << 3) | ((sljit_ins)reg_map[rd] & 0x7) | (((sljit_ins)reg_map[rd] & 0x8) << 4))+#define IS_2_LO_REGS(reg1, reg2) \+ (reg_map[reg1] <= 7 && reg_map[reg2] <= 7)+#define IS_3_LO_REGS(reg1, reg2, reg3) \+ (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7)++/* Thumb32 encodings. */+#define RM4(rm) ((sljit_ins)reg_map[rm])+#define RD4(rd) ((sljit_ins)reg_map[rd] << 8)+#define RT4(rt) ((sljit_ins)reg_map[rt] << 12)+#define RN4(rn) ((sljit_ins)reg_map[rn] << 16)++#define VM4(vm) (((sljit_ins)freg_map[vm]) | ((sljit_ins)freg_ebit_map[vm] << 5))+#define VD4(vd) (((sljit_ins)freg_map[vd] << 12) | ((sljit_ins)freg_ebit_map[vd] << 22))+#define VN4(vn) (((sljit_ins)freg_map[vn] << 16) | ((sljit_ins)freg_ebit_map[vn] << 7))++#define IMM5(imm) \+ (COPY_BITS(imm, 2, 12, 3) | (((sljit_ins)imm & 0x3) << 6))+#define IMM12(imm) \+ (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | ((sljit_ins)imm & 0xff))++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++/* dot '.' changed to _+ I immediate form (possibly followed by number of immediate bits). */+#define ADCI 0xf1400000+#define ADCS 0x4140+#define ADC_W 0xeb400000+#define ADD 0x4400+#define ADDS 0x1800+#define ADDSI3 0x1c00+#define ADDSI8 0x3000+#define ADDWI 0xf2000000+#define ADD_SP 0x4485+#define ADD_SP_I 0xb000+#define ADD_W 0xeb000000+#define ADD_WI 0xf1000000+#define ANDI 0xf0000000+#define ANDS 0x4000+#define AND_W 0xea000000+#define ASRS 0x4100+#define ASRSI 0x1000+#define ASR_W 0xfa40f000+#define ASR_WI 0xea4f0020+#define BCC 0xd000+#define BICI 0xf0200000+#define BKPT 0xbe00+#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+#define EOR_W 0xea800000+#define IT 0xbf00+#define LDR 0xf8d00000+#define LDR_SP 0x9800+#define LDRD 0xe9500000+#define LDREX 0xe8500f00+#define LDREXB 0xe8d00f4f+#define LDREXH 0xe8d00f5f+#define LDRI 0xf8500800+#define LSLS 0x4080+#define LSLSI 0x0000+#define LSL_W 0xfa00f000+#define LSL_WI 0xea4f0000+#define LSRS 0x40c0+#define LSRSI 0x0800+#define LSR_W 0xfa20f000+#define LSR_WI 0xea4f0010+#define MLA 0xfb000000+#define MOV 0x4600+#define MOVS 0x0000+#define MOVSI 0x2000+#define MOVT 0xf2c00000+#define MOVW 0xf2400000+#define MOV_W 0xea4f0000+#define MOV_WI 0xf04f0000+#define MUL 0xfb00f000+#define MVNS 0x43c0+#define MVN_W 0xea6f0000+#define MVN_WI 0xf06f0000+#define NOP 0xbf00+#define ORNI 0xf0600000+#define ORRI 0xf0400000+#define ORRS 0x4300+#define ORR_W 0xea400000+#define POP 0xbc00+#define POP_W 0xe8bd0000+#define PUSH 0xb400+#define PUSH_W 0xe92d0000+#define REV 0xba00+#define REV_W 0xfa90f080+#define REV16 0xba40+#define REV16_W 0xfa90f090+#define RBIT 0xfa90f0a0+#define RORS 0x41c0+#define ROR_W 0xfa60f000+#define ROR_WI 0xea4f0030+#define RSB_WI 0xf1c00000+#define RSBSI 0x4240+#define SBCI 0xf1600000+#define SBCS 0x4180+#define SBC_W 0xeb600000+#define SDIV 0xfb90f0f0+#define SMULL 0xfb800000+#define STR_SP 0x9000+#define STRD 0xe9400000+#define STREX 0xe8400000+#define STREXB 0xe8c00f40+#define STREXH 0xe8c00f50+#define SUBS 0x1a00+#define SUBSI3 0x1e00+#define SUBSI8 0x3800+#define SUB_W 0xeba00000+#define SUBWI 0xf2a00000+#define SUB_SP_I 0xb080+#define SUB_WI 0xf1a00000+#define SXTB 0xb240+#define SXTB_W 0xfa4ff080+#define SXTH 0xb200+#define SXTH_W 0xfa0ff080+#define TST 0x4200+#define TSTI 0xf0000f00+#define TST_W 0xea000f00+#define UDIV 0xfbb0f0f0+#define UMULL 0xfba00000+#define UXTB 0xb2c0+#define UXTB_W 0xfa5ff080+#define UXTH 0xb280+#define UXTH_W 0xfa1ff080+#define VABS_F32 0xeeb00ac0+#define VADD_F32 0xee300a00+#define VAND 0xef000110+#define VCMP_F32 0xeeb40a40+#define VCVT_F32_S32 0xeeb80ac0+#define VCVT_F32_U32 0xeeb80a40+#define VCVT_F64_F32 0xeeb70ac0+#define VCVT_S32_F32 0xeebd0ac0+#define VDIV_F32 0xee800a00+#define VDUP 0xee800b10+#define VDUP_s 0xffb00c00+#define VEOR 0xff000110+#define VLD1 0xf9200000+#define VLD1_r 0xf9a00c00+#define VLD1_s 0xf9a00000+#define VLDR_F32 0xed100a00+#define VMOV_F32 0xeeb00a40+#define VMOV 0xee000a10+#define VMOV2 0xec400a10+#define VMOV_i 0xef800010+#define VMOV_s 0xee000b10+#define VMOVN 0xffb20200+#define VMRS 0xeef1fa10+#define VMUL_F32 0xee200a00+#define VNEG_F32 0xeeb10a40+#define VORR 0xef200110+#define VPOP 0xecbd0b00+#define VPUSH 0xed2d0b00+#define VSHLL 0xef800a10+#define VSHR 0xef800010+#define VSRA 0xef800110+#define VST1 0xf9000000+#define VST1_s 0xf9800000+#define VSTR_F32 0xed000a00+#define VSUB_F32 0xee300a40++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)++static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)+{+ if (compiler->scratches == -1)+ return 0;++ if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))+ fr -= SLJIT_F64_SECOND(0);++ return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches))+ || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0)+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));+}++#endif /* SLJIT_ARGUMENT_CHECKS */++static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_ins inst)+{+ sljit_u16 *ptr;+ SLJIT_ASSERT(!(inst & 0xffff0000));++ ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16));+ FAIL_IF(!ptr);+ *ptr = (sljit_u16)(inst);+ compiler->size++;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst)+{+ sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ *ptr++ = (sljit_u16)(inst >> 16);+ *ptr = (sljit_u16)(inst);+ compiler->size += 2;+ return SLJIT_SUCCESS;+}++static 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)));+ return push_inst32(compiler, MOVT | RD4(dst)+ | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));+}++/* Dst must be in bits[11-8] */+static void set_imm32_const(sljit_u16 *inst, sljit_ins dst, sljit_uw new_imm)+{+ inst[0] = (sljit_u16)((MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1));+ inst[1] = (sljit_u16)(dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff));+ inst[2] = (sljit_u16)((MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1));+ inst[3] = (sljit_u16)(dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16));+}++static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm)+{+ sljit_ins dst = inst[1] & 0x0f00;+ SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));+ set_imm32_const(inst, dst, new_imm);+}++static SLJIT_INLINE sljit_u16* detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)+{+ sljit_sw diff;++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ goto exit;++ if (jump->flags & JUMP_ADDR) {+ /* Branch to ARM code is not optimized yet. */+ if (!(jump->u.target & 0x1))+ goto exit;+ diff = (sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset;+ } else {+ SLJIT_ASSERT(jump->u.label != NULL);+ diff = (sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2);+ }++ if (jump->flags & IS_COND) {+ SLJIT_ASSERT(!(jump->flags & IS_BL));+ /* Size of the prefix IT instruction. */+ diff += SSIZE_OF(u16);+ if (diff <= 0xff && diff >= -0x100) {+ jump->flags |= PATCH_TYPE1;+ jump->addr = (sljit_uw)(code_ptr - 1);+ return code_ptr - 1;+ }+ if (diff <= 0xfffff && diff >= -0x100000) {+ jump->flags |= PATCH_TYPE2;+ jump->addr = (sljit_uw)(code_ptr - 1);+ return code_ptr;+ }+ diff -= SSIZE_OF(u16);+ } else if (jump->flags & IS_BL) {+ /* Branch and link. */+ if (diff <= 0xffffff && diff >= -0x1000000) {+ jump->flags |= PATCH_TYPE5;+ return code_ptr + 1;+ }+ goto exit;+ } else if (diff <= 0x7ff && diff >= -0x800) {+ jump->flags |= PATCH_TYPE3;+ return code_ptr;+ }++ if (diff <= 0xffffff && diff >= -0x1000000) {+ jump->flags |= PATCH_TYPE4;+ return code_ptr + 1;+ }++exit:+ code_ptr[4] = code_ptr[0];++ if (jump->flags & IS_COND) {+ code_ptr[3] = code_ptr[-1];+ jump->addr = (sljit_uw)(code_ptr - 1);+ }++ return code_ptr + 4;+}++static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)+{+ sljit_uw addr;+ sljit_sw diff;+ SLJIT_UNUSED_ARG(executable_offset);++ if (jump->flags & JUMP_ADDR)+ addr = jump->u.target;+ else+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ /* The pc+4 offset is represented by the 2 * SSIZE_OF(sljit_u16) below. */+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ /* Note: ADR with imm8 does not set the last bit (Thumb2 flag). */++ if (diff <= 0xffd + 2 * SSIZE_OF(u16) && diff >= -0xfff + 2 * SSIZE_OF(u16)) {+ jump->flags |= PATCH_TYPE6;+ return 1;+ }++ return 3;+}++static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)+{+ sljit_s32 type = (jump->flags >> 4) & 0xf;+ sljit_u16 *jump_inst = (sljit_u16*)jump->addr;+ sljit_sw diff;+ sljit_ins ins;++ diff = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr);++ if (SLJIT_UNLIKELY(type == 0)) {+ ins = (jump->flags & JUMP_MOV_ADDR) ? *jump_inst : RDN3(TMP_REG1);+ set_imm32_const((sljit_u16*)jump->addr, ins, (sljit_uw)diff);+ return;+ }++ if (SLJIT_UNLIKELY(type == 6)) {+ SLJIT_ASSERT(jump->flags & JUMP_MOV_ADDR);+ diff -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_inst + 2, executable_offset) & ~(sljit_sw)0x3;++ SLJIT_ASSERT(diff <= 0xfff && diff >= -0xfff);++ ins = ADDWI >> 16;+ if (diff <= 0) {+ diff = -diff;+ ins = SUBWI >> 16;+ }++ jump_inst[1] = (sljit_u16)(jump_inst[0] | COPY_BITS(diff, 8, 12, 3) | (diff & 0xff));+ jump_inst[0] = (sljit_u16)(ins | 0xf | COPY_BITS(diff, 11, 10, 1));+ return;+ }++ SLJIT_ASSERT((diff & 0x1) != 0 && !(jump->flags & JUMP_MOV_ADDR));+ diff = (diff - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1;++ switch (type) {+ case 1:+ /* Encoding T1 of 'B' instruction */+ SLJIT_ASSERT(diff <= 0x7f && diff >= -0x80 && (jump->flags & IS_COND));+ jump_inst[0] = (sljit_u16)(0xd000 | (jump->flags & 0xf00) | ((sljit_ins)diff & 0xff));+ return;+ case 2:+ /* Encoding T3 of 'B' instruction */+ SLJIT_ASSERT(diff <= 0x7ffff && diff >= -0x80000 && (jump->flags & IS_COND));+ jump_inst[0] = (sljit_u16)(0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1));+ jump_inst[1] = (sljit_u16)(0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | ((sljit_ins)diff & 0x7ff));+ return;+ case 3:+ /* Encoding T2 of 'B' instruction */+ SLJIT_ASSERT(diff <= 0x3ff && diff >= -0x400 && !(jump->flags & IS_COND));+ jump_inst[0] = (sljit_u16)(0xe000 | (diff & 0x7ff));+ return;+ }++ SLJIT_ASSERT(diff <= 0x7fffff && diff >= -0x800000);++ /* Really complex instruction form for branches. Negate with sign bit. */+ diff ^= ((diff >> 2) & 0x600000) ^ 0x600000;++ jump_inst[0] = (sljit_u16)(0xf000 | COPY_BITS(diff, 11, 0, 10) | COPY_BITS(diff, 23, 10, 1));+ jump_inst[1] = (sljit_u16)((diff & 0x7ff) | COPY_BITS(diff, 22, 13, 1) | COPY_BITS(diff, 21, 11, 1));++ SLJIT_ASSERT(type == 4 || type == 5);++ /* The others have a common form. */+ if (type == 4) /* Encoding T4 of 'B' instruction */+ jump_inst[1] |= 0x9000;+ else /* Encoding T1 of 'BL' instruction */+ jump_inst[1] |= 0xd000;+}++static void reduce_code_size(struct sljit_compiler *compiler)+{+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_uw total_size;+ sljit_uw size_reduce = 0;+ sljit_sw diff;++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();++ while (1) {+ SLJIT_GET_NEXT_MIN();++ if (next_min_addr == SLJIT_MAX_ADDRESS)+ break;++ if (next_min_addr == next_label_size) {+ label->size -= size_reduce;++ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_const_addr) {+ const_->addr -= size_reduce;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ continue;+ }++ if (next_min_addr != next_jump_addr)+ continue;++ jump->addr -= size_reduce;+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ total_size = JUMP_MAX_SIZE;++ if (!(jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR))) {+ /* Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr - 2;++ if (jump->flags & IS_COND) {+ diff++;++ if (diff <= (0xff / SSIZE_OF(u16)) && diff >= (-0x100 / SSIZE_OF(u16)))+ total_size = 0;+ else if (diff <= (0xfffff / SSIZE_OF(u16)) && diff >= (-0x100000 / SSIZE_OF(u16)))+ total_size = 1;+ diff--;+ } else if (!(jump->flags & IS_BL) && diff <= (0x7ff / SSIZE_OF(u16)) && diff >= (-0x800 / SSIZE_OF(u16)))+ total_size = 1;++ if (total_size == JUMP_MAX_SIZE && diff <= (0xffffff / SSIZE_OF(u16)) && diff >= (-0x1000000 / SSIZE_OF(u16)))+ total_size = 2;+ }++ size_reduce += JUMP_MAX_SIZE - total_size;+ } else {+ /* Real size minus 1. Unit size: instruction. */+ total_size = 3;++ if (!(jump->flags & JUMP_ADDR)) {+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;++ if (diff <= (0xffd / SSIZE_OF(u16)) && diff >= (-0xfff / SSIZE_OF(u16)))+ total_size = 1;+ }++ size_reduce += 3 - total_size;+ }++ jump->flags |= total_size << JUMP_SIZE_SHIFT;+ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ }++ compiler->size -= size_reduce;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)+{+ struct sljit_memory_fragment *buf;+ sljit_u16 *code;+ sljit_u16 *code_ptr;+ sljit_u16 *buf_ptr;+ sljit_u16 *buf_end;+ sljit_uw half_count;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_sw addr;+ sljit_sw executable_offset;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));++ reduce_code_size(compiler);++ code = (sljit_u16*)allocate_executable_memory(compiler->size * sizeof(sljit_u16), options, exec_allocator_data, &executable_offset);+ PTR_FAIL_WITH_EXEC_IF(code);++ reverse_buf(compiler);+ buf = compiler->buf;++ code_ptr = code;+ half_count = 0;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();+ SLJIT_GET_NEXT_MIN();++ do {+ buf_ptr = (sljit_u16*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 1);+ do {+ *code_ptr = *buf_ptr++;+ if (next_min_addr == half_count) {+ SLJIT_ASSERT(!label || label->size >= half_count);+ SLJIT_ASSERT(!jump || jump->addr >= half_count);+ SLJIT_ASSERT(!const_ || const_->addr >= half_count);++ /* These structures are ordered by their address. */+ if (next_min_addr == next_label_size) {+ label->u.addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_jump_addr) {+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ half_count = half_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);+ jump->addr = (sljit_uw)code_ptr;+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);+ SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr <+ ((jump->flags >> JUMP_SIZE_SHIFT) + ((jump->flags & 0xf0) <= PATCH_TYPE2)) * sizeof(sljit_u16));+ } else {+ half_count += jump->flags >> JUMP_SIZE_SHIFT;+ addr = (sljit_sw)code_ptr;+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);+ jump->addr = (sljit_uw)addr;+ }++ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ } else if (next_min_addr == next_const_addr) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ }++ SLJIT_GET_NEXT_MIN();+ }+ code_ptr++;+ half_count++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == half_count) {+ label->u.addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ generate_jump_or_mov_addr(jump, executable_offset);+ jump = jump->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (sljit_uw)(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);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);++ /* 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:+ case SLJIT_HAS_F64_AS_F32_PAIR:+ case SLJIT_HAS_SIMD:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return (SLJIT_IS_FPU_AVAILABLE) != 0;+#else+ /* Available by default. */+ return 1;+#endif++ case SLJIT_SIMD_REGS_ARE_PAIRS:+ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CTZ:+ case SLJIT_HAS_REV:+ case SLJIT_HAS_ROT:+ case SLJIT_HAS_CMOV:+ case SLJIT_HAS_PREFETCH:+ case SLJIT_HAS_COPY_F32:+ case SLJIT_HAS_COPY_F64:+ case SLJIT_HAS_ATOMIC:+ return 1;++ default:+ return 0;+ }+}++/* --------------------------------------------------------------------- */+/* Core code generator functions. */+/* --------------------------------------------------------------------- */++#define INVALID_IMM 0x80000000+static sljit_uw get_imm(sljit_uw imm)+{+ /* Thumb immediate form. */+ sljit_s32 counter;++ if (imm <= 0xff)+ return imm;++ if ((imm & 0xffff) == (imm >> 16)) {+ /* Some special cases. */+ if (!(imm & 0xff00))+ return (1 << 12) | (imm & 0xff);+ if (!(imm & 0xff))+ return (2 << 12) | ((imm >> 8) & 0xff);+ if ((imm & 0xff00) == ((imm & 0xff) << 8))+ return (3 << 12) | (imm & 0xff);+ }++ /* Assembly optimization: count leading zeroes? */+ counter = 8;+ if (!(imm & 0xffff0000)) {+ counter += 16;+ imm <<= 16;+ }+ if (!(imm & 0xff000000)) {+ counter += 8;+ imm <<= 8;+ }+ if (!(imm & 0xf0000000)) {+ counter += 4;+ imm <<= 4;+ }+ if (!(imm & 0xc0000000)) {+ counter += 2;+ imm <<= 2;+ }+ if (!(imm & 0x80000000)) {+ counter += 1;+ imm <<= 1;+ }+ /* Since imm >= 128, this must be true. */+ SLJIT_ASSERT(counter <= 31);++ if (imm & 0x00ffffff)+ return INVALID_IMM; /* Cannot be encoded. */++ return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1);+}++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)+{+ sljit_uw tmp;++ /* MOVS cannot be used since it destroy flags. */++ if (imm >= 0x10000) {+ tmp = get_imm(imm);+ if (tmp != INVALID_IMM)+ return push_inst32(compiler, MOV_WI | RD4(dst) | tmp);+ tmp = get_imm(~imm);+ if (tmp != INVALID_IMM)+ return push_inst32(compiler, MVN_WI | RD4(dst) | tmp);+ }++ /* set low 16 bits, set hi 16 bits to 0. */+ 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)));++ /* set hi 16 bit if needed. */+ if (imm >= 0x10000)+ return push_inst32(compiler, MOVT | RD4(dst)+ | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));+ return SLJIT_SUCCESS;+}++#define ARG1_IMM 0x0010000+#define ARG2_IMM 0x0020000+/* 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 REGISTER_OP 0x0400000++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+ arg1 must be register, imm+ arg2 must be register, imm */+ sljit_s32 reg;+ sljit_uw imm, imm2;++ if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {+ /* Both are immediates, no temporaries are used. */+ flags &= ~ARG1_IMM;+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));+ arg1 = TMP_REG1;+ }++ if (flags & (ARG1_IMM | ARG2_IMM)) {+ reg = (sljit_s32)((flags & ARG2_IMM) ? arg1 : arg2);+ imm = (flags & ARG2_IMM) ? arg2 : arg1;++ switch (flags & 0xffff) {+ case SLJIT_CLZ:+ case SLJIT_CTZ:+ case SLJIT_REV:+ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ case SLJIT_MUL:+ case SLJIT_MULADD:+ /* No form with immediate operand. */+ break;+ case SLJIT_MOV:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG2);+ return load_immediate(compiler, dst, imm);+ case SLJIT_ADD:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ imm2 = NEGATE(imm);+ if (IS_2_LO_REGS(reg, dst)) {+ if (imm <= 0x7)+ return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));+ if (imm2 <= 0x7)+ return push_inst16(compiler, SUBSI3 | IMM3(imm2) | RD3(dst) | RN3(reg));+ if (reg == dst) {+ if (imm <= 0xff)+ return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst));+ if (imm2 <= 0xff)+ return push_inst16(compiler, SUBSI8 | IMM8(imm2) | RDN3(dst));+ }+ }+ if (!(flags & SET_FLAGS)) {+ if (imm <= 0xfff)+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm));+ if (imm2 <= 0xfff)+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm2));+ }+ imm2 = get_imm(imm);+ if (imm2 != INVALID_IMM)+ return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);+ imm = get_imm(NEGATE(imm));+ if (imm != INVALID_IMM)+ return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_ADDC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ imm2 = get_imm(imm);+ if (imm2 != INVALID_IMM)+ return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);+ if (flags & ARG2_IMM) {+ imm = get_imm(~imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ }+ break;+ case SLJIT_SUB:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ if (flags & ARG1_IMM) {+ 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));+ imm2 = get_imm(imm);+ if (imm2 != INVALID_IMM)+ return push_inst32(compiler, CMPI_W | RN4(reg) | imm2);+ imm = get_imm(NEGATE(imm));+ if (imm != INVALID_IMM)+ return push_inst32(compiler, CMNI_W | RN4(reg) | imm);+ break;+ }+ imm2 = NEGATE(imm);+ if (IS_2_LO_REGS(reg, dst)) {+ if (imm <= 0x7)+ return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));+ if (imm2 <= 0x7)+ return push_inst16(compiler, ADDSI3 | IMM3(imm2) | RD3(dst) | RN3(reg));+ if (reg == dst) {+ if (imm <= 0xff)+ return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));+ if (imm2 <= 0xff)+ return push_inst16(compiler, ADDSI8 | IMM8(imm2) | RDN3(dst));+ }+ }+ if (!(flags & SET_FLAGS)) {+ if (imm <= 0xfff)+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));+ if (imm2 <= 0xfff)+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm2));+ }+ imm2 = get_imm(imm);+ if (imm2 != INVALID_IMM)+ return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);+ imm = get_imm(NEGATE(imm));+ if (imm != INVALID_IMM)+ return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_SUBC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ if (flags & ARG1_IMM)+ break;+ imm2 = get_imm(imm);+ if (imm2 != INVALID_IMM)+ return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);+ imm = get_imm(~imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_AND:+ imm2 = get_imm(imm);+ if (imm2 != INVALID_IMM)+ return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TSTI : ANDI) | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);+ imm = get_imm(~imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_OR:+ imm2 = get_imm(imm);+ if (imm2 != INVALID_IMM)+ return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);+ imm = get_imm(~imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_XOR:+ if (imm == (sljit_uw)-1) {+ if (IS_2_LO_REGS(dst, reg))+ return push_inst16(compiler, MVNS | RD3(dst) | RN3(reg));+ return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(reg));+ }+ imm = get_imm(imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_SHL:+ case SLJIT_MSHL:+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (flags & ARG1_IMM)+ break;+ imm &= 0x1f;++ if (imm == 0) {+ if (!(flags & SET_FLAGS))+ return push_inst16(compiler, MOV | SET_REGS44(dst, reg));+ if (IS_2_LO_REGS(dst, reg))+ return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));+ }++ switch (flags & 0xffff) {+ case SLJIT_SHL:+ case SLJIT_MSHL:+ 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:+ case SLJIT_MLSHR:+ 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));+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ 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));+ case SLJIT_ROTL:+ imm = (imm ^ 0x1f) + 1;+ /* fallthrough */+ default: /* SLJIT_ROTR */+ return push_inst32(compiler, ROR_WI | RD4(dst) | RM4(reg) | IMM5(imm));+ }+ default:+ SLJIT_UNREACHABLE();+ break;+ }++ if (flags & ARG2_IMM) {+ imm = arg2;+ arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(load_immediate(compiler, (sljit_s32)arg2, imm));+ } else {+ imm = arg1;+ arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(load_immediate(compiler, (sljit_s32)arg1, imm));+ }++ SLJIT_ASSERT(arg1 != arg2);+ }++ /* Both arguments are registers. */+ switch (flags & 0xffff) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);+ if (dst == (sljit_s32)arg2)+ return SLJIT_SUCCESS;+ return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));+ case SLJIT_MOV_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_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_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_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_CLZ:+ SLJIT_ASSERT(arg1 == TMP_REG2);+ return push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2));+ case SLJIT_CTZ:+ SLJIT_ASSERT(arg1 == TMP_REG2);+ FAIL_IF(push_inst32(compiler, RBIT | RN4(arg2) | RD4(dst) | RM4(arg2)));+ return push_inst32(compiler, CLZ | RN4(dst) | RD4(dst) | RM4(dst));+ case SLJIT_REV:+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ SLJIT_ASSERT(arg1 == TMP_REG2);+ if (IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, REV | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, REV_W | RN4(arg2) | RD4(dst) | RM4(arg2));+ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ SLJIT_ASSERT(arg1 == TMP_REG2);++ if (IS_2_LO_REGS(dst, arg2))+ FAIL_IF(push_inst16(compiler, REV16 | RD3(dst) | RN3(arg2)));+ else+ FAIL_IF(push_inst32(compiler, REV16_W | RN4(arg2) | RD4(dst) | RM4(arg2)));++ if (!(flags & REGISTER_OP))+ return SLJIT_SUCCESS;++ flags &= 0xffff;+ if (reg_map[dst] <= 7)+ return push_inst16(compiler, (flags == SLJIT_REV_U16 ? UXTH : SXTH) | RD3(dst) | RN3(dst));+ return push_inst32(compiler, (flags == SLJIT_REV_U16 ? UXTH_W : SXTH_W) | RD4(dst) | RM4(dst));+ case SLJIT_ADD:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ if (IS_3_LO_REGS(dst, arg1, arg2))+ return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2));+ if (dst == (sljit_s32)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:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ if (dst == (sljit_s32)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:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ 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:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ if (dst == (sljit_s32)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:+ compiler->status_flags_state = 0;+ if (!(flags & SET_FLAGS))+ return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2));+ reg = (dst == TMP_REG2) ? TMP_REG1 : TMP_REG2;+ FAIL_IF(push_inst32(compiler, SMULL | RT4(dst) | RD4(reg) | RN4(arg1) | RM4(arg2)));+ /* cmp TMP_REG2, dst asr #31. */+ return push_inst32(compiler, CMP_W | RN4(reg) | 0x70e0 | RM4(dst));+ case SLJIT_AND:+ if (dst == (sljit_s32)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, ((flags & UNUSED_RETURN) ? TST_W : AND_W) | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_OR:+ if (dst == (sljit_s32)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 == (sljit_s32)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_MSHL:+ reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;+ FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f));+ arg2 = (sljit_uw)reg;+ /* fallthrough */+ case SLJIT_SHL:+ if (dst == (sljit_s32)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_MLSHR:+ reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;+ FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f));+ arg2 = (sljit_uw)reg;+ /* fallthrough */+ case SLJIT_LSHR:+ if (dst == (sljit_s32)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_MASHR:+ reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;+ FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f));+ arg2 = (sljit_uw)reg;+ /* fallthrough */+ case SLJIT_ASHR:+ if (dst == (sljit_s32)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));+ case SLJIT_ROTL:+ reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;+ FAIL_IF(push_inst32(compiler, RSB_WI | RD4(reg) | RN4(arg2) | 0));+ arg2 = (sljit_uw)reg;+ /* fallthrough */+ case SLJIT_ROTR:+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, RORS | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, ROR_W | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_MULADD:+ compiler->status_flags_state = 0;+ return push_inst32(compiler, MLA | RD4(dst) | RN4(arg1) | RM4(arg2) | RT4(dst));+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++#define STORE 0x01+#define SIGNED 0x02++#define WORD_SIZE 0x00+#define BYTE_SIZE 0x04+#define HALF_SIZE 0x08+#define PRELOAD 0x0c++#define IS_WORD_SIZE(flags) (!((flags) & (BYTE_SIZE | HALF_SIZE)))+#define ALIGN_CHECK(argw, imm, shift) (!((argw) & ~((imm) << (shift))))++/*+ 1st letter:+ w = word+ b = byte+ h = half++ 2nd letter:+ s = signed+ u = unsigned++ 3rd letter:+ l = load+ s = store+*/++static const sljit_ins sljit_mem16[12] = {+/* w u l */ 0x5800 /* ldr */,+/* w u s */ 0x5000 /* str */,+/* w s l */ 0x5800 /* ldr */,+/* w s s */ 0x5000 /* str */,++/* b u l */ 0x5c00 /* ldrb */,+/* b u s */ 0x5400 /* strb */,+/* b s l */ 0x5600 /* ldrsb */,+/* b s s */ 0x5400 /* strb */,++/* h u l */ 0x5a00 /* ldrh */,+/* h u s */ 0x5200 /* strh */,+/* h s l */ 0x5e00 /* ldrsh */,+/* h s s */ 0x5200 /* strh */,+};++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 */,+/* w s s */ 0x6000 /* str imm5 */,++/* b u l */ 0x7800 /* ldrb imm5 */,+/* b u s */ 0x7000 /* strb imm5 */,+/* b s l */ 0x0000 /* not allowed */,+/* b s s */ 0x7000 /* strb imm5 */,++/* h u l */ 0x8800 /* ldrh imm5 */,+/* h u s */ 0x8000 /* strh imm5 */,+/* h s l */ 0x0000 /* not allowed */,+/* h s s */ 0x8000 /* strh imm5 */,+};++#define MEM_IMM8 0xc00+#define MEM_IMM12 0x800000+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 */,+/* w s s */ 0xf8400000 /* str.w */,++/* b u l */ 0xf8100000 /* ldrb.w */,+/* b u s */ 0xf8000000 /* strb.w */,+/* b s l */ 0xf9100000 /* ldrsb.w */,+/* b s s */ 0xf8000000 /* strb.w */,++/* h u l */ 0xf8300000 /* ldrh.w */,+/* 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_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value)+{+ sljit_uw imm;++ if (value >= 0) {+ if (value <= 0xfff)+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(value));+ imm = get_imm((sljit_uw)value);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, ADD_WI | RD4(dst) | RN4(reg) | imm);+ }+ else {+ value = -value;+ if (value <= 0xfff)+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(value));+ imm = get_imm((sljit_uw)value);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, SUB_WI | RD4(dst) | RN4(reg) | imm);+ }+ return SLJIT_ERR_UNSUPPORTED;+}++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_s32 other_r;+ sljit_uw imm, tmp;++ SLJIT_ASSERT(arg & SLJIT_MEM);+ SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -0xff && argw <= 0xfff));++ if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {+ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);+ if (imm != INVALID_IMM) {+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | imm));+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg) | (argw & 0xfff));+ }++ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)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(arg & OFFS_REG_MASK)) {+ argw &= 0x3;+ other_r = OFFS_REG(arg);+ arg &= REG_MASK;++ if (!argw && IS_3_LO_REGS(reg, arg, other_r))+ 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) | ((sljit_ins)argw << 4));+ }++ arg &= REG_MASK;++ if (argw > 0xfff) {+ imm = get_imm((sljit_uw)(argw & ~0xfff));+ if (imm != INVALID_IMM) {+ push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | imm);+ arg = tmp_reg;+ argw = argw & 0xfff;+ }+ }+ else if (argw < -0xff) {+ tmp = (sljit_uw)((-argw + 0xfff) & ~0xfff);+ SLJIT_ASSERT(tmp >= (sljit_uw)-argw);+ imm = get_imm(tmp);++ if (imm != INVALID_IMM) {+ push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | imm);+ arg = tmp_reg;+ argw += (sljit_sw)tmp;++ SLJIT_ASSERT(argw >= 0 && argw <= 0xfff);+ }+ }++ /* 16 bit instruction forms. */+ if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {+ tmp = 3;+ if (IS_WORD_SIZE(flags)) {+ if (ALIGN_CHECK(argw, 0x1f, 2))+ tmp = 2;+ }+ else if (flags & BYTE_SIZE)+ {+ if (ALIGN_CHECK(argw, 0x1f, 0))+ tmp = 0;+ }+ else {+ SLJIT_ASSERT(flags & HALF_SIZE);+ if (ALIGN_CHECK(argw, 0x1f, 1))+ tmp = 1;+ }++ if (tmp < 3)+ return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | ((sljit_ins)argw << (6 - tmp)));+ }+ else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && ALIGN_CHECK(argw, 0xff, 2) && reg_map[reg] <= 7) {+ /* SP based immediate. */+ return push_inst16(compiler, STR_SP | (sljit_ins)((flags & STORE) ? 0 : 0x800) | RDN3(reg) | ((sljit_ins)argw >> 2));+ }++ if (argw >= 0 && argw <= 0xfff)+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | (sljit_ins)argw);+ else if (argw < 0 && argw >= -0xff)+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | (sljit_ins)-argw);++ SLJIT_ASSERT(arg != tmp_reg);++ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)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));+}++#undef ALIGN_CHECK+#undef IS_WORD_SIZE++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 size, i, tmp, word_arg_count;+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);+ sljit_uw offset;+ sljit_uw imm = 0;+#ifdef __SOFTFP__+ sljit_u32 float_arg_count;+#else+ sljit_u32 old_offset, f32_offset;+ sljit_u32 remap[3];+ sljit_u32 *remap_ptr = remap;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ tmp = SLJIT_S0 - saveds;+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--)+ imm |= (sljit_uw)1 << reg_map[i];++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)+ imm |= (sljit_uw)1 << reg_map[i];++ /* At least two registers must be set for PUSH_W and one for PUSH instruction. */+ FAIL_IF((imm & 0xff00)+ ? push_inst32(compiler, PUSH_W | (1 << 14) | imm)+ : push_inst16(compiler, PUSH | (1 << 8) | imm));++ /* Stack must be aligned to 8 bytes: (LR, R4) */+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);++ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ if ((size & SSIZE_OF(sw)) != 0) {+ FAIL_IF(push_inst16(compiler, SUB_SP_I | (sizeof(sljit_sw) >> 2)));+ size += SSIZE_OF(sw);+ }++ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {+ FAIL_IF(push_inst32(compiler, VPUSH | VD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));+ } else {+ if (fsaveds > 0)+ FAIL_IF(push_inst32(compiler, VPUSH | VD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)+ FAIL_IF(push_inst32(compiler, VPUSH | VD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));+ }+ }++ local_size = ((size + local_size + 0x7) & ~0x7) - size;+ compiler->local_size = local_size;++ if (options & SLJIT_ENTER_REG_ARG)+ arg_types = 0;++ arg_types >>= SLJIT_ARG_SHIFT;+ word_arg_count = 0;+ saved_arg_count = 0;+#ifdef __SOFTFP__+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);++ offset = 0;+ float_arg_count = 0;++ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (offset & 0x7)+ offset += sizeof(sljit_sw);++ if (offset < 4 * sizeof(sljit_sw))+ FAIL_IF(push_inst32(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));+ else+ FAIL_IF(push_inst32(compiler, VLDR_F32 | 0x800100 | RN4(SLJIT_SP)+ | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));+ float_arg_count++;+ offset += sizeof(sljit_f64) - sizeof(sljit_sw);+ break;+ case SLJIT_ARG_TYPE_F32:+ if (offset < 4 * sizeof(sljit_sw))+ FAIL_IF(push_inst32(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));+ else+ FAIL_IF(push_inst32(compiler, VLDR_F32 | 0x800000 | RN4(SLJIT_SP)+ | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));+ float_arg_count++;+ break;+ default:+ word_arg_count++;++ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ tmp = SLJIT_S0 - saved_arg_count;+ saved_arg_count++;+ } else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))+ tmp = word_arg_count;+ else+ break;++ if (offset < 4 * sizeof(sljit_sw))+ FAIL_IF(push_inst16(compiler, MOV | ((sljit_ins)reg_map[tmp] & 0x7) | (((sljit_ins)reg_map[tmp] & 0x8) << 4) | (offset << 1)));+ else if (reg_map[tmp] <= 7)+ FAIL_IF(push_inst16(compiler, LDR_SP | RDN3(tmp)+ | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));+ else+ FAIL_IF(push_inst32(compiler, LDR | RT4(tmp) | RN4(SLJIT_SP)+ | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)))));+ break;+ }++ offset += sizeof(sljit_sw);+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ compiler->args_size = offset;+#else+ offset = SLJIT_FR0;+ old_offset = SLJIT_FR0;+ f32_offset = 0;++ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (offset != old_offset)+ *remap_ptr++ = VMOV_F32 | SLJIT_32 | VD4(offset) | VM4(old_offset);+ old_offset++;+ offset++;+ break;+ case SLJIT_ARG_TYPE_F32:+ if (f32_offset != 0) {+ *remap_ptr++ = VMOV_F32 | 0x20 | VD4(offset) | VM4(f32_offset);+ f32_offset = 0;+ } else {+ if (offset != old_offset)+ *remap_ptr++ = VMOV_F32 | VD4(offset) | VM4(old_offset);+ f32_offset = old_offset;+ old_offset++;+ }+ offset++;+ break;+ default:+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0 - saved_arg_count, SLJIT_R0 + word_arg_count)));+ saved_arg_count++;+ }++ word_arg_count++;+ break;+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));++ while (remap_ptr > remap)+ FAIL_IF(push_inst32(compiler, *(--remap_ptr)));+#endif++#ifdef _WIN32+ if (local_size >= 4096) {+ imm = get_imm(4096);+ SLJIT_ASSERT(imm != INVALID_IMM);++ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));++ if (local_size < 4 * 4096) {+ if (local_size > 2 * 4096) {+ if (local_size > 3 * 4096) {+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));+ }++ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));+ }+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG2, ((sljit_uw)local_size >> 12) - 1));+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));+ FAIL_IF(push_inst32(compiler, SUB_WI | SET_FLAGS | RD4(TMP_REG2) | RN4(TMP_REG2) | 1));+ FAIL_IF(push_inst16(compiler, BCC | (0x1 << 8) /* not-equal */ | (-8 & 0xff)));+ }++ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));+ local_size &= 0xfff;+ }++ if (local_size >= 256) {+ SLJIT_ASSERT(local_size < 4096);++ if (local_size <= (127 << 2))+ FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)local_size >> 2)));+ else+ FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, (sljit_uw)local_size));++ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));+ } else if (local_size > 0)+ FAIL_IF(push_inst32(compiler, LDRI | 0x500 | RT4(TMP_REG1) | RN4(SLJIT_SP) | (sljit_uw)local_size));+#else /* !_WIN32 */+ if (local_size > 0) {+ if (local_size <= (127 << 2))+ FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)local_size >> 2)));+ else+ FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, (sljit_uw)local_size));+ }+#endif /* _WIN32 */++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);++ /* Doubles are saved, so alignment is unaffected. */+ if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))+ size += SSIZE_OF(sw);++ compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)+{+ sljit_uw imm2;++ /* The TMP_REG1 register must keep its value. */+ if (imm <= (127u << 2))+ return push_inst16(compiler, ADD_SP_I | (imm >> 2));++ if (imm <= 0xfff)+ return push_inst32(compiler, ADDWI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | IMM12(imm));++ imm2 = get_imm(imm);++ if (imm2 != INVALID_IMM)+ return push_inst32(compiler, ADD_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm2);++ FAIL_IF(load_immediate(compiler, TMP_REG2, imm));+ return push_inst16(compiler, ADD_SP | RN3(TMP_REG2));+}++static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)+{+ sljit_s32 local_size, fscratches, fsaveds, i, tmp;+ sljit_s32 restored_reg = 0;+ sljit_s32 lr_dst = TMP_PC;+ sljit_uw reg_list = 0;++ SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128);++ local_size = compiler->local_size;+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;++ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ if (local_size > 0)+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));++ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {+ FAIL_IF(push_inst32(compiler, VPOP | VD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));+ } else {+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)+ FAIL_IF(push_inst32(compiler, VPOP | VD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));+ if (fsaveds > 0)+ FAIL_IF(push_inst32(compiler, VPOP | VD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));+ }++ local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;+ }++ if (frame_size < 0) {+ lr_dst = TMP_REG2;+ frame_size = 0;+ } else if (frame_size > 0) {+ SLJIT_ASSERT(frame_size == 1 || (frame_size & 0x7) == 0);+ lr_dst = 0;+ frame_size &= ~0x7;+ }++ tmp = SLJIT_S0 - compiler->saveds;+ i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options);+ if (tmp < i) {+ restored_reg = i;+ do {+ reg_list |= (sljit_uw)1 << reg_map[i];+ } while (--i > tmp);+ }++ i = compiler->scratches;+ if (i >= SLJIT_FIRST_SAVED_REG) {+ restored_reg = i;+ do {+ reg_list |= (sljit_uw)1 << reg_map[i];+ } while (--i >= SLJIT_FIRST_SAVED_REG);+ }++ if (lr_dst == TMP_REG2 && reg_list == 0) {+ reg_list |= (sljit_uw)1 << reg_map[TMP_REG2];+ restored_reg = TMP_REG2;+ lr_dst = 0;+ }++ if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {+ /* The local_size does not include the saved registers. */+ tmp = 0;+ if (reg_list != 0) {+ tmp = 2;+ if (local_size <= 0xfff) {+ if (local_size == 0) {+ SLJIT_ASSERT(restored_reg != TMP_REG2);+ if (frame_size == 0)+ return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | 0x308);+ if (frame_size > 2 * SSIZE_OF(sw))+ return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | 0x100 | (sljit_ins)(frame_size - (2 * SSIZE_OF(sw))));+ }++ if (reg_map[restored_reg] <= 7 && local_size <= 0x3fc)+ FAIL_IF(push_inst16(compiler, STR_SP | 0x800 | RDN3(restored_reg) | (sljit_ins)(local_size >> 2)));+ else+ FAIL_IF(push_inst32(compiler, LDR | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)local_size));+ tmp = 1;+ } else if (frame_size == 0) {+ frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw);+ tmp = 3;+ }++ /* Place for the saved register. */+ if (restored_reg != TMP_REG2)+ local_size += SSIZE_OF(sw);+ }++ /* Place for the lr register. */+ local_size += SSIZE_OF(sw);++ if (frame_size > local_size)+ FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_ins)(frame_size - local_size) >> 2)));+ else if (frame_size < local_size)+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));++ if (tmp <= 1)+ return SLJIT_SUCCESS;++ if (tmp == 2) {+ frame_size -= SSIZE_OF(sw);+ if (restored_reg != TMP_REG2)+ frame_size -= SSIZE_OF(sw);++ if (reg_map[restored_reg] <= 7)+ return push_inst16(compiler, STR_SP | 0x800 | RDN3(restored_reg) | (sljit_ins)(frame_size >> 2));++ return push_inst32(compiler, LDR | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)frame_size);+ }++ tmp = (restored_reg == TMP_REG2) ? 0x304 : 0x308;+ return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)tmp);+ }++ if (local_size > 0)+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));++ if (!(reg_list & 0xff00) && lr_dst != TMP_REG2) {+ if (lr_dst == TMP_PC)+ reg_list |= 1u << 8;++ /* At least one register must be set for POP instruction. */+ SLJIT_ASSERT(reg_list != 0);++ FAIL_IF(push_inst16(compiler, POP | reg_list));+ } else {+ if (lr_dst != 0)+ reg_list |= (sljit_uw)1 << reg_map[lr_dst];++ /* At least two registers must be set for POP_W instruction. */+ SLJIT_ASSERT((reg_list & (reg_list - 1)) != 0);++ FAIL_IF(push_inst32(compiler, POP_W | reg_list));+ }++ if (frame_size > 0)+ return push_inst16(compiler, SUB_SP_I | (((sljit_ins)frame_size - sizeof(sljit_sw)) >> 2));++ if (lr_dst != 0)+ return SLJIT_SUCCESS;++ return push_inst16(compiler, ADD_SP_I | 1);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ return emit_stack_frame_release(compiler, 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ srcw = 0;+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src)));+ src = TMP_REG1;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 1));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)++#ifdef __cplusplus+extern "C" {+#endif++#ifdef _WIN32+extern unsigned long long __rt_udiv(unsigned int denominator, unsigned int numerator);+extern long long __rt_sdiv(int denominator, int numerator);+#elif defined(__GNUC__)+extern unsigned int __aeabi_uidivmod(unsigned int numerator, int unsigned denominator);+extern int __aeabi_idivmod(int numerator, int denominator);+#else+#error "Software divmod functions are needed"+#endif++#ifdef __cplusplus+}+#endif++#endif /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)+ sljit_uw saved_reg_list[3];+ sljit_uw saved_reg_count;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ return push_inst16(compiler, BKPT);+ case SLJIT_NOP:+ return push_inst16(compiler, NOP);+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+ return push_inst32(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)+ | RD4(SLJIT_R1) | RT4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1));+#if (defined __ARM_FEATURE_IDIV) || (defined __ARM_ARCH_EXT_IDIV__)+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));+ FAIL_IF(push_inst32(compiler, (op == SLJIT_DIVMOD_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));+ FAIL_IF(push_inst32(compiler, MUL | RD4(SLJIT_R1) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));+ return push_inst32(compiler, SUB_W | RD4(SLJIT_R1) | RN4(TMP_REG1) | RM4(SLJIT_R1));+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+ return push_inst32(compiler, (op == SLJIT_DIV_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1));+#else /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */+ 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_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8)+ | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));+ if (saved_reg_count >= 2) {+ SLJIT_ASSERT(saved_reg_list[1] < 8);+ FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */));+ }+ if (saved_reg_count >= 3) {+ SLJIT_ASSERT(saved_reg_list[2] < 8);+ FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */));+ }+ }++#ifdef _WIN32+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R0, SLJIT_R1)));+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R1, TMP_REG1)));+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__rt_udiv) : SLJIT_FUNC_ADDR(__rt_sdiv))));+#elif defined(__GNUC__)+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));+#else+#error "Software divmod functions are needed"+#endif++ if (saved_reg_count > 0) {+ if (saved_reg_count >= 3) {+ SLJIT_ASSERT(saved_reg_list[2] < 8);+ FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */));+ }+ if (saved_reg_count >= 2) {+ SLJIT_ASSERT(saved_reg_list[1] < 8);+ FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */));+ }+ return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8)+ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);+ }+ return SLJIT_SUCCESS;+#endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++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_s32 dst_r, flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ op = GET_OPCODE(op);+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {+ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ case SLJIT_MOV_P:+ flags = WORD_SIZE;+ break;+ case SLJIT_MOV_U8:+ flags = BYTE_SIZE;+ if (src == SLJIT_IMM)+ srcw = (sljit_u8)srcw;+ break;+ case SLJIT_MOV_S8:+ flags = BYTE_SIZE | SIGNED;+ if (src == SLJIT_IMM)+ srcw = (sljit_s8)srcw;+ break;+ case SLJIT_MOV_U16:+ flags = HALF_SIZE;+ if (src == SLJIT_IMM)+ srcw = (sljit_u16)srcw;+ break;+ case SLJIT_MOV_S16:+ flags = HALF_SIZE | SIGNED;+ if (src == SLJIT_IMM)+ srcw = (sljit_s16)srcw;+ break;+ default:+ SLJIT_UNREACHABLE();+ flags = 0;+ break;+ }++ if (src == SLJIT_IMM)+ FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, (sljit_uw)srcw));+ else if (src & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1));+ else if (FAST_IS_REG(dst))+ return emit_op_imm(compiler, op, dst_r, TMP_REG2, (sljit_uw)src);+ else+ dst_r = src;++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;++ return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG1);+ }++ SLJIT_COMPILE_ASSERT(WORD_SIZE == 0, word_size_must_be_0);+ flags = WORD_SIZE;++ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {+ if (!(dst & SLJIT_MEM) && (!(src & SLJIT_MEM) || op == SLJIT_REV_S16))+ op |= REGISTER_OP;+ flags |= HALF_SIZE;+ }++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, flags, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ emit_op_imm(compiler, op, dst_r, TMP_REG2, (sljit_uw)src);++ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))+ return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG1);+ return SLJIT_SUCCESS;+}++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_s32 dst_reg, src2_tmp_reg, flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG2;+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;++ if (dst == TMP_REG1)+ flags |= UNUSED_RETURN;++ if (src2 == SLJIT_IMM)+ flags |= ARG2_IMM;+ else if (src2 & SLJIT_MEM) {+ src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;+ emit_op_mem(compiler, WORD_SIZE, src2_tmp_reg, src2, src2w, TMP_REG1);+ src2w = src2_tmp_reg;+ } else+ src2w = src2;++ 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;++ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, (sljit_uw)src1w, (sljit_uw)src2w);++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));++ switch (GET_OPCODE(op)) {+ case SLJIT_MULADD:+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, dst_reg, 0, src1, src1w, src2, src2w);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+ sljit_s32 is_left;++ CHECK_ERROR();+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));++ op = GET_OPCODE(op);+ is_left = (op == SLJIT_SHL || op == SLJIT_MSHL);++ if (src1_reg == src2_reg) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, is_left ? SLJIT_ROTL : SLJIT_ROTR, dst_reg, 0, src1_reg, 0, src3, src3w);+ }++ ADJUST_LOCAL_OFFSET(src3, src3w);++ if (src3 == SLJIT_IMM) {+ src3w &= 0x1f;++ if (src3w == 0)+ return SLJIT_SUCCESS;++ if (IS_2_LO_REGS(dst_reg, src1_reg))+ FAIL_IF(push_inst16(compiler, (is_left ? LSLSI : LSRSI) | RD3(dst_reg) | RN3(src1_reg) | ((sljit_ins)src3w << 6)));+ else+ FAIL_IF(push_inst32(compiler, (is_left ? LSL_WI : LSR_WI) | RD4(dst_reg) | RM4(src1_reg) | IMM5(src3w)));++ src3w = (src3w ^ 0x1f) + 1;+ return push_inst32(compiler, ORR_W | RD4(dst_reg) | RN4(dst_reg) | RM4(src2_reg) | (is_left ? 0x10 : 0x0) | IMM5(src3w));+ }++ if (src3 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src3, src3w, TMP_REG2));+ src3 = TMP_REG2;+ }++ if (op == SLJIT_MSHL || op == SLJIT_MLSHR || dst_reg == src3) {+ FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(src3) | 0x1f));+ src3 = TMP_REG2;+ }++ if (dst_reg == src1_reg && IS_2_LO_REGS(dst_reg, src3))+ FAIL_IF(push_inst16(compiler, (is_left ? LSLS : LSRS) | RD3(dst_reg) | RN3(src3)));+ else+ FAIL_IF(push_inst32(compiler, (is_left ? LSL_W : LSR_W) | RD4(dst_reg) | RN4(src1_reg) | RM4(src3)));++ FAIL_IF(push_inst32(compiler, (is_left ? LSR_WI : LSL_WI) | RD4(TMP_REG1) | RM4(src2_reg) | (1 << 6)));+ FAIL_IF(push_inst32(compiler, EORI | RD4(TMP_REG2) | RN4(src3) | 0x1f));+ FAIL_IF(push_inst32(compiler, (is_left ? LSR_W : LSL_W) | RD4(TMP_REG1) | RN4(TMP_REG1) | RM4(TMP_REG2)));+ return push_inst32(compiler, ORR_W | RD4(dst_reg) | RN4(dst_reg) | RM4(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(src))+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));++ return push_inst16(compiler, BX | RN3(TMP_REG2));+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 size, dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ switch (op) {+ case SLJIT_FAST_ENTER:+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(dst))+ return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2));+ break;+ case SLJIT_GET_RETURN_ADDRESS:+ size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);++ if (compiler->fsaveds > 0 || compiler->fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ /* The size of pc is not added above. */+ if ((size & SSIZE_OF(sw)) == 0)+ size += SSIZE_OF(sw);++ size += GET_SAVED_FLOAT_REGISTERS_SIZE(compiler->fscratches, compiler->fsaveds, f64);+ }++ SLJIT_ASSERT(((compiler->local_size + size + SSIZE_OF(sw)) & 0x7) == 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, TMP_REG1));+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));++ if (type == SLJIT_GP_REGISTER)+ return reg_map[reg];++ if (type == SLJIT_FLOAT_REGISTER || type == SLJIT_SIMD_REG_64)+ return freg_map[reg];++ if (type != SLJIT_SIMD_REG_128)+ return freg_map[reg] & ~0x1;++ return -1;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ if (size == 2)+ return push_inst16(compiler, *(sljit_u16*)instruction);+ return push_inst32(compiler, *(sljit_ins*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define FPU_LOAD (1 << 20)++static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ sljit_uw imm;+ sljit_ins inst = VSTR_F32 | (flags & (SLJIT_32 | 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_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | (((sljit_uw)argw & 0x3) << 6)));+ arg = SLJIT_MEM | TMP_REG1;+ argw = 0;+ }++ if ((arg & REG_MASK) && (argw & 0x3) == 0) {+ if (!(argw & ~0x3fc))+ return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | VD4(reg) | ((sljit_uw)argw >> 2));+ if (!(-argw & ~0x3fc))+ return push_inst32(compiler, inst | RN4(arg & REG_MASK) | VD4(reg) | ((sljit_uw)-argw >> 2));+ }++ if (arg & REG_MASK) {+ if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {+ FAIL_IF(compiler->error);+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | VD4(reg));+ }++ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);+ if (imm != INVALID_IMM) {+ FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | VD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2));+ }++ imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);+ if (imm != INVALID_IMM) {+ argw = -argw;+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));+ return push_inst32(compiler, inst | RN4(TMP_REG1) | VD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2));+ }+ }++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));+ if (arg & REG_MASK)+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, (arg & REG_MASK))));+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | VD4(reg));+}++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_32;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_32) | VD4(TMP_FREG1) | VM4(src)));++ if (FAST_IS_REG(dst))+ return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | VN4(TMP_FREG1));++ /* Store the integer value from a VFP register. */+ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);+}++static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (FAST_IS_REG(src))+ FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | VN4(TMP_FREG1)));+ else if (src & SLJIT_MEM) {+ /* Load the integer value into a VFP register. */+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));+ }+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));+ FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | VN4(TMP_FREG1)));+ }++ FAIL_IF(push_inst32(compiler, ins | VD4(dst_r) | VM4(TMP_FREG1)));++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, (ins & SLJIT_32), TMP_FREG1, dst, dstw);+ return SLJIT_SUCCESS;+}++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)+{+ return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_S32 | (~op & SLJIT_32), dst, dstw, src, srcw);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_U32 | (~op & SLJIT_32), dst, dstw, src, srcw);+}++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_32;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));+ src2 = TMP_FREG2;+ }++ FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_32) | VD4(src1) | VM4(src2)));+ FAIL_IF(push_inst32(compiler, VMRS));++ if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst16(compiler, IT | (0x6 << 4) | 0x8));+ return push_inst16(compiler, CMP /* Rm, Rn = r0 */);+}++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_s32 dst_r;++ CHECK_ERROR();++ SLJIT_COMPILE_ASSERT((SLJIT_32 == 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_32;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (!(dst & SLJIT_MEM))+ FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src)));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src)));+ op ^= SLJIT_32;+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);+ return SLJIT_SUCCESS;+}++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_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ op ^= SLJIT_32;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;+ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));+ src1 = TMP_FREG1;+ }+ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));+ src2 = TMP_FREG2;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2)));+ break;+ case SLJIT_SUB_F64:+ FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2)));+ break;+ case SLJIT_MUL_F64:+ FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2)));+ break;+ case SLJIT_DIV_F64:+ FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2)));+ break;+ case SLJIT_COPYSIGN_F64:+ FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(src2) | RT4(TMP_REG1) | ((op & SLJIT_32) ? (1 << 7) : 0)));+ FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src1)));+ FAIL_IF(push_inst32(compiler, CMPI_W | RN4(TMP_REG1) | 0));+ FAIL_IF(push_inst16(compiler, IT | (0xb << 4) | 0x8));+ return push_inst32(compiler, VNEG_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(dst_r));+ }++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+#if defined(__ARM_NEON) && __ARM_NEON+ sljit_u32 exp;+ sljit_ins ins;+#endif /* NEON */+ union {+ sljit_u32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++#if defined(__ARM_NEON) && __ARM_NEON+ if ((u.imm << (32 - 19)) == 0) {+ exp = (u.imm >> (23 + 2)) & 0x3f;++ if (exp == 0x20 || exp == 0x1f) {+ ins = ((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f);+ return push_inst32(compiler, (VMOV_F32 ^ (1 << 6)) | ((ins & 0xf0) << 12) | VD4(freg) | (ins & 0xf));+ }+ }+#endif /* NEON */++ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));+ return push_inst32(compiler, VMOV | VN4(freg) | RT4(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+#if defined(__ARM_NEON) && __ARM_NEON+ sljit_u32 exp;+ sljit_ins ins;+#endif /* NEON */+ union {+ sljit_u32 imm[2];+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++#if defined(__ARM_NEON) && __ARM_NEON+ if (u.imm[0] == 0 && (u.imm[1] << (64 - 48)) == 0) {+ exp = (u.imm[1] >> ((52 - 32) + 2)) & 0x1ff;++ if (exp == 0x100 || exp == 0xff) {+ ins = ((u.imm[1] >> (56 - 32)) & 0x80) | ((u.imm[1] >> (48 - 32)) & 0x7f);+ return push_inst32(compiler, (VMOV_F32 ^ (1 << 6)) | (1 << 8) | ((ins & 0xf0) << 12) | VD4(freg) | (ins & 0xf));+ }+ }+#endif /* NEON */++ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));+ if (u.imm[0] == u.imm[1])+ return push_inst32(compiler, VMOV2 | RN4(TMP_REG1) | RT4(TMP_REG1) | VM4(freg));++ FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));+ return push_inst32(compiler, VMOV2 | RN4(TMP_REG2) | RT4(TMP_REG1) | VM4(freg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_s32 reg2;+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ if (reg & REG_PAIR_MASK) {+ reg2 = REG_PAIR_SECOND(reg);+ reg = REG_PAIR_FIRST(reg);++ inst = VMOV2 | RN4(reg) | RT4(reg2) | VM4(freg);+ } else {+ inst = VMOV | VN4(freg) | RT4(reg);++ if (!(op & SLJIT_32))+ inst |= 1 << 7;+ }++ if (GET_OPCODE(op) == SLJIT_COPY_FROM_F64)+ inst |= 1 << 20;++ return push_inst32(compiler, inst);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_ATOMIC_STORED:+ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ return 0x0;++ case SLJIT_NOT_EQUAL:+ case SLJIT_ATOMIC_NOT_STORED:+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ return 0x1;++ case SLJIT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)+ return 0x2;+ /* fallthrough */++ case SLJIT_LESS:+ return 0x3;++ case SLJIT_NOT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)+ return 0x3;+ /* fallthrough */++ case SLJIT_GREATER_EQUAL:+ return 0x2;++ case SLJIT_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ return 0x8;++ case SLJIT_LESS_EQUAL:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ return 0x9;++ case SLJIT_SIG_LESS:+ case SLJIT_UNORDERED_OR_LESS:+ return 0xb;++ case SLJIT_SIG_GREATER_EQUAL:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ return 0xa;++ case SLJIT_SIG_GREATER:+ case SLJIT_F_GREATER:+ case SLJIT_ORDERED_GREATER:+ return 0xc;++ case SLJIT_SIG_LESS_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ return 0xd;++ case SLJIT_OVERFLOW:+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))+ return 0x1;+ /* fallthrough */++ case SLJIT_UNORDERED:+ return 0x6;++ case SLJIT_NOT_OVERFLOW:+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))+ return 0x0;+ /* fallthrough */++ case SLJIT_ORDERED:+ return 0x7;++ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ return 0x4;++ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ return 0x5;++ default: /* SLJIT_JUMP */+ SLJIT_UNREACHABLE();+ return 0xe;+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;+ sljit_ins cc;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ if (type < SLJIT_JUMP) {+ jump->flags |= IS_COND;+ cc = get_cc(compiler, type);+ jump->flags |= cc << 8;+ PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ }++ jump->addr = compiler->size;+ if (type <= SLJIT_JUMP)+ PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG1)));+ else {+ jump->flags |= IS_BL;+ PTR_FAIL_IF(push_inst16(compiler, BLX | RN3(TMP_REG1)));+ }++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return jump;+}++#ifdef __SOFTFP__++static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)+{+ sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;+ sljit_u32 offset = 0;+ sljit_u32 word_arg_offset = 0;+ sljit_u32 float_arg_count = 0;+ sljit_s32 types = 0;+ sljit_u32 src_offset = 4 * sizeof(sljit_sw);+ sljit_u8 offsets[4];+ sljit_u8 *offset_ptr = offsets;++ if (src && FAST_IS_REG(*src))+ src_offset = (sljit_u32)reg_map[*src] * sizeof(sljit_sw);++ arg_types >>= SLJIT_ARG_SHIFT;++ while (arg_types) {+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);++ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (offset & 0x7)+ offset += sizeof(sljit_sw);+ *offset_ptr++ = (sljit_u8)offset;+ offset += sizeof(sljit_f64);+ float_arg_count++;+ break;+ case SLJIT_ARG_TYPE_F32:+ *offset_ptr++ = (sljit_u8)offset;+ offset += sizeof(sljit_f32);+ float_arg_count++;+ break;+ default:+ *offset_ptr++ = (sljit_u8)offset;+ offset += sizeof(sljit_sw);+ word_arg_offset += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {+ /* Keep lr register on the stack. */+ if (is_tail_call)+ offset += sizeof(sljit_sw);++ offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_uw)0x7;++ *extra_space = offset;++ if (is_tail_call)+ FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));+ else+ FAIL_IF(push_inst16(compiler, SUB_SP_I | (offset >> 2)));+ } else {+ if (is_tail_call)+ FAIL_IF(emit_stack_frame_release(compiler, -1));+ *extra_space = 0;+ }++ SLJIT_ASSERT(reg_map[TMP_REG1] == 12);++ /* Process arguments in reversed direction. */+ while (types) {+ switch (types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ float_arg_count--;+ offset = *(--offset_ptr);++ SLJIT_ASSERT((offset & 0x7) == 0);++ if (offset < 4 * sizeof(sljit_sw)) {+ if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {+ FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));+ *src = TMP_REG1;+ }+ FAIL_IF(push_inst32(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));+ } else+ FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800100 | RN4(SLJIT_SP)+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));+ break;+ case SLJIT_ARG_TYPE_F32:+ float_arg_count--;+ offset = *(--offset_ptr);++ if (offset < 4 * sizeof(sljit_sw)) {+ if (src_offset == offset) {+ FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));+ *src = TMP_REG1;+ }+ FAIL_IF(push_inst32(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));+ } else+ FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800000 | RN4(SLJIT_SP)+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));+ break;+ default:+ word_arg_offset -= sizeof(sljit_sw);+ offset = *(--offset_ptr);++ SLJIT_ASSERT(offset >= word_arg_offset);++ if (offset != word_arg_offset) {+ if (offset < 4 * sizeof(sljit_sw)) {+ if (src_offset == offset) {+ FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));+ *src = TMP_REG1;+ }+ else if (src_offset == word_arg_offset) {+ *src = (sljit_s32)(1 + (offset >> 2));+ src_offset = offset;+ }+ FAIL_IF(push_inst16(compiler, MOV | (offset >> 2) | (word_arg_offset << 1)));+ } else+ FAIL_IF(push_inst16(compiler, STR_SP | (word_arg_offset << 6) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));+ }+ break;+ }++ types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)+ FAIL_IF(push_inst32(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)+ FAIL_IF(push_inst32(compiler, VMOV | (0 << 16) | (0 << 12)));++ return SLJIT_SUCCESS;+}++#else++static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ sljit_u32 offset = SLJIT_FR0;+ sljit_u32 new_offset = SLJIT_FR0;+ sljit_u32 f32_offset = 0;++ /* Remove return value. */+ arg_types >>= SLJIT_ARG_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (offset != new_offset)+ FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_32 | VD4(new_offset) | VM4(offset)));++ new_offset++;+ offset++;+ break;+ case SLJIT_ARG_TYPE_F32:+ if (f32_offset != 0) {+ FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | VD4(f32_offset) | VM4(offset)));+ f32_offset = 0;+ } else {+ if (offset != new_offset)+ FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | VD4(new_offset) | VM4(offset)));+ f32_offset = new_offset;+ new_offset++;+ }+ offset++;+ break;+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++#endif++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+#ifdef __SOFTFP__+ struct sljit_jump *jump;+ sljit_u32 extra_space = (sljit_u32)type;+#endif++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++#ifdef __SOFTFP__+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {+ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));+ SLJIT_ASSERT((extra_space & 0x7) == 0);++ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);++ SLJIT_SKIP_CHECKS(compiler);+ jump = sljit_emit_jump(compiler, type);+ PTR_FAIL_IF(jump == NULL);++ if (extra_space > 0) {+ if (type & SLJIT_CALL_RETURN)+ PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)+ | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));++ PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));++ if (type & SLJIT_CALL_RETURN) {+ PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2)));+ return jump;+ }+ }++ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));+ PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));+ return jump;+ }+#endif /* __SOFTFP__ */++ if (type & SLJIT_CALL_RETURN) {+ /* ldmia sp!, {..., lr} */+ PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);+ }++#ifndef __SOFTFP__+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));+#endif /* !__SOFTFP__ */++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, type);+}++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;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);++ if (src != SLJIT_IMM) {+ if (FAST_IS_REG(src)) {+ SLJIT_ASSERT(reg_map[src] != 14);+ 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, TMP_REG1));+ if (type >= SLJIT_FAST_CALL)+ return push_inst16(compiler, BLX | RN3(TMP_REG1));+ }++ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));+ jump->u.target = (sljit_uw)srcw;++ jump->addr = compiler->size;+ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+#ifdef __SOFTFP__+ sljit_u32 extra_space = (sljit_u32)type;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src)));+ src = TMP_REG1;+ }++#ifdef __SOFTFP__+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {+ FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));+ SLJIT_ASSERT((extra_space & 0x7) == 0);++ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)+ type = SLJIT_JUMP;++ SLJIT_SKIP_CHECKS(compiler);+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));++ if (extra_space > 0) {+ if (type & SLJIT_CALL_RETURN)+ FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)+ | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));++ FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));++ if (type & SLJIT_CALL_RETURN)+ return push_inst16(compiler, BX | RN3(TMP_REG2));+ }++ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));+ return softfloat_post_call_with_args(compiler, arg_types);+ }+#endif /* __SOFTFP__ */++ if (type & SLJIT_CALL_RETURN) {+ /* ldmia sp!, {..., lr} */+ FAIL_IF(emit_stack_frame_release(compiler, -1));+ type = SLJIT_JUMP;+ }++#ifndef __SOFTFP__+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ FAIL_IF(hardfloat_call_with_args(compiler, arg_types));+#endif /* !__SOFTFP__ */++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+}++#ifdef __SOFTFP__++static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ if (compiler->options & SLJIT_ENTER_REG_ARG) {+ if (src == SLJIT_FR0)+ return SLJIT_SUCCESS;++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);+ }++ if (FAST_IS_REG(src)) {+ if (op & SLJIT_32)+ return push_inst32(compiler, VMOV | (1 << 20) | VN4(src) | RT4(SLJIT_R0));+ return push_inst32(compiler, VMOV2 | (1 << 20) | VM4(src) | RT4(SLJIT_R0) | RN4(SLJIT_R1));+ }++ SLJIT_SKIP_CHECKS(compiler);++ if (op & SLJIT_32)+ return sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src, srcw);+ return sljit_emit_mem(compiler, SLJIT_MOV, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), src, srcw);+}++#endif /* __SOFTFP__ */++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_s32 dst_r, flags = GET_ALL_FLAGS(op);+ sljit_ins cc;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+ cc = get_cc(compiler, type);+ 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));+ if (reg_map[dst_r] > 7) {+ 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 & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2);+ }++ 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, ((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. */+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+ sljit_uw cc, tmp;++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (src2_reg != dst_reg && src1 == dst_reg) {+ src1 = src2_reg;+ src1w = 0;+ src2_reg = dst_reg;+ type ^= 0x1;+ }++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, (src2_reg != dst_reg) ? dst_reg : TMP_REG1, src1, src1w, TMP_REG1));++ if (src2_reg != dst_reg) {+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else {+ src1 = TMP_REG1;+ src1w = 0;+ }+ } else if (dst_reg != src2_reg)+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(dst_reg, src2_reg)));++ cc = get_cc(compiler, type & ~SLJIT_32);++ if (src1 != SLJIT_IMM) {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src1));+ }++ tmp = (sljit_uw)src1w;++ 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));+ }++ tmp = get_imm((sljit_uw)src1w);+ if (tmp != INVALID_IMM) {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);+ }++ tmp = get_imm(~(sljit_uw)src1w);+ if (tmp != INVALID_IMM) {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);+ }++ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4));++ tmp = (sljit_uw)src1w;+ 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 sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ type ^= SLJIT_32;++ if (dst_freg != src2_freg) {+ if (dst_freg == src1) {+ src1 = src2_freg;+ src1w = 0;+ type ^= 0x1;+ } else+ FAIL_IF(push_inst32(compiler, VMOV_F32 | (type & SLJIT_32) | VD4(dst_freg) | VM4(src2_freg)));+ }++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) | FPU_LOAD, TMP_FREG2, src1, src1w));+ src1 = TMP_FREG2;+ }++ FAIL_IF(push_inst16(compiler, IT | (get_cc(compiler, type & ~SLJIT_32) << 4) | 0x8));+ return push_inst32(compiler, VMOV_F32 | (type & SLJIT_32) | VD4(dst_freg) | VM4(src1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 flags;+ sljit_uw imm, tmp;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (!(reg & REG_PAIR_MASK))+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);++ if (type & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) {+ if ((mem & REG_MASK) == 0) {+ if ((memw & 0xfff) >= (0x1000 - SSIZE_OF(sw))) {+ imm = get_imm((sljit_uw)((memw + 0x1000) & ~0xfff));++ if (imm != INVALID_IMM)+ memw = (memw & 0xfff) - 0x1000;+ } else {+ imm = get_imm((sljit_uw)(memw & ~0xfff));++ if (imm != INVALID_IMM)+ memw &= 0xfff;+ }++ if (imm == INVALID_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));+ memw = 0;+ } else+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(TMP_REG1) | imm));++ mem = SLJIT_MEM1(TMP_REG1);+ } else if (mem & OFFS_REG_MASK) {+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(mem & REG_MASK) | RM4(OFFS_REG(mem)) | ((sljit_uw)(memw & 0x3) << 6)));+ memw = 0;+ mem = SLJIT_MEM1(TMP_REG1);+ } else if (memw < -0xff) {+ /* Zero value can be included in the first case. */+ if ((-memw & 0xfff) <= SSIZE_OF(sw))+ tmp = (sljit_uw)((-memw + 0x7ff) & ~0x7ff);+ else+ tmp = (sljit_uw)((-memw + 0xfff) & ~0xfff);++ SLJIT_ASSERT(tmp >= (sljit_uw)-memw);+ imm = get_imm(tmp);++ if (imm != INVALID_IMM) {+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm));+ memw += (sljit_sw)tmp;+ SLJIT_ASSERT(memw >= 0 && memw <= 0xfff - SSIZE_OF(sw));+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK)));+ memw = 0;+ }++ mem = SLJIT_MEM1(TMP_REG1);+ } else if (memw >= (0x1000 - SSIZE_OF(sw))) {+ if ((memw & 0xfff) >= (0x1000 - SSIZE_OF(sw))) {+ imm = get_imm((sljit_uw)((memw + 0x1000) & ~0xfff));++ if (imm != INVALID_IMM)+ memw = (memw & 0xfff) - 0x1000;+ } else {+ imm = get_imm((sljit_uw)(memw & ~0xfff));++ if (imm != INVALID_IMM)+ memw &= 0xfff;+ }++ if (imm != INVALID_IMM) {+ SLJIT_ASSERT(memw >= -0xff && memw <= 0xfff);+ FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm));+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK)));+ memw = 0;+ }++ mem = SLJIT_MEM1(TMP_REG1);+ }++ flags = WORD_SIZE;++ SLJIT_ASSERT(memw <= 0xfff - SSIZE_OF(sw) && memw >= -0xff);++ if (type & SLJIT_MEM_STORE) {+ flags |= STORE;+ } else if (REG_PAIR_FIRST(reg) == (mem & REG_MASK)) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, REG_PAIR_SECOND(reg), mem, memw + SSIZE_OF(sw), TMP_REG2));+ return emit_op_mem(compiler, WORD_SIZE, REG_PAIR_FIRST(reg), mem, memw, TMP_REG2);+ }++ FAIL_IF(emit_op_mem(compiler, flags, REG_PAIR_FIRST(reg), mem, memw, TMP_REG2));+ return emit_op_mem(compiler, flags, REG_PAIR_SECOND(reg), mem, memw + SSIZE_OF(sw), TMP_REG2);+ }++ flags = 1 << 23;++ if ((mem & REG_MASK) == 0) {+ tmp = (sljit_uw)(memw & 0x7fc);+ imm = get_imm((sljit_uw)((memw + (tmp <= 0x400 ? 0 : 0x400)) & ~0x3fc));++ if (imm == INVALID_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));+ memw = 0;+ } else {+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(TMP_REG1) | imm));+ memw = (memw & 0x3fc) >> 2;++ if (tmp > 0x400) {+ memw = 0x100 - memw;+ flags = 0;+ }++ SLJIT_ASSERT(memw >= 0 && memw <= 0xff);+ }++ mem = SLJIT_MEM1(TMP_REG1);+ } else if (mem & OFFS_REG_MASK) {+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(mem & REG_MASK) | RM4(OFFS_REG(mem)) | ((sljit_uw)(memw & 0x3) << 6)));+ memw = 0;+ mem = SLJIT_MEM1(TMP_REG1);+ } else if (memw < 0) {+ if ((-memw & ~0x3fc) == 0) {+ flags = 0;+ memw = -memw >> 2;+ } else {+ tmp = (sljit_uw)(-memw & 0x7fc);+ imm = get_imm((sljit_uw)((-memw + (tmp <= 0x400 ? 0 : 0x400)) & ~0x3fc));++ if (imm != INVALID_IMM) {+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm));+ memw = (-memw & 0x3fc) >> 2;++ if (tmp <= 0x400)+ flags = 0;+ else+ memw = 0x100 - memw;+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK)));+ memw = 0;+ }++ mem = SLJIT_MEM1(TMP_REG1);+ }+ } else if ((memw & ~0x3fc) != 0) {+ tmp = (sljit_uw)(memw & 0x7fc);+ imm = get_imm((sljit_uw)((memw + (tmp <= 0x400 ? 0 : 0x400)) & ~0x3fc));++ if (imm != INVALID_IMM) {+ FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm));+ memw = (memw & 0x3fc) >> 2;++ if (tmp > 0x400) {+ memw = 0x100 - memw;+ flags = 0;+ }+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK)));+ memw = 0;+ }++ mem = SLJIT_MEM1(TMP_REG1);+ } else+ memw >>= 2;++ SLJIT_ASSERT(memw >= 0 && memw <= 0xff);+ return push_inst32(compiler, ((type & SLJIT_MEM_STORE) ? STRD : LDRD) | (sljit_ins)flags | RN4(mem & REG_MASK) | RT4(REG_PAIR_FIRST(reg)) | RD4(REG_PAIR_SECOND(reg)) | (sljit_ins)memw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 flags;+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));++ if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ switch (type & 0xff) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ case SLJIT_MOV_P:+ flags = WORD_SIZE;+ break;+ case SLJIT_MOV_U8:+ flags = BYTE_SIZE;+ break;+ case SLJIT_MOV_S8:+ flags = BYTE_SIZE | SIGNED;+ break;+ case SLJIT_MOV_U16:+ flags = HALF_SIZE;+ break;+ case SLJIT_MOV_S16:+ flags = HALF_SIZE | SIGNED;+ break;+ default:+ SLJIT_UNREACHABLE();+ flags = WORD_SIZE;+ break;+ }++ if (type & SLJIT_MEM_STORE)+ flags |= STORE;++ inst = sljit_mem32[flags] | 0x900;++ if (!(type & SLJIT_MEM_POST))+ inst |= 0x400;++ if (memw >= 0)+ inst |= 0x200;+ else+ memw = -memw;++ return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | (sljit_ins)memw);+}++static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset)+{+ sljit_s32 arg = *mem;+ sljit_sw argw = *memw;+ sljit_uw imm;++ *mem = TMP_REG1;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ *memw = 0;+ return push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((sljit_uw)(argw & 0x3) << 6));+ }++ arg &= REG_MASK;++ if (arg) {+ if (argw <= max_offset && argw >= -0xff) {+ *mem = arg;+ return SLJIT_SUCCESS;+ }++ if (argw < 0) {+ imm = get_imm((sljit_uw)(-argw & ~0xff));++ if (imm) {+ *memw = -(-argw & 0xff);+ return push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg) | imm);+ }+ } else if ((argw & 0xfff) <= max_offset) {+ imm = get_imm((sljit_uw)(argw & ~0xfff));++ if (imm) {+ *memw = argw & 0xfff;+ return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm);+ }+ } else {+ imm = get_imm((sljit_uw)((argw | 0xfff) + 1));++ if (imm) {+ *memw = (argw & 0xfff) - 0x1000;+ return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm);+ }+ }+ }++ imm = (sljit_uw)(argw & ~0xfff);++ if ((argw & 0xfff) > max_offset) {+ imm += 0x1000;+ *memw = (argw & 0xfff) - 0x1000;+ } else+ *memw = argw & 0xfff;++ FAIL_IF(load_immediate(compiler, TMP_REG1, imm));++ if (arg == 0)+ return SLJIT_SUCCESS;++ return push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, arg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));++ if (type & SLJIT_MEM_ALIGNED_32)+ return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw);++ if (type & SLJIT_MEM_STORE) {+ FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(freg) | RT4(TMP_REG2)));++ if (type & SLJIT_32)+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1);++ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));+ mem |= SLJIT_MEM;++ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1));+ FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(freg) | 0x80 | RT4(TMP_REG2)));+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw + 4, TMP_REG1);+ }++ if (type & SLJIT_32) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));+ return push_inst32(compiler, VMOV | VN4(freg) | RT4(TMP_REG2));+ }++ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));+ mem |= SLJIT_MEM;++ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, mem, memw + 4, TMP_REG1));+ return push_inst32(compiler, VMOV2 | VM4(freg) | RT4(TMP_REG2) | RN4(TMP_REG1));+}++static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw)+{+ sljit_uw imm;+ sljit_s32 mem = *mem_ptr;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ *mem_ptr = TMP_REG1;+ return push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(mem & REG_MASK) | RM4(OFFS_REG(mem)) | ((sljit_uw)(memw & 0x3) << 6));+ }++ if (SLJIT_UNLIKELY(!(mem & REG_MASK))) {+ *mem_ptr = TMP_REG1;+ return load_immediate(compiler, TMP_REG1, (sljit_uw)memw);+ }++ mem &= REG_MASK;++ if (memw == 0) {+ *mem_ptr = mem;+ return SLJIT_SUCCESS;+ }++ *mem_ptr = TMP_REG1;+ imm = get_imm((sljit_uw)(memw < 0 ? -memw : memw));++ if (imm != INVALID_IMM)+ return push_inst32(compiler, ((memw < 0) ? SUB_WI : ADD_WI) | RD4(TMP_REG1) | RN4(mem) | imm);++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));+ return push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem));+}++static SLJIT_INLINE sljit_s32 simd_get_quad_reg_index(sljit_s32 freg)+{+ freg += freg & 0x1;++ SLJIT_ASSERT((freg_map[freg] & 0x1) == (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS));++ if (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)+ freg--;++ return freg;+}++#define SLJIT_QUAD_OTHER_HALF(freg) ((((freg) & 0x1) << 1) - 1)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4)+ freg = simd_get_quad_reg_index(freg);++ if (!(srcdst & SLJIT_MEM)) {+ if (reg_size == 4)+ srcdst = simd_get_quad_reg_index(srcdst);++ if (type & SLJIT_SIMD_STORE)+ ins = VD4(srcdst) | VN4(freg) | VM4(freg);+ else+ ins = VD4(freg) | VN4(srcdst) | VM4(srcdst);++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 6;++ return push_inst32(compiler, VORR | ins);+ }++ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));++ if (elem_size > 3)+ elem_size = 3;++ ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD4(freg)+ | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8));++ SLJIT_ASSERT(reg_size >= alignment);++ if (alignment == 3)+ ins |= 0x10;+ else if (alignment >= 4)+ ins |= 0x20;++ return push_inst32(compiler, ins | RN4(srcdst) | ((sljit_ins)elem_size) << 6 | 0xf);+}++static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value)+{+ sljit_ins result;++ if (elem_size > 1 && (sljit_u16)value == (value >> 16)) {+ elem_size = 1;+ value = (sljit_u16)value;+ }++ if (elem_size == 1 && (sljit_u8)value == (value >> 8)) {+ elem_size = 0;+ value = (sljit_u8)value;+ }++ switch (elem_size) {+ case 0:+ SLJIT_ASSERT(value <= 0xff);+ result = 0xe00;+ break;+ case 1:+ SLJIT_ASSERT(value <= 0xffff);+ result = 0;++ while (1) {+ if (value <= 0xff) {+ result |= 0x800;+ break;+ }++ if ((value & 0xff) == 0) {+ value >>= 8;+ result |= 0xa00;+ break;+ }++ if (result != 0)+ return ~(sljit_ins)0;++ value ^= (sljit_uw)0xffff;+ result = (1 << 5);+ }+ break;+ default:+ SLJIT_ASSERT(value <= 0xffffffff);+ result = 0;++ while (1) {+ if (value <= 0xff) {+ result |= 0x000;+ break;+ }++ if ((value & ~(sljit_uw)0xff00) == 0) {+ value >>= 8;+ result |= 0x200;+ break;+ }++ if ((value & ~(sljit_uw)0xff0000) == 0) {+ value >>= 16;+ result |= 0x400;+ break;+ }++ if ((value & ~(sljit_uw)0xff000000) == 0) {+ value >>= 24;+ result |= 0x600;+ break;+ }++ if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) {+ value >>= 8;+ result |= 0xc00;+ break;+ }++ if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) {+ value >>= 16;+ result |= 0xd00;+ break;+ }++ if (result != 0)+ return ~(sljit_ins)0;++ value = ~value;+ result = (1 << 5);+ }+ break;+ }++ return ((sljit_ins)value & 0xf) | (((sljit_ins)value & 0x70) << 12) | (((sljit_ins)value & 0x80) << 21) | result;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins, imm;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4)+ freg = simd_get_quad_reg_index(freg);++ if (src == SLJIT_IMM && srcw == 0)+ return push_inst32(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD4(freg));++ if (SLJIT_UNLIKELY(elem_size == 3)) {+ SLJIT_ASSERT(type & SLJIT_SIMD_FLOAT);++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, freg, src, srcw));+ src = freg;+ } else if (freg != src)+ FAIL_IF(push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src)));++ freg += SLJIT_QUAD_OTHER_HALF(freg);++ if (freg != src)+ return push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src));+ return SLJIT_SUCCESS;+ }++ if (src & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));++ ins = (sljit_ins)(elem_size << 6);++ if (reg_size == 4)+ ins |= 1 << 5;++ return push_inst32(compiler, VLD1_r | ins | VD4(freg) | RN4(src) | 0xf);+ }++ if (type & SLJIT_SIMD_FLOAT) {+ SLJIT_ASSERT(elem_size == 2);+ ins = ((sljit_ins)freg_ebit_map[src] << (16 + 2 + 1)) | ((sljit_ins)1 << (16 + 2));++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 6;++ return push_inst32(compiler, VDUP_s | ins | VD4(freg) | (sljit_ins)freg_map[src]);+ }++ if (src == SLJIT_IMM) {+ if (elem_size < 2)+ srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;++ imm = simd_get_imm(elem_size, (sljit_uw)srcw);++ if (imm != ~(sljit_ins)0) {+ if (reg_size == 4)+ imm |= (sljit_ins)1 << 6;++ return push_inst32(compiler, VMOV_i | imm | VD4(freg));+ }++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));+ src = TMP_REG1;+ }++ switch (elem_size) {+ case 0:+ ins = 1 << 22;+ break;+ case 1:+ ins = 1 << 5;+ break;+ default:+ ins = 0;+ break;+ }++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 21;++ return push_inst32(compiler, VDUP | ins | VN4(freg) | RT4(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4)+ freg = simd_get_quad_reg_index(freg);++ if (type & SLJIT_SIMD_LANE_ZERO) {+ ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 6);++ if (type & SLJIT_SIMD_FLOAT) {+ if (elem_size == 3 && !(srcdst & SLJIT_MEM)) {+ if (lane_index == 1)+ freg += SLJIT_QUAD_OTHER_HALF(freg);++ if (srcdst != freg)+ FAIL_IF(push_inst32(compiler, VORR | VD4(freg) | VN4(srcdst) | VM4(srcdst)));++ freg += SLJIT_QUAD_OTHER_HALF(freg);+ return push_inst32(compiler, VMOV_i | VD4(freg));+ }++ if (srcdst == freg || (elem_size == 3 && srcdst == (freg + SLJIT_QUAD_OTHER_HALF(freg)))) {+ FAIL_IF(push_inst32(compiler, VORR | ins | VD4(TMP_FREG2) | VN4(freg) | VM4(freg)));+ srcdst = TMP_FREG2;+ srcdstw = 0;+ }+ }++ FAIL_IF(push_inst32(compiler, VMOV_i | ins | VD4(freg)));+ }++ if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) {+ lane_index -= (0x8 >> elem_size);+ freg += SLJIT_QUAD_OTHER_HALF(freg);+ }++ if (srcdst & SLJIT_MEM) {+ if (elem_size == 3)+ return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, freg, srcdst, srcdstw);++ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));++ lane_index = lane_index << elem_size;+ ins = (sljit_ins)((elem_size << 10) | (lane_index << 5));+ return push_inst32(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD4(freg) | RN4(srcdst) | 0xf);+ }++ if (type & SLJIT_SIMD_FLOAT) {+ if (elem_size == 3) {+ if (type & SLJIT_SIMD_STORE)+ return push_inst32(compiler, VORR | VD4(srcdst) | VN4(freg) | VM4(freg));+ return push_inst32(compiler, VMOV_F32 | SLJIT_32 | VD4(freg) | VM4(srcdst));+ }++ if (type & SLJIT_SIMD_STORE) {+ if (freg_ebit_map[freg] == 0) {+ if (lane_index == 1)+ freg = SLJIT_F64_SECOND(freg);++ return push_inst32(compiler, VMOV_F32 | VD4(srcdst) | VM4(freg));+ }++ FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN4(freg) | RT4(TMP_REG1)));+ return push_inst32(compiler, VMOV | VN4(srcdst) | RT4(TMP_REG1));+ }++ FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(srcdst) | RT4(TMP_REG1)));+ return push_inst32(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN4(freg) | RT4(TMP_REG1));+ }++ if (srcdst == SLJIT_IMM) {+ if (elem_size < 2)+ srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcdstw));+ srcdst = TMP_REG1;+ }++ if (elem_size == 0)+ ins = 0x400000;+ else if (elem_size == 1)+ ins = 0x20;+ else+ ins = 0;++ lane_index = lane_index << elem_size;+ ins |= (sljit_ins)(((lane_index & 0x4) << 19) | ((lane_index & 0x3) << 5));++ if (type & SLJIT_SIMD_STORE) {+ ins |= (1 << 20);++ if (elem_size < 2 && !(type & SLJIT_SIMD_LANE_SIGNED))+ ins |= (1 << 23);+ }++ return push_inst32(compiler, VMOV_s | ins | VN4(freg) | RT4(srcdst));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_s32 src_lane_index)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index));++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4) {+ freg = simd_get_quad_reg_index(freg);+ src = simd_get_quad_reg_index(src);++ if (src_lane_index >= (0x8 >> elem_size)) {+ src_lane_index -= (0x8 >> elem_size);+ src += SLJIT_QUAD_OTHER_HALF(src);+ }+ }++ if (elem_size == 3) {+ if (freg != src)+ FAIL_IF(push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src)));++ freg += SLJIT_QUAD_OTHER_HALF(freg);++ if (freg != src)+ return push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src));+ return SLJIT_SUCCESS;+ }++ ins = ((((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size));++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 6;++ return push_inst32(compiler, VDUP_s | ins | VD4(freg) | VM4(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);+ sljit_s32 dst_reg;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4)+ freg = simd_get_quad_reg_index(freg);++ if (src & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));+ if (reg_size == 4 && elem2_size - elem_size == 1)+ FAIL_IF(push_inst32(compiler, VLD1 | (0x7 << 8) | VD4(freg) | RN4(src) | 0xf));+ else+ FAIL_IF(push_inst32(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD4(freg) | RN4(src) | 0xf));+ src = freg;+ } else if (reg_size == 4)+ src = simd_get_quad_reg_index(src);++ if (!(type & SLJIT_SIMD_FLOAT)) {+ dst_reg = (reg_size == 4) ? freg : TMP_FREG2;++ do {+ FAIL_IF(push_inst32(compiler, VSHLL | ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0 : (1 << 28))+ | ((sljit_ins)1 << (19 + elem_size)) | VD4(dst_reg) | VM4(src)));+ src = dst_reg;+ } while (++elem_size < elem2_size);++ if (dst_reg == TMP_FREG2)+ return push_inst32(compiler, VORR | VD4(freg) | VN4(TMP_FREG2) | VM4(TMP_FREG2));+ return SLJIT_SUCCESS;+ }++ /* No SIMD variant, must use VFP instead. */+ SLJIT_ASSERT(reg_size == 4);++ if (freg == src) {+ freg += SLJIT_QUAD_OTHER_HALF(freg);+ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src) | 0x20));+ freg += SLJIT_QUAD_OTHER_HALF(freg);+ return push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src));+ }++ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src)));+ freg += SLJIT_QUAD_OTHER_HALF(freg);+ return push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src) | 0x20);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins, imms;+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw));++ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ switch (elem_size) {+ case 0:+ imms = 0x243219;+ ins = VSHR | (1 << 28) | (0x9 << 16);+ break;+ case 1:+ imms = (reg_size == 4) ? 0x243219 : 0x2231;+ ins = VSHR | (1 << 28) | (0x11 << 16);+ break;+ case 2:+ imms = (reg_size == 4) ? 0x2231 : 0x21;+ ins = VSHR | (1 << 28) | (0x21 << 16);+ break;+ default:+ imms = 0x21;+ ins = VSHR | (1 << 28) | (0x1 << 16) | (1 << 7);+ break;+ }++ if (reg_size == 4) {+ freg = simd_get_quad_reg_index(freg);+ ins |= (sljit_ins)1 << 6;+ }++ SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0);+ FAIL_IF(push_inst32(compiler, ins | VD4(TMP_FREG2) | VM4(freg)));++ if (reg_size == 4 && elem_size > 0)+ FAIL_IF(push_inst32(compiler, VMOVN | ((sljit_ins)(elem_size - 1) << 18) | VD4(TMP_FREG2) | VM4(TMP_FREG2)));++ ins = (reg_size == 4 && elem_size == 0) ? (1 << 6) : 0;++ while (imms >= 0x100) {+ FAIL_IF(push_inst32(compiler, VSRA | (1 << 28) | ins | ((imms & 0xff) << 16) | VD4(TMP_FREG2) | VM4(TMP_FREG2)));+ imms >>= 8;+ }++ FAIL_IF(push_inst32(compiler, VSRA | (1 << 28) | ins | (1 << 7) | (imms << 16) | VD4(TMP_FREG2) | VM4(TMP_FREG2)));++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RT4(dst_r) | VN4(TMP_FREG2)));++ if (reg_size == 4 && elem_size == 0) {+ SLJIT_ASSERT(freg_map[TMP_FREG2] + 1 == freg_map[TMP_FREG1]);+ FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RT4(TMP_REG2)| VN4(TMP_FREG1)));+ FAIL_IF(push_inst32(compiler, ORR_W | RD4(dst_r) | RN4(dst_r) | RM4(TMP_REG2) | (0x2 << 12)));+ }++ if (dst_r == TMP_REG1)+ return emit_op_mem(compiler, STORE | WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg));++ if (reg_size != 3 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ switch (SLJIT_SIMD_GET_OPCODE(type)) {+ case SLJIT_SIMD_OP2_AND:+ ins = VAND;+ break;+ case SLJIT_SIMD_OP2_OR:+ ins = VORR;+ break;+ case SLJIT_SIMD_OP2_XOR:+ ins = VEOR;+ break;+ }++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 4) {+ dst_freg = simd_get_quad_reg_index(dst_freg);+ src1_freg = simd_get_quad_reg_index(src1_freg);+ src2_freg = simd_get_quad_reg_index(src2_freg);+ ins |= (sljit_ins)1 << 6;+ }++ return push_inst32(compiler, ins | VD4(dst_freg) | VN4(src1_freg) | VM4(src2_freg));+}++#undef FPU_LOAD++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 mem_reg)+{+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ ins = LDREXB;+ break;+ case SLJIT_MOV_U16:+ ins = LDREXH;+ break;+ default:+ ins = LDREX;+ break;+ }++ return push_inst32(compiler, ins | RN4(mem_reg) | RT4(dst_reg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src_reg,+ sljit_s32 mem_reg,+ sljit_s32 temp_reg)+{+ sljit_ins ins;++ /* temp_reg == mem_reg is undefined so use another temp register */+ SLJIT_UNUSED_ARG(temp_reg);++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ ins = STREXB | RM4(TMP_REG1);+ break;+ case SLJIT_MOV_U16:+ ins = STREXH | RM4(TMP_REG1);+ break;+ default:+ ins = STREX | RD4(TMP_REG1);+ break;+ }++ FAIL_IF(push_inst32(compiler, ins | RN4(mem_reg) | RT4(src_reg)));+ if (op & SLJIT_SET_ATOMIC_STORED)+ return push_inst32(compiler, CMPI_W | RN4(TMP_REG1));++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, (sljit_uw)init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ PTR_FAIL_IF(push_inst16(compiler, RDN3(dst_r)));+ compiler->size += 3;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));+ return jump; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+ src/c/pcre2/src/sljit/sljitNativeLOONGARCH_64.c view
@@ -0,0 +1,3765 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+ return "LOONGARCH" SLJIT_CPUINFO;+}++typedef sljit_u32 sljit_ins;++#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_ZERO 0++/* Flags are kept in volatile registers. */+#define EQUAL_FLAG (SLJIT_NUMBER_OF_REGISTERS + 5)+#define RETURN_ADDR_REG TMP_REG2+#define OTHER_FLAG (SLJIT_NUMBER_OF_REGISTERS + 6)++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {+ 0, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 22, 31, 30, 29, 28, 27, 26, 25, 24, 23, 3, 13, 1, 14, 12, 15+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 31, 30, 29, 28, 27, 26, 25, 24, 8, 9+};++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++/*+LoongArch instructions are 32 bits wide, belonging to 9 basic instruction formats (and variants of them):++| Format name | Composition |+| 2R | Opcode + Rj + Rd |+| 3R | Opcode + Rk + Rj + Rd |+| 4R | Opcode + Ra + Rk + Rj + Rd |+| 2RI8 | Opcode + I8 + Rj + Rd |+| 2RI12 | Opcode + I12 + Rj + Rd |+| 2RI14 | Opcode + I14 + Rj + Rd |+| 2RI16 | Opcode + I16 + Rj + Rd |+| 1RI21 | Opcode + I21L + Rj + I21H |+| I26 | Opcode + I26L + I26H |++Rd is the destination register operand, while Rj, Rk and Ra (“a” stands for “additional”) are the source register operands.+I8/I12/I14/I16/I21/I26 are immediate operands of respective width. The longer I21 and I26 are stored in separate higher and+lower parts in the instruction word, denoted by the “L” and “H” suffixes. */++#define RD(rd) ((sljit_ins)reg_map[rd])+#define RJ(rj) ((sljit_ins)reg_map[rj] << 5)+#define RK(rk) ((sljit_ins)reg_map[rk] << 10)+#define RA(ra) ((sljit_ins)reg_map[ra] << 15)++#define FD(fd) ((sljit_ins)reg_map[fd])+#define FRD(fd) ((sljit_ins)freg_map[fd])+#define FRJ(fj) ((sljit_ins)freg_map[fj] << 5)+#define FRK(fk) ((sljit_ins)freg_map[fk] << 10)+#define FRA(fa) ((sljit_ins)freg_map[fa] << 15)++#define IMM_V(imm) ((sljit_ins)(imm) << 10)+#define IMM_I8(imm) (((sljit_ins)(imm)&0xff) << 10)+#define IMM_I12(imm) (((sljit_ins)(imm)&0xfff) << 10)+#define IMM_I14(imm) (((sljit_ins)(imm)&0xfff3) << 10)+#define IMM_I16(imm) (((sljit_ins)(imm)&0xffff) << 10)+#define IMM_I20(imm) (((sljit_ins)(imm)&0xffffffff) >> 12 << 5)+#define IMM_I21(imm) ((((sljit_ins)(imm)&0xffff) << 10) | (((sljit_ins)(imm) >> 16) & 0x1f))+#define IMM_I26(imm) ((((sljit_ins)(imm)&0xffff) << 10) | (((sljit_ins)(imm) >> 16) & 0x3ff))++#define OPC_I26(opc) ((sljit_ins)(opc) << 26)+#define OPC_1RI21(opc) ((sljit_ins)(opc) << 26)+#define OPC_2RI16(opc) ((sljit_ins)(opc) << 26)+#define OPC_2RI14(opc) ((sljit_ins)(opc) << 24)+#define OPC_2RI12(opc) ((sljit_ins)(opc) << 22)+#define OPC_2RI8(opc) ((sljit_ins)(opc) << 18)+#define OPC_4R(opc) ((sljit_ins)(opc) << 20)+#define OPC_3R(opc) ((sljit_ins)(opc) << 15)+#define OPC_2R(opc) ((sljit_ins)(opc) << 10)+#define OPC_1RI20(opc) ((sljit_ins)(opc) << 25)++/* Arithmetic operation instructions */+#define ADD_W OPC_3R(0x20)+#define ADD_D OPC_3R(0x21)+#define SUB_W OPC_3R(0x22)+#define SUB_D OPC_3R(0x23)+#define ADDI_W OPC_2RI12(0xa)+#define ADDI_D OPC_2RI12(0xb)+#define ANDI OPC_2RI12(0xd)+#define ORI OPC_2RI12(0xe)+#define XORI OPC_2RI12(0xf)+#define ADDU16I_D OPC_2RI16(0x4)+#define LU12I_W OPC_1RI20(0xa)+#define LU32I_D OPC_1RI20(0xb)+#define LU52I_D OPC_2RI12(0xc)+#define SLT OPC_3R(0x24)+#define SLTU OPC_3R(0x25)+#define SLTI OPC_2RI12(0x8)+#define SLTUI OPC_2RI12(0x9)+#define PCADDI OPC_1RI20(0xc)+#define PCALAU12I OPC_1RI20(0xd)+#define PCADDU12I OPC_1RI20(0xe)+#define PCADDU18I OPC_1RI20(0xf)+#define NOR OPC_3R(0x28)+#define AND OPC_3R(0x29)+#define OR OPC_3R(0x2a)+#define XOR OPC_3R(0x2b)+#define ORN OPC_3R(0x2c)+#define ANDN OPC_3R(0x2d)+#define MUL_W OPC_3R(0x38)+#define MULH_W OPC_3R(0x39)+#define MULH_WU OPC_3R(0x3a)+#define MUL_D OPC_3R(0x3b)+#define MULH_D OPC_3R(0x3c)+#define MULH_DU OPC_3R(0x3d)+#define MULW_D_W OPC_3R(0x3e)+#define MULW_D_WU OPC_3R(0x3f)+#define DIV_W OPC_3R(0x40)+#define MOD_W OPC_3R(0x41)+#define DIV_WU OPC_3R(0x42)+#define MOD_WU OPC_3R(0x43)+#define DIV_D OPC_3R(0x44)+#define MOD_D OPC_3R(0x45)+#define DIV_DU OPC_3R(0x46)+#define MOD_DU OPC_3R(0x47)++/* Bit-shift instructions */+#define SLL_W OPC_3R(0x2e)+#define SRL_W OPC_3R(0x2f)+#define SRA_W OPC_3R(0x30)+#define SLL_D OPC_3R(0x31)+#define SRL_D OPC_3R(0x32)+#define SRA_D OPC_3R(0x33)+#define ROTR_W OPC_3R(0x36)+#define ROTR_D OPC_3R(0x37)+#define SLLI_W OPC_3R(0x81)+#define SLLI_D ((sljit_ins)(0x41) << 16)+#define SRLI_W OPC_3R(0x89)+#define SRLI_D ((sljit_ins)(0x45) << 16)+#define SRAI_W OPC_3R(0x91)+#define SRAI_D ((sljit_ins)(0x49) << 16)+#define ROTRI_W OPC_3R(0x99)+#define ROTRI_D ((sljit_ins)(0x4d) << 16)++/* Bit-manipulation instructions */+#define CLO_W OPC_2R(0x4)+#define CLZ_W OPC_2R(0x5)+#define CTO_W OPC_2R(0x6)+#define CTZ_W OPC_2R(0x7)+#define CLO_D OPC_2R(0x8)+#define CLZ_D OPC_2R(0x9)+#define CTO_D OPC_2R(0xa)+#define CTZ_D OPC_2R(0xb)+#define REVB_2H OPC_2R(0xc)+#define REVB_4H OPC_2R(0xd)+#define REVB_2W OPC_2R(0xe)+#define REVB_D OPC_2R(0xf)+#define REVH_2W OPC_2R(0x10)+#define REVH_D OPC_2R(0x11)+#define BITREV_4B OPC_2R(0x12)+#define BITREV_8B OPC_2R(0x13)+#define BITREV_W OPC_2R(0x14)+#define BITREV_D OPC_2R(0x15)+#define EXT_W_H OPC_2R(0x16)+#define EXT_W_B OPC_2R(0x17)+#define BSTRINS_W (0x1 << 22 | 1 << 21)+#define BSTRPICK_W (0x1 << 22 | 1 << 21 | 1 << 15)+#define BSTRINS_D (0x2 << 22)+#define BSTRPICK_D (0x3 << 22)++/* Branch instructions */+#define BEQZ OPC_1RI21(0x10)+#define BNEZ OPC_1RI21(0x11)+#define JIRL OPC_2RI16(0x13)+#define B OPC_I26(0x14)+#define BL OPC_I26(0x15)+#define BEQ OPC_2RI16(0x16)+#define BNE OPC_2RI16(0x17)+#define BLT OPC_2RI16(0x18)+#define BGE OPC_2RI16(0x19)+#define BLTU OPC_2RI16(0x1a)+#define BGEU OPC_2RI16(0x1b)++/* Memory access instructions */+#define LD_B OPC_2RI12(0xa0)+#define LD_H OPC_2RI12(0xa1)+#define LD_W OPC_2RI12(0xa2)+#define LD_D OPC_2RI12(0xa3)++#define ST_B OPC_2RI12(0xa4)+#define ST_H OPC_2RI12(0xa5)+#define ST_W OPC_2RI12(0xa6)+#define ST_D OPC_2RI12(0xa7)++#define LD_BU OPC_2RI12(0xa8)+#define LD_HU OPC_2RI12(0xa9)+#define LD_WU OPC_2RI12(0xaa)++#define LDX_B OPC_3R(0x7000)+#define LDX_H OPC_3R(0x7008)+#define LDX_W OPC_3R(0x7010)+#define LDX_D OPC_3R(0x7018)++#define STX_B OPC_3R(0x7020)+#define STX_H OPC_3R(0x7028)+#define STX_W OPC_3R(0x7030)+#define STX_D OPC_3R(0x7038)++#define LDX_BU OPC_3R(0x7040)+#define LDX_HU OPC_3R(0x7048)+#define LDX_WU OPC_3R(0x7050)++#define PRELD OPC_2RI12(0xab)++/* Atomic memory access instructions */+#define LL_W OPC_2RI14(0x20)+#define SC_W OPC_2RI14(0x21)+#define LL_D OPC_2RI14(0x22)+#define SC_D OPC_2RI14(0x23)++/* LoongArch V1.10 Instructions */+#define AMCAS_B OPC_3R(0x70B0)+#define AMCAS_H OPC_3R(0x70B1)+#define AMCAS_W OPC_3R(0x70B2)+#define AMCAS_D OPC_3R(0x70B3)++/* Other instructions */+#define BREAK OPC_3R(0x54)+#define DBGCALL OPC_3R(0x55)+#define SYSCALL OPC_3R(0x56)++/* Basic Floating-Point Instructions */+/* Floating-Point Arithmetic Operation Instructions */+#define FADD_S OPC_3R(0x201)+#define FADD_D OPC_3R(0x202)+#define FSUB_S OPC_3R(0x205)+#define FSUB_D OPC_3R(0x206)+#define FMUL_S OPC_3R(0x209)+#define FMUL_D OPC_3R(0x20a)+#define FDIV_S OPC_3R(0x20d)+#define FDIV_D OPC_3R(0x20e)+#define FCMP_COND_S OPC_4R(0xc1)+#define FCMP_COND_D OPC_4R(0xc2)+#define FCOPYSIGN_S OPC_3R(0x225)+#define FCOPYSIGN_D OPC_3R(0x226)+#define FSEL OPC_4R(0xd0)+#define FABS_S OPC_2R(0x4501)+#define FABS_D OPC_2R(0x4502)+#define FNEG_S OPC_2R(0x4505)+#define FNEG_D OPC_2R(0x4506)+#define FMOV_S OPC_2R(0x4525)+#define FMOV_D OPC_2R(0x4526)++/* Floating-Point Conversion Instructions */+#define FCVT_S_D OPC_2R(0x4646)+#define FCVT_D_S OPC_2R(0x4649)+#define FTINTRZ_W_S OPC_2R(0x46a1)+#define FTINTRZ_W_D OPC_2R(0x46a2)+#define FTINTRZ_L_S OPC_2R(0x46a9)+#define FTINTRZ_L_D OPC_2R(0x46aa)+#define FFINT_S_W OPC_2R(0x4744)+#define FFINT_S_L OPC_2R(0x4746)+#define FFINT_D_W OPC_2R(0x4748)+#define FFINT_D_L OPC_2R(0x474a)++/* Floating-Point Move Instructions */+#define FMOV_S OPC_2R(0x4525)+#define FMOV_D OPC_2R(0x4526)+#define MOVGR2FR_W OPC_2R(0x4529)+#define MOVGR2FR_D OPC_2R(0x452a)+#define MOVGR2FRH_W OPC_2R(0x452b)+#define MOVFR2GR_S OPC_2R(0x452d)+#define MOVFR2GR_D OPC_2R(0x452e)+#define MOVFRH2GR_S OPC_2R(0x452f)+#define MOVGR2FCSR OPC_2R(0x4530)+#define MOVFCSR2GR OPC_2R(0x4532)+#define MOVFR2CF OPC_2R(0x4534)+#define MOVCF2FR OPC_2R(0x4535)+#define MOVGR2CF OPC_2R(0x4536)+#define MOVCF2GR OPC_2R(0x4537)++/* Floating-Point Branch Instructions */+#define BCEQZ OPC_I26(0x12)+#define BCNEZ OPC_I26(0x12)++/* Floating-Point Common Memory Access Instructions */+#define FLD_S OPC_2RI12(0xac)+#define FLD_D OPC_2RI12(0xae)+#define FST_S OPC_2RI12(0xad)+#define FST_D OPC_2RI12(0xaf)++#define FLDX_S OPC_3R(0x7060)+#define FLDX_D OPC_3R(0x7068)+#define FSTX_S OPC_3R(0x7070)+#define FSTX_D OPC_3R(0x7078)++/* Vector Instructions */++/* Vector Arithmetic Instructions */+#define VOR_V OPC_3R(0xe24d)+#define VXOR_V OPC_3R(0xe24e)+#define VAND_V OPC_3R(0xe24c)+#define VMSKLTZ OPC_2R(0x1ca710)++/* Vector Memory Access Instructions */+#define VLD OPC_2RI12(0xb0)+#define VST OPC_2RI12(0xb1)+#define XVLD OPC_2RI12(0xb2)+#define XVST OPC_2RI12(0xb3)+#define VSTELM OPC_2RI8(0xc40)++/* Vector Float Conversion Instructions */+#define VFCVTL_D_S OPC_2R(0x1ca77c)++/* Vector Bit Manipulate Instructions */+#define VSLLWIL OPC_2R(0x1cc200)++/* Vector Move And Shuffle Instructions */+#define VLDREPL OPC_2R(0xc0000)+#define VINSGR2VR OPC_2R(0x1cbac0)+#define VPICKVE2GR_U OPC_2R(0x1cbce0)+#define VREPLGR2VR OPC_2R(0x1ca7c0)+#define VREPLVE OPC_3R(0xe244)+#define VREPLVEI OPC_2R(0x1cbde0)+#define XVPERMI OPC_2RI8(0x1dfa)++#define I12_MAX (0x7ff)+#define I12_MIN (-0x800)+#define BRANCH16_MAX (0x7fff << 2)+#define BRANCH16_MIN (-(0x8000 << 2))+#define BRANCH21_MAX (0xfffff << 2)+#define BRANCH21_MIN (-(0x100000 << 2))+#define JUMP_MAX (0x1ffffff << 2)+#define JUMP_MIN (-(0x2000000 << 2))+#define JIRL_MAX (0x7fff << 2)+#define JIRL_MIN (-(0x8000 << 2))++#define S32_MAX (0x7fffffffl)+#define S32_MIN (-0x80000000l)+#define S52_MAX (0x7ffffffffffffl)++#define INST(inst, type) ((sljit_ins)((type & SLJIT_32) ? inst##_W : inst##_D))++/* LoongArch CPUCFG register for feature detection */+#define LOONGARCH_CFG2 0x02+#define LOONGARCH_CFG2_LAMCAS (1 << 28)++static sljit_u32 cfg2_feature_list = 0;++/* According to Software Development and Build Convention for LoongArch Architectures,++ the status of LSX and LASX extension must be checked through HWCAP */+#include <sys/auxv.h>++#define LOONGARCH_HWCAP_LSX (1 << 4)+#define LOONGARCH_HWCAP_LASX (1 << 5)++static sljit_u32 hwcap_feature_list = 0;++/* Feature type */+#define GET_CFG2 0+#define GET_HWCAP 1++static SLJIT_INLINE sljit_u32 get_cpu_features(sljit_u32 feature_type)+ {+ if (cfg2_feature_list == 0)+ __asm__ ("cpucfg %0, %1" : "+&r"(cfg2_feature_list) : "r"(LOONGARCH_CFG2));+ if (hwcap_feature_list == 0)+ hwcap_feature_list = (sljit_u32)getauxval(AT_HWCAP);++ return feature_type ? hwcap_feature_list : cfg2_feature_list;+ }++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);+ *ptr = ins;+ compiler->size++;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_sw diff;+ sljit_uw target_addr;+ sljit_ins *inst;++ inst = (sljit_ins *)jump->addr;++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ goto exit;++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->u.label != NULL);+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;+ }++ diff = (sljit_sw)target_addr - (sljit_sw)inst - executable_offset;++ if (jump->flags & IS_COND) {+ diff += SSIZE_OF(ins);++ if (diff >= BRANCH16_MIN && diff <= BRANCH16_MAX) {+ inst--;+ inst[0] = (inst[0] & 0xfc0003ff) ^ 0x4000000;+ jump->flags |= PATCH_B;+ jump->addr = (sljit_uw)inst;+ return inst;+ }++ diff -= SSIZE_OF(ins);+ }++ if (diff >= JUMP_MIN && diff <= JUMP_MAX) {+ if (jump->flags & IS_COND) {+ inst[-1] |= (sljit_ins)IMM_I16(2);+ }++ jump->flags |= PATCH_J;+ return inst;+ }++ if (diff >= S32_MIN && diff <= S32_MAX) {+ if (jump->flags & IS_COND)+ inst[-1] |= (sljit_ins)IMM_I16(3);++ jump->flags |= PATCH_REL32;+ inst[1] = inst[0];+ return inst + 1;+ }++ if (target_addr <= (sljit_uw)S32_MAX) {+ if (jump->flags & IS_COND)+ inst[-1] |= (sljit_ins)IMM_I16(3);++ jump->flags |= PATCH_ABS32;+ inst[1] = inst[0];+ return inst + 1;+ }++ if (target_addr <= S52_MAX) {+ if (jump->flags & IS_COND)+ inst[-1] |= (sljit_ins)IMM_I16(4);++ jump->flags |= PATCH_ABS52;+ inst[2] = inst[0];+ return inst + 2;+ }++exit:+ if (jump->flags & IS_COND)+ inst[-1] |= (sljit_ins)IMM_I16(5);+ inst[3] = inst[0];+ return inst + 3;+}++static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_uw addr;+ sljit_sw diff;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT));+ if (jump->flags & JUMP_ADDR)+ addr = jump->u.target;+ else+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ if (diff >= S32_MIN && diff <= S32_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_REL32;+ return 1;+ }++ if (addr <= S32_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS32;+ return 1;+ }++ if (addr <= S52_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)2 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS52;+ return 2;+ }++ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));+ return 3;+}++static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw executable_offset)+{+ sljit_uw flags = jump->flags;+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;+ sljit_ins *ins = (sljit_ins*)jump->addr;+ sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : TMP_REG1;+ SLJIT_UNUSED_ARG(executable_offset);++ if (flags & PATCH_REL32) {+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);++ SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX);++ if ((addr & 0x800) != 0)+ addr += 0x1000;++ ins[0] = PCADDU12I | RD(reg) | IMM_I20(addr);++ if (!(flags & JUMP_MOV_ADDR)) {+ SLJIT_ASSERT((ins[1] & OPC_2RI16(0x3f)) == JIRL);+ ins[1] = (ins[1] & (OPC_2RI16(0x3f) | 0x3ff)) | IMM_I16((addr & 0xfff) >> 2);+ } else+ ins[1] = ADDI_D | RD(reg) | RJ(reg) | IMM_I12(addr);+ return;+ }++ if (flags & PATCH_ABS32) {+ SLJIT_ASSERT(addr <= S32_MAX);+ ins[0] = LU12I_W | RD(reg) | (sljit_ins)(((addr & 0xffffffff) >> 12) << 5);+ } else if (flags & PATCH_ABS52) {+ ins[0] = LU12I_W | RD(reg) | (sljit_ins)(((addr & 0xffffffff) >> 12) << 5);+ ins[1] = LU32I_D | RD(reg) | (sljit_ins)(((addr >> 32) & 0xfffff) << 5);+ ins += 1;+ } else {+ ins[0] = LU12I_W | RD(reg) | (sljit_ins)(((addr & 0xffffffff) >> 12) << 5);+ ins[1] = LU32I_D | RD(reg) | (sljit_ins)(((addr >> 32) & 0xfffff) << 5);+ ins[2] = LU52I_D | RD(reg) | RJ(reg) | IMM_I12(addr >> 52);+ ins += 2;+ }++ if (!(flags & JUMP_MOV_ADDR)) {+ SLJIT_ASSERT((ins[1] & OPC_2RI16(0x3f)) == JIRL);+ ins[1] = (ins[1] & (OPC_2RI16(0x3f) | 0x3ff)) | IMM_I16((addr & 0xfff) >> 2);+ } else+ ins[1] = ORI | RD(reg) | RJ(reg) | IMM_I12(addr);+}++static void reduce_code_size(struct sljit_compiler *compiler)+{+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_uw total_size;+ sljit_uw size_reduce = 0;+ sljit_sw diff;++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;++ SLJIT_NEXT_INIT_TYPES();++ while (1) {+ SLJIT_GET_NEXT_MIN();++ if (next_min_addr == SLJIT_MAX_ADDRESS)+ break;++ if (next_min_addr == next_label_size) {+ label->size -= size_reduce;++ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_const_addr) {+ const_->addr -= size_reduce;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ continue;+ }++ if (next_min_addr != next_jump_addr)+ continue;++ jump->addr -= size_reduce;+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ total_size = JUMP_MAX_SIZE;++ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {+ if (jump->flags & JUMP_ADDR) {+ if (jump->u.target <= S32_MAX)+ total_size = 2;+ else if (jump->u.target <= S52_MAX)+ total_size = 3;+ } else {+ /* Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;++ if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH16_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH16_MIN / SSIZE_OF(ins)))+ total_size = 0;+ else if (diff >= (JUMP_MIN / SSIZE_OF(ins)) && diff <= (JUMP_MAX / SSIZE_OF(ins)))+ total_size = 1;+ else if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))+ total_size = 2;+ }+ }++ size_reduce += JUMP_MAX_SIZE - total_size;+ jump->flags |= total_size << JUMP_SIZE_SHIFT;+ } else {+ total_size = 3;++ if (!(jump->flags & JUMP_ADDR)) {+ /* Real size minus 1. Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;++ if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))+ total_size = 1;+ } else if (jump->u.target < S32_MAX)+ total_size = 1;+ else if (jump->u.target <= S52_MAX)+ total_size = 2;++ size_reduce += 3 - total_size;+ jump->flags |= total_size << JUMP_SIZE_SHIFT;+ }++ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ }++ compiler->size -= size_reduce;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_sw executable_offset;+ sljit_uw addr;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));++ reduce_code_size(compiler);++ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);+ PTR_FAIL_WITH_EXEC_IF(code);++ reverse_buf(compiler);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();+ SLJIT_GET_NEXT_MIN();++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ *code_ptr = *buf_ptr++;+ if (next_min_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);++ /* These structures are ordered by their address. */+ if (next_min_addr == next_label_size) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_jump_addr) {+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);+ jump->addr = (sljit_uw)code_ptr;+ code_ptr = detect_jump_type(jump, code, executable_offset);+ SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));+ } else {+ word_count += jump->flags >> JUMP_SIZE_SHIFT;+ addr = (sljit_uw)code_ptr;+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);+ jump->addr = addr;+ }+ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ } else if (next_min_addr == next_const_addr) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ }++ SLJIT_GET_NEXT_MIN();+ }+ code_ptr++;+ word_count++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->u.addr = (sljit_uw)code_ptr;+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ do {+ if (!(jump->flags & (PATCH_B | PATCH_J)) || (jump->flags & JUMP_MOV_ADDR)) {+ load_addr_to_reg(jump, executable_offset);+ break;+ }++ addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;+ buf_ptr = (sljit_ins *)jump->addr;+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);++ if (jump->flags & PATCH_B) {+ SLJIT_ASSERT((sljit_sw)addr >= BRANCH16_MIN && (sljit_sw)addr <= BRANCH16_MAX);+ buf_ptr[0] |= (sljit_ins)IMM_I16(addr >> 2);+ break;+ }++ SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX);+ if (jump->flags & IS_CALL)+ buf_ptr[0] = BL | (sljit_ins)IMM_I26(addr >> 2);+ else+ buf_ptr[0] = B | (sljit_ins)IMM_I26(addr >> 2);+ } while (0);+ jump = jump->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (sljit_uw)(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);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ 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) != 0;+#else+ /* Available by default. */+ return 1;+#endif++ case SLJIT_HAS_LASX:+ return (LOONGARCH_HWCAP_LASX & get_cpu_features(GET_HWCAP));++ case SLJIT_HAS_SIMD:+ return (LOONGARCH_HWCAP_LSX & get_cpu_features(GET_HWCAP));++ case SLJIT_HAS_ATOMIC:+ return (LOONGARCH_CFG2_LAMCAS & get_cpu_features(GET_CFG2));++ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CTZ:+ case SLJIT_HAS_REV:+ case SLJIT_HAS_ROT:+ case SLJIT_HAS_PREFETCH:+ case SLJIT_HAS_COPY_F32:+ case SLJIT_HAS_COPY_F64:+ return 1;++ default:+ return 0;+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)+{+ SLJIT_UNUSED_ARG(type);++ return 0;+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++/* Creates an index in data_transfer_insts array. */+#define LOAD_DATA 0x01+#define WORD_DATA 0x00+#define BYTE_DATA 0x02+#define HALF_DATA 0x04+#define INT_DATA 0x06+#define SIGNED_DATA 0x08+/* Separates integer and floating point registers */+#define GPR_REG 0x0f+#define DOUBLE_DATA 0x10+#define SINGLE_DATA 0x12++#define MEM_MASK 0x1f++#define ARG_TEST 0x00020+#define ALT_KEEP_CACHE 0x00040+#define CUMULATIVE_OP 0x00080+#define IMM_OP 0x00100+#define MOVE_OP 0x00200+#define SRC2_IMM 0x00400++#define UNUSED_DEST 0x00800+#define REG_DEST 0x01000+#define REG1_SOURCE 0x02000+#define REG2_SOURCE 0x04000+#define SLOW_SRC1 0x08000+#define SLOW_SRC2 0x10000+#define SLOW_DEST 0x20000+#define MEM_USE_TMP2 0x40000++#define STACK_STORE ST_D+#define STACK_LOAD LD_D++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm)+{+ if (imm <= I12_MAX && imm >= I12_MIN)+ return push_inst(compiler, ADDI_D | RD(dst_r) | RJ(TMP_ZERO) | IMM_I12(imm));++ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {+ FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));+ return push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm));+ } else if (imm <= 0x7ffffffffffffl && imm >= -0x8000000000000l) {+ FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));+ FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm)));+ return push_inst(compiler, LU32I_D | RD(dst_r) | (sljit_ins)(((imm >> 32) & 0xfffff) << 5));+ }+ FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));+ FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm)));+ FAIL_IF(push_inst(compiler, LU32I_D | RD(dst_r) | (sljit_ins)(((imm >> 32) & 0xfffff) << 5)));+ return push_inst(compiler, LU52I_D | RD(dst_r) | RJ(dst_r) | IMM_I12(imm >> 52));+}++#define STACK_MAX_DISTANCE (-I12_MIN)++static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw);++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 i, tmp, offset;+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);++ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;+ compiler->local_size = local_size;++ if (local_size <= STACK_MAX_DISTANCE) {+ /* Frequent case. */+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(-local_size)));+ offset = local_size - SSIZE_OF(sw);+ local_size = 0;+ } else {+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(STACK_MAX_DISTANCE)));+ local_size -= STACK_MAX_DISTANCE;++ if (local_size > STACK_MAX_DISTANCE)+ FAIL_IF(load_immediate(compiler, TMP_REG1, local_size));+ offset = STACK_MAX_DISTANCE - SSIZE_OF(sw);+ }++ FAIL_IF(push_inst(compiler, STACK_STORE | RD(RETURN_ADDR_REG) | RJ(SLJIT_SP) | IMM_I12(offset)));++ tmp = SLJIT_S0 - saveds;+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_STORE | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_STORE | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));+ }++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, FST_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));+ }++ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, FST_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));+ }++ if (local_size > STACK_MAX_DISTANCE)+ FAIL_IF(push_inst(compiler, SUB_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | RK(TMP_REG1)));+ else if (local_size > 0)+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(-local_size)));++ if (options & SLJIT_ENTER_REG_ARG)+ return SLJIT_SUCCESS;++ arg_types >>= SLJIT_ARG_SHIFT;+ saved_arg_count = 0;+ tmp = SLJIT_R0;++ while (arg_types > 0) {+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_S0 - saved_arg_count) | RJ(tmp) | IMM_I12(0)));+ saved_arg_count++;+ }+ tmp++;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++#undef STACK_MAX_DISTANCE++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);++ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;++ return SLJIT_SUCCESS;+}++#define STACK_MAX_DISTANCE (-I12_MIN - 16)++static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)+{+ sljit_s32 i, tmp, offset;+ sljit_s32 local_size = compiler->local_size;++ if (local_size > STACK_MAX_DISTANCE) {+ local_size -= STACK_MAX_DISTANCE;++ if (local_size > STACK_MAX_DISTANCE) {+ FAIL_IF(load_immediate(compiler, TMP_REG2, local_size));+ FAIL_IF(push_inst(compiler, ADD_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | RK(TMP_REG2)));+ } else+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(local_size)));++ local_size = STACK_MAX_DISTANCE;+ }++ SLJIT_ASSERT(local_size > 0);++ offset = local_size - SSIZE_OF(sw);+ if (!is_return_to)+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RJ(SLJIT_SP) | IMM_I12(offset)));++ tmp = SLJIT_S0 - compiler->saveds;+ for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));+ }++ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));+ }++ tmp = SLJIT_FS0 - compiler->fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, FLD_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));+ }++ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, FLD_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));+ }++ return push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(local_size));+}++#undef STACK_MAX_DISTANCE++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ FAIL_IF(emit_stack_frame_release(compiler, 0));+ return push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(RETURN_ADDR_REG) | IMM_I12(0));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));+ src = TMP_REG1;+ srcw = 0;+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(src) | IMM_I12(0)));+ src = TMP_REG1;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 1));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++static const sljit_ins data_transfer_insts[16 + 4] = {+/* u w s */ ST_D /* st.d */,+/* u w l */ LD_D /* ld.d */,+/* u b s */ ST_B /* st.b */,+/* u b l */ LD_BU /* ld.bu */,+/* u h s */ ST_H /* st.h */,+/* u h l */ LD_HU /* ld.hu */,+/* u i s */ ST_W /* st.w */,+/* u i l */ LD_WU /* ld.wu */,++/* s w s */ ST_D /* st.d */,+/* s w l */ LD_D /* ld.d */,+/* s b s */ ST_B /* st.b */,+/* s b l */ LD_B /* ld.b */,+/* s h s */ ST_H /* st.h */,+/* s h l */ LD_H /* ld.h */,+/* s i s */ ST_W /* st.w */,+/* s i l */ LD_W /* ld.w */,++/* d s */ FST_D /* fst.d */,+/* d l */ FLD_D /* fld.d */,+/* s s */ FST_S /* fst.s */,+/* s l */ FLD_S /* fld.s */,+};++static const sljit_ins data_transfer_insts_x[16 + 4] = {+/* u w s */ STX_D /* stx.d */,+/* u w l */ LDX_D /* ldx.d */,+/* u b s */ STX_B /* stx.b */,+/* u b l */ LDX_BU /* ldx.bu */,+/* u h s */ STX_H /* stx.h */,+/* u h l */ LDX_HU /* ldx.hu */,+/* u i s */ STX_W /* stx.w */,+/* u i l */ LDX_WU /* ldx.wu */,++/* s w s */ STX_D /* stx.d */,+/* s w l */ LDX_D /* ldx.d */,+/* s b s */ STX_B /* stx.b */,+/* s b l */ LDX_B /* ldx.b */,+/* s h s */ STX_H /* stx.h */,+/* s h l */ LDX_H /* ldx.h */,+/* s i s */ STX_W /* stx.w */,+/* s i l */ LDX_W /* ldx.w */,++/* d s */ FSTX_D /* fstx.d */,+/* d l */ FLDX_D /* fldx.d */,+/* s s */ FSTX_S /* fstx.s */,+/* s l */ FLDX_S /* fldx.s */,+};++static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ sljit_ins ins;+ sljit_s32 base = arg & REG_MASK;++ SLJIT_ASSERT(arg & SLJIT_MEM);++ if (arg & OFFS_REG_MASK) {+ sljit_s32 offs = OFFS_REG(arg);++ SLJIT_ASSERT(!argw);+ ins = data_transfer_insts_x[flags & MEM_MASK] |+ ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) |+ RJ(base) | RK(offs);+ } else {+ SLJIT_ASSERT(argw <= 0xfff && argw >= I12_MIN);++ ins = data_transfer_insts[flags & MEM_MASK] |+ ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) |+ RJ(base) | IMM_I12(argw);+ }+ return push_inst(compiler, ins);+}++/* Can perform an operation using at most 1 instruction. */+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);++ /* argw == 0 (ldx/stx rd, rj, rk) can be used.+ * argw in [-2048, 2047] (ld/st rd, rj, imm) can be used. */+ if (!argw || (!(arg & OFFS_REG_MASK) && (argw <= I12_MAX && argw >= I12_MIN))) {+ /* Works for both absolute and relative addresses. */+ if (SLJIT_UNLIKELY(flags & ARG_TEST))+ return 1;++ FAIL_IF(push_mem_inst(compiler, flags, reg, arg, argw));+ return -1;+ }+ return 0;+}++#define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0))++/* See getput_arg below.+ Note: can_cache is called only for binary operators. */+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));++ if (arg & OFFS_REG_MASK)+ return 0;++ if (arg == next_arg) {+ if (((next_argw - argw) <= I12_MAX && (next_argw - argw) >= I12_MIN)+ || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))+ return 1;+ return 0;+ }++ return 0;+}++/* Emit the necessary instructions. See can_cache above. */+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_s32 base = arg & REG_MASK;+ sljit_s32 tmp_r = (flags & MEM_USE_TMP2) ? TMP_REG2 : TMP_REG1;+ sljit_sw offset;++ SLJIT_ASSERT(arg & SLJIT_MEM);+ if (!(next_arg & SLJIT_MEM)) {+ next_arg = 0;+ next_argw = 0;+ }++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ if (SLJIT_UNLIKELY(argw))+ FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG3) | RJ(OFFS_REG(arg)) | IMM_I12(argw)));+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, TMP_REG3), 0);+ }++ if (compiler->cache_arg == arg && argw - compiler->cache_argw <= I12_MAX && argw - compiler->cache_argw >= I12_MIN)+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(TMP_REG3), argw - compiler->cache_argw);++ if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw <= I12_MAX) && (argw - compiler->cache_argw >= I12_MIN)) {+ offset = argw - compiler->cache_argw;+ } else {+ sljit_sw argw_hi=TO_ARGW_HI(argw);+ compiler->cache_arg = SLJIT_MEM;++ if (next_arg && next_argw - argw <= I12_MAX && next_argw - argw >= I12_MIN && argw_hi != TO_ARGW_HI(next_argw)) {+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw));+ compiler->cache_argw = argw;+ offset = 0;+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi));+ compiler->cache_argw = argw_hi;+ offset = argw & 0xfff;+ argw = argw_hi;+ }+ }++ if (!base)+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(TMP_REG3), offset);++ if (arg == next_arg && next_argw - argw <= I12_MAX && next_argw - argw >= I12_MIN) {+ compiler->cache_arg = arg;+ FAIL_IF(push_inst(compiler, ADD_D | RD(TMP_REG3) | RJ(TMP_REG3) | RK(base)));+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(TMP_REG3), offset);+ }++ if (!offset)+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, TMP_REG3), 0);++ FAIL_IF(push_inst(compiler, ADD_D | RD(tmp_r) | RJ(TMP_REG3) | RK(base)));+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(tmp_r), offset);+}++static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ sljit_s32 base = arg & REG_MASK;+ sljit_s32 tmp_r = TMP_REG1;++ if (getput_arg_fast(compiler, flags, reg, arg, argw))+ return compiler->error;++ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))+ tmp_r = reg;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ if (SLJIT_UNLIKELY(argw))+ FAIL_IF(push_inst(compiler, SLLI_D | RD(tmp_r) | RJ(OFFS_REG(arg)) | IMM_I12(argw)));+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, tmp_r), 0);+ } else {+ FAIL_IF(load_immediate(compiler, tmp_r, argw));++ if (base != 0)+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, tmp_r), 0);+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(tmp_r), 0);+ }+}++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);+}++#define IMM_EXTEND(v) (IMM_I12((op & SLJIT_32) ? (v) : (32 + (v))))++/* andi/ori/xori are zero-extended */+#define EMIT_LOGICAL(op_imm, op_reg) \+ if (flags & SRC2_IMM) { \+ if (op & SLJIT_SET_Z) {\+ FAIL_IF(push_inst(compiler, ADDI_D | RD(EQUAL_FLAG) | RJ(TMP_ZERO) | IMM_I12(src2))); \+ FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG))); \+ } \+ if (!(flags & UNUSED_DEST)) { \+ if (dst == src1) { \+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(TMP_ZERO) | IMM_I12(src2))); \+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(TMP_REG1))); \+ } else { \+ FAIL_IF(push_inst(compiler, ADDI_D | RD(dst) | RJ(TMP_ZERO) | IMM_I12(src2))); \+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(dst))); \+ } \+ } \+ } else { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(src2))); \+ } \+ while (0)++#define EMIT_SHIFT(imm, reg) \+ op_imm = (imm); \+ op_reg = (reg)++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, carry_src_r, is_handled, reg;+ sljit_ins op_imm, op_reg;+ sljit_ins word_size = ((op & SLJIT_32) ? 32 : 64);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if (dst != src2)+ return push_inst(compiler, INST(ADD, op) | RD(dst) | RJ(src2) | IMM_I12(0));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, ANDI | RD(dst) | RJ(src2) | IMM_I12(0xff));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, EXT_W_B | RD(dst) | RJ(src2));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, INST(BSTRPICK, op) | RD(dst) | RJ(src2) | (15 << 16));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, EXT_W_H | RD(dst) | RJ(src2));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U32:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, BSTRPICK_D | RD(dst) | RJ(src2) | (31 << 16));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_S32:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, SLLI_W | RD(dst) | RJ(src2) | IMM_I12(0));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_CLZ:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ return push_inst(compiler, INST(CLZ, op) | RD(dst) | RJ(src2));++ case SLJIT_CTZ:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ return push_inst(compiler, INST(CTZ, op) | RD(dst) | RJ(src2));++ case SLJIT_REV:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ return push_inst(compiler, ((op & SLJIT_32) ? REVB_2W : REVB_D) | RD(dst) | RJ(src2));++ case SLJIT_REV_S16:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ FAIL_IF(push_inst(compiler, REVB_2H | RD(dst) | RJ(src2)));+ return push_inst(compiler, EXT_W_H | RD(dst) | RJ(dst));++ case SLJIT_REV_U16:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ FAIL_IF(push_inst(compiler, REVB_2H | RD(dst) | RJ(src2)));+ return push_inst(compiler, INST(BSTRPICK, op) | RD(dst) | RJ(dst) | (15 << 16));++ case SLJIT_REV_S32:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1);+ FAIL_IF(push_inst(compiler, REVB_2W | RD(dst) | RJ(src2)));+ return push_inst(compiler, SLLI_W | RD(dst) | RJ(dst) | IMM_I12(0));++ case SLJIT_REV_U32:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1);+ FAIL_IF(push_inst(compiler, REVB_2W | RD(dst) | RJ(src2)));+ return push_inst(compiler, BSTRPICK_D | RD(dst) | RJ(dst) | (31 << 16));++ case SLJIT_ADD:+ /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0)));+ else {+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(TMP_ZERO) | IMM_I12(-1)));+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG)));+ }+ } else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(src2)));++ /* Only the zero flag is needed. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(src2)));+ } else {+ if (is_overflow)+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, INST(ADD, op) | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));++ if (is_overflow || carry_src_r != 0) {+ if (src1 != dst)+ carry_src_r = (sljit_s32)src1;+ else if (src2 != dst)+ carry_src_r = (sljit_s32)src2;+ else {+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(0)));+ carry_src_r = OTHER_FLAG;+ }+ }++ /* Only the zero flag is needed. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, INST(ADD, op) | RD(dst) | RJ(src1) | RK(src2)));+ }++ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */+ if (is_overflow || carry_src_r != 0) {+ if (flags & SRC2_IMM)+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(dst) | IMM_I12(src2)));+ else+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(dst) | RK(carry_src_r)));+ }++ if (!is_overflow)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RJ(dst) | RK(EQUAL_FLAG)));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, INST(ADD, op) | RD(EQUAL_FLAG) | RJ(dst) | IMM_I12(0)));+ FAIL_IF(push_inst(compiler, INST(SRLI, op) | RD(TMP_REG1) | RJ(TMP_REG1) | IMM_EXTEND(31)));+ return push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(TMP_REG1) | RK(OTHER_FLAG));++ case SLJIT_ADDC:+ carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ FAIL_IF(push_inst(compiler, ADDI_D | RD(dst) | RJ(src1) | IMM_I12(src2)));+ } else {+ if (carry_src_r != 0) {+ if (src1 != dst)+ carry_src_r = (sljit_s32)src1;+ else if (src2 != dst)+ carry_src_r = (sljit_s32)src2;+ else {+ FAIL_IF(push_inst(compiler, ADDI_D | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0)));+ carry_src_r = EQUAL_FLAG;+ }+ }++ FAIL_IF(push_inst(compiler, ADD_D | RD(dst) | RJ(src1) | RK(src2)));+ }++ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */+ if (carry_src_r != 0) {+ if (flags & SRC2_IMM)+ FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RJ(dst) | IMM_I12(src2)));+ else+ FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RJ(dst) | RK(carry_src_r)));+ }++ FAIL_IF(push_inst(compiler, ADD_D | RD(dst) | RJ(dst) | RK(OTHER_FLAG)));++ if (carry_src_r == 0)+ return SLJIT_SUCCESS;++ /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(dst) | RK(OTHER_FLAG)));+ /* Set carry flag. */+ return push_inst(compiler, OR | RD(OTHER_FLAG) | RJ(OTHER_FLAG) | RK(EQUAL_FLAG));++ case SLJIT_SUB:+ if ((flags & SRC2_IMM) && src2 == I12_MIN) {+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG2) | RJ(TMP_ZERO) | IMM_I12(src2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ is_handled = 0;++ if (flags & SRC2_IMM) {+ if (GET_FLAG_TYPE(op) == SLJIT_LESS) {+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(src2)));+ is_handled = 1;+ } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {+ FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(src2)));+ 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) {+ reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(push_inst(compiler, ADDI_D | RD(reg) | RJ(TMP_ZERO) | IMM_I12(src2)));+ src2 = reg;+ flags &= ~SRC2_IMM;+ }++ switch (GET_FLAG_TYPE(op)) {+ case SLJIT_LESS:+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(src1) | RK(src2)));+ break;+ case SLJIT_GREATER:+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(src2) | RK(src1)));+ break;+ case SLJIT_SIG_LESS:+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RJ(src1) | RK(src2)));+ break;+ case SLJIT_SIG_GREATER:+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RJ(src2) | RK(src1)));+ break;+ }+ }++ if (is_handled) {+ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(-src2)));+ if (!(flags & UNUSED_DEST))+ return push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(-src2));+ } else {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));+ if (!(flags & UNUSED_DEST))+ return push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(src1) | RK(src2));+ }+ return SLJIT_SUCCESS;+ }++ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0)));+ else {+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(-1)));+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG)));+ }+ } else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(-src2)));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(src2)));++ /* Only the zero flag is needed. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(-src2)));+ } else {+ if (is_overflow)+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(src1) | RK(src2)));++ /* Only the zero flag is needed. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(src1) | RK(src2)));+ }++ if (!is_overflow)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RJ(dst) | RK(EQUAL_FLAG)));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(dst) | IMM_I12(0)));+ FAIL_IF(push_inst(compiler, INST(SRLI, op) | RD(TMP_REG1) | RJ(TMP_REG1) | IMM_EXTEND(31)));+ return push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(TMP_REG1) | RK(OTHER_FLAG));++ case SLJIT_SUBC:+ if ((flags & SRC2_IMM) && src2 == I12_MIN) {+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(TMP_REG2) | RJ(TMP_ZERO) | IMM_I12(src2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(src2)));++ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(-src2)));+ } else {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));++ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(src1) | RK(src2)));+ }++ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | RD(TMP_REG1) | RJ(dst) | RK(OTHER_FLAG)));++ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(dst) | RK(OTHER_FLAG)));++ if (!is_carry)+ return SLJIT_SUCCESS;++ return push_inst(compiler, OR | RD(OTHER_FLAG) | RJ(EQUAL_FLAG) | RK(TMP_REG1));++ case SLJIT_MUL:+ SLJIT_ASSERT(!(flags & SRC2_IMM));++ if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW)+ return push_inst(compiler, INST(MUL, op) | RD(dst) | RJ(src1) | RK(src2));++ if (op & SLJIT_32) {+ FAIL_IF(push_inst(compiler, MUL_D | RD(OTHER_FLAG) | RJ(src1) | RK(src2)));+ FAIL_IF(push_inst(compiler, MUL_W | RD(dst) | RJ(src1) | RK(src2)));+ return push_inst(compiler, SUB_D | RD(OTHER_FLAG) | RJ(dst) | RK(OTHER_FLAG));+ }++ FAIL_IF(push_inst(compiler, MULH_D | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));+ FAIL_IF(push_inst(compiler, MUL_D | RD(dst) | RJ(src1) | RK(src2)));+ FAIL_IF(push_inst(compiler, SRAI_D | RD(OTHER_FLAG) | RJ(dst) | IMM_I12((63))));+ return push_inst(compiler, SUB_D | RD(OTHER_FLAG) | RJ(EQUAL_FLAG) | RK(OTHER_FLAG));++ case SLJIT_AND:+ EMIT_LOGICAL(ANDI, AND);+ return SLJIT_SUCCESS;++ case SLJIT_OR:+ EMIT_LOGICAL(ORI, OR);+ return SLJIT_SUCCESS;++ case SLJIT_XOR:+ EMIT_LOGICAL(XORI, XOR);+ return SLJIT_SUCCESS;++ case SLJIT_SHL:+ case SLJIT_MSHL:+ if (op & SLJIT_32) {+ EMIT_SHIFT(SLLI_W, SLL_W);+ } else {+ EMIT_SHIFT(SLLI_D, SLL_D);+ }+ break;++ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ if (op & SLJIT_32) {+ EMIT_SHIFT(SRLI_W, SRL_W);+ } else {+ EMIT_SHIFT(SRLI_D, SRL_D);+ }+ break;++ case SLJIT_ASHR:+ case SLJIT_MASHR:+ if (op & SLJIT_32) {+ EMIT_SHIFT(SRAI_W, SRA_W);+ } else {+ EMIT_SHIFT(SRAI_D, SRA_D);+ }+ break;++ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (flags & SRC2_IMM) {+ SLJIT_ASSERT(src2 != 0);++ if (GET_OPCODE(op) == SLJIT_ROTL)+ src2 = word_size - src2;+ return push_inst(compiler, INST(ROTRI, op) | RD(dst) | RJ(src1) | IMM_I12(src2));+ }++ if (src2 == TMP_ZERO) {+ if (dst != src1)+ return push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(0));+ return SLJIT_SUCCESS;+ }++ if (GET_OPCODE(op) == SLJIT_ROTL) {+ FAIL_IF(push_inst(compiler, INST(SUB, op)| RD(OTHER_FLAG) | RJ(TMP_ZERO) | RK(src2)));+ src2 = OTHER_FLAG;+ }+ return push_inst(compiler, INST(ROTR, op) | RD(dst) | RJ(src1) | RK(src2));++ default:+ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+ }++ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(src2)));++ if (flags & UNUSED_DEST)+ return SLJIT_SUCCESS;+ return push_inst(compiler, op_imm | RD(dst) | RJ(src1) | IMM_I12(src2));+ }++ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));++ if (flags & UNUSED_DEST)+ return SLJIT_SUCCESS;+ return push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(src2));+}++#undef IMM_EXTEND++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_s32 dst_r = TMP_REG2;+ sljit_s32 src1_r;+ sljit_sw src2_r = 0;+ sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;++ if (!(flags & ALT_KEEP_CACHE)) {+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ }++ if (dst == 0) {+ SLJIT_ASSERT(HAS_FLAGS(op));+ flags |= UNUSED_DEST;+ dst = TMP_REG2;+ } else if (FAST_IS_REG(dst)) {+ dst_r = dst;+ flags |= REG_DEST;+ if (flags & MOVE_OP)+ src2_tmp_reg = dst_r;+ } 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 != 0 && src2w <= I12_MAX && src2w >= I12_MIN) {+ flags |= SRC2_IMM;+ src2_r = src2w;+ } else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && src1w <= I12_MAX && src1w >= I12_MIN) {+ flags |= SRC2_IMM;+ src2_r = src1w;++ /* And swap arguments. */+ src1 = src2;+ src1w = src2w;+ src2 = SLJIT_IMM;+ /* src2w = src2_r unneeded. */+ }+ }++ /* Source 1. */+ if (FAST_IS_REG(src1)) {+ src1_r = src1;+ flags |= REG1_SOURCE;+ } else if (src1 == SLJIT_IMM) {+ if (src1w) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));+ src1_r = TMP_REG1;+ }+ else+ src1_r = TMP_ZERO;+ } else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC1;+ src1_r = TMP_REG1;+ }++ /* Source 2. */+ if (FAST_IS_REG(src2)) {+ src2_r = src2;+ flags |= REG2_SOURCE;+ if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)+ dst_r = (sljit_s32)src2_r;+ } else if (src2 == SLJIT_IMM) {+ if (!(flags & SRC2_IMM)) {+ if (src2w) {+ FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w));+ src2_r = src2_tmp_reg;+ } else {+ src2_r = TMP_ZERO;+ if (flags & MOVE_OP) {+ if (dst & SLJIT_MEM)+ dst_r = 0;+ else+ op = SLJIT_MOV;+ }+ }+ }+ } else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, src2_tmp_reg, src2, src2w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC2;++ src2_r = src2_tmp_reg;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ SLJIT_ASSERT(src2_r == TMP_REG2);+ if ((flags & SLOW_DEST) && !can_cache(src2, src2w, src1, src1w) && can_cache(src2, src2w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | MEM_USE_TMP2, TMP_REG2, src2, src2w, dst, dstw));+ } else {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | ((src1_r == TMP_REG1) ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, dst, dstw));++ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));++ if (dst & SLJIT_MEM) {+ if (!(flags & SLOW_DEST)) {+ getput_arg_fast(compiler, flags, dst_r, dst, dstw);+ return compiler->error;+ }+ return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);+ }++ return SLJIT_SUCCESS;+}++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));++ switch (GET_OPCODE(op)) {+ case SLJIT_BREAKPOINT:+ return push_inst(compiler, BREAK);+ case SLJIT_NOP:+ return push_inst(compiler, ANDI | RD(TMP_ZERO) | RJ(TMP_ZERO) | IMM_I12(0));+ case SLJIT_LMUL_UW:+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(SLJIT_R1) | IMM_I12(0)));+ FAIL_IF(push_inst(compiler, MULH_DU | RD(SLJIT_R1) | RJ(SLJIT_R0) | RK(SLJIT_R1)));+ return push_inst(compiler, MUL_D | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(TMP_REG1));+ case SLJIT_LMUL_SW:+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(SLJIT_R1) | IMM_I12(0)));+ FAIL_IF(push_inst(compiler, MULH_D | RD(SLJIT_R1) | RJ(SLJIT_R0) | RK(SLJIT_R1)));+ return push_inst(compiler, MUL_D | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(TMP_REG1));+ case SLJIT_DIVMOD_UW:+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(TMP_REG1) | RJ(SLJIT_R0) | IMM_I12(0)));+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32)? DIV_WU: DIV_DU) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1)));+ return push_inst(compiler, ((op & SLJIT_32)? MOD_WU: MOD_DU) | RD(SLJIT_R1) | RJ(TMP_REG1) | RK(SLJIT_R1));+ case SLJIT_DIVMOD_SW:+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(TMP_REG1) | RJ(SLJIT_R0) | IMM_I12(0)));+ FAIL_IF(push_inst(compiler, INST(DIV, op) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1)));+ return push_inst(compiler, INST(MOD, op) | RD(SLJIT_R1) | RJ(TMP_REG1) | RK(SLJIT_R1));+ case SLJIT_DIV_UW:+ return push_inst(compiler, ((op & SLJIT_32)? DIV_WU: DIV_DU) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1));+ case SLJIT_DIV_SW:+ return push_inst(compiler, INST(DIV, op) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1));+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++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_s32 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 (op & SLJIT_32)+ flags = INT_DATA | SIGNED_DATA;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, srcw);++ case SLJIT_MOV_U32:+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);++ case SLJIT_MOV_S32:+ /* Logical operators have no W variant, so sign extended input is necessary for them. */+ case SLJIT_MOV32:+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);++ case SLJIT_MOV_U8:+ return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);++ case SLJIT_MOV_S8:+ return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);++ case SLJIT_MOV_U16:+ return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);++ case SLJIT_MOV_S16:+ return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);++ case SLJIT_CLZ:+ case SLJIT_CTZ:+ case SLJIT_REV:+ return emit_op(compiler, op, flags, dst, dstw, TMP_ZERO, 0, src, srcw);++ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);++ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++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_s32 flags = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (op & SLJIT_32) {+ flags |= INT_DATA | SIGNED_DATA;+ if (src1 == SLJIT_IMM)+ src1w = (sljit_s32)src1w;+ if (src2 == SLJIT_IMM)+ src2w = (sljit_s32)src2w;+ }+++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ case SLJIT_ADDC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUB:+ case SLJIT_SUBC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_MUL:+ compiler->status_flags_state = 0;+ return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_MSHL:+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (src2 == SLJIT_IMM) {+ if (op & SLJIT_32)+ src2w &= 0x1f;+ else+ src2w &= 0x3f;+ }++ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));++ switch (GET_OPCODE(op)) {+ case SLJIT_MULADD:+ SLJIT_SKIP_CHECKS(compiler);+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));+ return push_inst(compiler, ADD_D | RD(dst_reg) | RJ(dst_reg) | RK(TMP_REG2));+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+ sljit_s32 is_left;+ sljit_ins ins1, ins2, ins3;+ sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;+++ CHECK_ERROR();+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));++ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);++ if (src1_reg == src2_reg) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);+ }++ ADJUST_LOCAL_OFFSET(src3, src3w);++ if (src3 == SLJIT_IMM) {+ src3w &= bit_length - 1;++ if (src3w == 0)+ return SLJIT_SUCCESS;++ if (is_left) {+ ins1 = INST(SLLI, op) | IMM_I12(src3w);+ src3w = bit_length - src3w;+ ins2 = INST(SRLI, op) | IMM_I12(src3w);+ } else {+ ins1 = INST(SRLI, op) | IMM_I12(src3w);+ src3w = bit_length - src3w;+ ins2 = INST(SLLI, op) | IMM_I12(src3w);+ }++ FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RJ(src1_reg)));+ FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RJ(src2_reg)));+ return push_inst(compiler, OR | RD(dst_reg) | RJ(dst_reg) | RK(TMP_REG1));+ }++ if (src3 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w));+ src3 = TMP_REG2;+ } else if (dst_reg == src3) {+ push_inst(compiler, INST(ADDI, op) | RD(TMP_REG2) | RJ(src3) | IMM_I12(0));+ src3 = TMP_REG2;+ }++ if (is_left) {+ ins1 = INST(SLL, op);+ ins2 = INST(SRLI, op);+ ins3 = INST(SRL, op);+ } else {+ ins1 = INST(SRL, op);+ ins2 = INST(SLLI, op);+ ins3 = INST(SLL, op);+ }++ FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RJ(src1_reg) | RK(src3)));++ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {+ FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RJ(src2_reg) | IMM_I12(1)));+ FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RJ(src3) | IMM_I12((sljit_ins)bit_length - 1)));+ src2_reg = TMP_REG1;+ } else+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(TMP_REG2) | RJ(TMP_ZERO) | RK(src3)));++ FAIL_IF(push_inst(compiler, ins3 | RD(TMP_REG1) | RJ(src2_reg) | RK(TMP_REG2)));+ return push_inst(compiler, OR | RD(dst_reg) | RJ(dst_reg) | RK(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 base = src & REG_MASK;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, ADDI_D | RD(RETURN_ADDR_REG) | RJ(src) | IMM_I12(0)));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));++ return push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(RETURN_ADDR_REG) | IMM_I12(0));+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ if (SLJIT_UNLIKELY(src & OFFS_REG_MASK)) {+ srcw &= 0x3;+ if (SLJIT_UNLIKELY(srcw))+ FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG1) | RJ(OFFS_REG(src)) | IMM_I12(srcw)));+ FAIL_IF(push_inst(compiler, ADD_D | RD(TMP_REG1) | RJ(base) | RK(TMP_REG1)));+ } else {+ if (base && srcw <= I12_MAX && srcw >= I12_MIN)+ return push_inst(compiler,PRELD | RJ(base) | IMM_I12(srcw));++ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ if (base != 0)+ FAIL_IF(push_inst(compiler, ADD_D | RD(TMP_REG1) | RJ(base) | RK(TMP_REG1)));+ }+ return push_inst(compiler, PRELD | RD(0) | RJ(TMP_REG1));+ }+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ switch (op) {+ case SLJIT_FAST_ENTER:+ if (FAST_IS_REG(dst))+ return push_inst(compiler, ADDI_D | RD(dst) | RJ(RETURN_ADDR_REG) | IMM_I12(0));++ SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2);+ break;+ case SLJIT_GET_RETURN_ADDRESS:+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));++ if (type == SLJIT_GP_REGISTER)+ return reg_map[reg];++ if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_128 && type != SLJIT_SIMD_REG_256)+ return -1;++ return freg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+ SLJIT_UNUSED_ARG(size);+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */+#define SET_COND(cond) (sljit_ins)(cond << 15)++#define COND_CUN SET_COND(0x8) /* UN */+#define COND_CEQ SET_COND(0x4) /* EQ */+#define COND_CUEQ SET_COND(0xc) /* UN EQ */+#define COND_CLT SET_COND(0x2) /* LT */+#define COND_CULT SET_COND(0xa) /* UN LT */+#define COND_CLE SET_COND(0x6) /* LT EQ */+#define COND_CULE SET_COND(0xe) /* UN LT EQ */+#define COND_CNE SET_COND(0x10) /* GT LT */+#define COND_CUNE SET_COND(0x18) /* UN GT LT */+#define COND_COR SET_COND(0x14) /* GT LT EQ */++#define FINST(inst, type) (sljit_ins)((type & SLJIT_32) ? inst##_S : inst##_D)+#define FCD(cd) (sljit_ins)(cd & 0x7)+#define FCJ(cj) (sljit_ins)((cj & 0x7) << 5)+#define FCA(ca) (sljit_ins)((ca & 0x7) << 15)+#define F_OTHER_FLAG 1++#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))++/* convert to inter exact toward zero */+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_ins inst;+ sljit_u32 word_data = 0;+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ switch (GET_OPCODE(op))+ {+ case SLJIT_CONV_SW_FROM_F64:+ word_data = 1;+ inst = FINST(FTINTRZ_L, op);+ break;+ case SLJIT_CONV_S32_FROM_F64:+ inst = FINST(FTINTRZ_W, op);+ break;+ default:+ inst = BREAK;+ SLJIT_UNREACHABLE();+ }++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst(compiler, inst | FRD(TMP_FREG1) | FRJ(src)));+ FAIL_IF(push_inst(compiler, FINST(MOVFR2GR, word_data) | RD(dst_r) | FRJ(TMP_FREG1)));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, word_data ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_ins inst;+ sljit_u32 word_data = 0;+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ switch (GET_OPCODE(op))+ {+ case SLJIT_CONV_F64_FROM_SW:+ word_data = 1;+ inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_L : FFINT_D_L);+ break;+ case SLJIT_CONV_F64_FROM_S32:+ inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_W : FFINT_D_W);+ break;+ default:+ inst = BREAK;+ SLJIT_UNREACHABLE();+ }++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, (word_data ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));+ src = TMP_REG1;+ } else if (src == SLJIT_IMM) {+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)+ srcw = (sljit_s32)srcw;++ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ }+ FAIL_IF(push_inst(compiler, (word_data ? MOVGR2FR_D : MOVGR2FR_W) | FRD(dst_r) | RJ(src)));+ FAIL_IF(push_inst(compiler, inst | FRD(dst_r) | FRJ(dst_r)));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++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)+{+ return sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_ins inst;+ sljit_u32 word_data = 0;+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ switch (GET_OPCODE(op))+ {+ case SLJIT_CONV_F64_FROM_UW:+ word_data = 1;+ inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_L : FFINT_D_L);+ break;+ case SLJIT_CONV_F64_FROM_U32:+ inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_W : FFINT_D_W);+ break;+ default:+ inst = BREAK;+ SLJIT_UNREACHABLE();+ }++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, (word_data ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));+ src = TMP_REG1;+ } else if (src == SLJIT_IMM) {+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)+ srcw = (sljit_u32)srcw;++ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ }++ if (!word_data)+ FAIL_IF(push_inst(compiler, SRLI_W | RD(src) | RJ(src) | IMM_I12(0)));++ FAIL_IF(push_inst(compiler, BLT | RJ(src) | RD(TMP_ZERO) | IMM_I16(4)));++ FAIL_IF(push_inst(compiler, (word_data ? MOVGR2FR_D : MOVGR2FR_W) | FRD(dst_r) | RJ(src)));+ FAIL_IF(push_inst(compiler, inst | FRD(dst_r) | FRJ(dst_r)));+ FAIL_IF(push_inst(compiler, B | IMM_I26(7)));++ FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG2) | RJ(src) | IMM_I12(1)));+ FAIL_IF(push_inst(compiler, (word_data ? SRLI_D : SRLI_W) | RD(TMP_REG1) | RJ(src) | IMM_I12(1)));+ FAIL_IF(push_inst(compiler, OR | RD(TMP_REG1) | RJ(TMP_REG1) | RK(TMP_REG2)));+ FAIL_IF(push_inst(compiler, INST(MOVGR2FR, (!word_data)) | FRD(dst_r) | RJ(TMP_REG1)));+ FAIL_IF(push_inst(compiler, inst | FRD(dst_r) | FRJ(dst_r)));+ FAIL_IF(push_inst(compiler, FINST(FADD, op) | FRD(dst_r) | FRJ(dst_r) | FRK(dst_r)));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++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));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));+ src2 = TMP_FREG2;+ }++ FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(OTHER_FLAG) | RK(OTHER_FLAG)));++ switch (GET_FLAG_TYPE(op)) {+ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CEQ | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));+ break;+ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CLT | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));+ break;+ case SLJIT_F_GREATER:+ case SLJIT_ORDERED_GREATER:+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CLT | FCD(F_OTHER_FLAG) | FRJ(src2) | FRK(src1)));+ break;+ case SLJIT_UNORDERED_OR_GREATER:+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CULT | FCD(F_OTHER_FLAG) | FRJ(src2) | FRK(src1)));+ break;+ case SLJIT_UNORDERED_OR_LESS:+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CULT | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));+ break;+ case SLJIT_UNORDERED_OR_EQUAL:+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CUEQ | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));+ break;+ default: /* SLJIT_UNORDERED */+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CUN | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));+ }+ return push_inst(compiler, MOVCF2GR | RD(OTHER_FLAG) | FCJ(F_OTHER_FLAG));+}++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_s32 dst_r;++ CHECK_ERROR();+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)+ op ^= SLJIT_32;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (!(dst & SLJIT_MEM))+ FAIL_IF(push_inst(compiler, FINST(FMOV, op) | FRD(dst_r) | FRJ(src)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, FINST(FNEG, op) | FRD(dst_r) | FRJ(src)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, FINST(FABS, op) | FRD(dst_r) | FRJ(src)));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? FCVT_D_S : FCVT_S_D) | FRD(dst_r) | FRJ(src)));+ op ^= SLJIT_32;+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++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_s32 dst_r, flags = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;++ if (src1 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {+ FAIL_IF(compiler->error);+ src1 = TMP_FREG1;+ } else+ flags |= SLOW_SRC1;+ }++ if (src2 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {+ FAIL_IF(compiler->error);+ src2 = TMP_FREG2;+ } else+ flags |= SLOW_SRC2;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));+ } else {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));++ if (flags & SLOW_SRC1)+ src1 = TMP_FREG1;+ if (flags & SLOW_SRC2)+ src2 = TMP_FREG2;++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, FINST(FADD, op) | FRD(dst_r) | FRJ(src1) | FRK(src2)));+ break;+ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, FINST(FSUB, op) | FRD(dst_r) | FRJ(src1) | FRK(src2)));+ break;+ case SLJIT_MUL_F64:+ FAIL_IF(push_inst(compiler, FINST(FMUL, op) | FRD(dst_r) | FRJ(src1) | FRK(src2)));+ break;+ case SLJIT_DIV_F64:+ FAIL_IF(push_inst(compiler, FINST(FDIV, op) | FRD(dst_r) | FRJ(src1) | FRK(src2)));+ break;+ }++ if (dst_r != dst)+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 reg;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src2, src2w, 0, 0));+ src2 = TMP_FREG1;+ }++ if (src1 & SLJIT_MEM) {+ reg = (dst_freg == src2) ? TMP_FREG1 : dst_freg;+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, reg, src1, src1w, 0, 0));+ src1 = reg;+ }++ return push_inst(compiler, FINST(FCOPYSIGN, op) | FRD(dst_freg) | FRJ(src1) | FRK(src2));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+ union {+ sljit_s32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++ if (u.imm == 0)+ return push_inst(compiler, MOVGR2FR_W | RJ(TMP_ZERO) | FRD(freg));++ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));+ return push_inst(compiler, MOVGR2FR_W | RJ(TMP_REG1) | FRD(freg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ union {+ sljit_sw imm;+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ if (u.imm == 0)+ return push_inst(compiler, MOVGR2FR_D | RJ(TMP_ZERO) | FRD(freg));++ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));+ return push_inst(compiler, MOVGR2FR_D | RJ(TMP_REG1) | FRD(freg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)+ inst = ((op & SLJIT_32) ? MOVGR2FR_W : MOVGR2FR_D) | FRD(freg) | RJ(reg);+ else+ inst = ((op & SLJIT_32) ? MOVFR2GR_S : MOVFR2GR_D) | RD(reg) | FRJ(freg);+ return push_inst(compiler, inst);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++static sljit_ins get_jump_instruction(sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_ATOMIC_NOT_STORED:+ return BNE | RJ(EQUAL_FLAG) | RD(TMP_ZERO);+ case SLJIT_NOT_EQUAL:+ case SLJIT_ATOMIC_STORED:+ return BEQ | RJ(EQUAL_FLAG) | RD(TMP_ZERO);+ case SLJIT_LESS:+ case SLJIT_GREATER:+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_GREATER:+ case SLJIT_OVERFLOW:+ case SLJIT_CARRY:+ return BEQ | RJ(OTHER_FLAG) | RD(TMP_ZERO);+ case SLJIT_GREATER_EQUAL:+ case SLJIT_LESS_EQUAL:+ case SLJIT_SIG_GREATER_EQUAL:+ case SLJIT_SIG_LESS_EQUAL:+ case SLJIT_NOT_OVERFLOW:+ case SLJIT_NOT_CARRY:+ return BNE | RJ(OTHER_FLAG) | RD(TMP_ZERO);+ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ case SLJIT_ORDERED_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ case SLJIT_F_GREATER:+ case SLJIT_UNORDERED_OR_LESS:+ case SLJIT_UNORDERED_OR_EQUAL:+ case SLJIT_UNORDERED:+ return BEQ | RJ(OTHER_FLAG) | RD(TMP_ZERO);+ case SLJIT_ORDERED_NOT_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_ORDERED:+ return BNE | RJ(OTHER_FLAG) | RD(TMP_ZERO);+ default:+ /* Not conditional branch. */+ return 0;+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;+ sljit_ins inst;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ inst = get_jump_instruction(type);++ if (inst != 0) {+ PTR_FAIL_IF(push_inst(compiler, inst));+ jump->flags |= IS_COND;+ }++ jump->addr = compiler->size;+ inst = JIRL | RJ(TMP_REG1) | IMM_I16(0);++ if (type >= SLJIT_FAST_CALL) {+ jump->flags |= IS_CALL;+ inst |= RD(RETURN_ADDR_REG);+ }++ PTR_FAIL_IF(push_inst(compiler, inst));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ SLJIT_UNUSED_ARG(arg_types);+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ if (type & SLJIT_CALL_RETURN) {+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, type);+}++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_s32 flags;+ sljit_ins inst;+ sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;++ if (src1 & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG1, src1, src1w, src2, src2w));+ src1 = TMP_REG1;+ }++ if (src2 & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, src2_tmp_reg, src2, src2w, 0, 0));+ src2 = src2_tmp_reg;+ }++ if (src1 == SLJIT_IMM) {+ if (src1w != 0) {+ PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));+ src1 = TMP_REG1;+ }+ else+ src1 = TMP_ZERO;+ }++ if (src2 == SLJIT_IMM) {+ if (src2w != 0) {+ PTR_FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w));+ src2 = src2_tmp_reg;+ }+ else+ src2 = TMP_ZERO;+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND));+ type &= 0xff;++ switch (type) {+ case SLJIT_EQUAL:+ inst = BNE | RJ(src1) | RD(src2);+ break;+ case SLJIT_NOT_EQUAL:+ inst = BEQ | RJ(src1) | RD(src2);+ break;+ case SLJIT_LESS:+ inst = BGEU | RJ(src1) | RD(src2);+ break;+ case SLJIT_GREATER_EQUAL:+ inst = BLTU | RJ(src1) | RD(src2);+ break;+ case SLJIT_GREATER:+ inst = BGEU | RJ(src2) | RD(src1);+ break;+ case SLJIT_LESS_EQUAL:+ inst = BLTU | RJ(src2) | RD(src1);+ break;+ case SLJIT_SIG_LESS:+ inst = BGE | RJ(src1) | RD(src2);+ break;+ case SLJIT_SIG_GREATER_EQUAL:+ inst = BLT | RJ(src1) | RD(src2);+ break;+ case SLJIT_SIG_GREATER:+ inst = BGE | RJ(src2) | RD(src1);+ break;+ case SLJIT_SIG_LESS_EQUAL:+ inst = BLT | RJ(src2) | RD(src1);+ break;+ default:+ inst = BREAK;+ SLJIT_UNREACHABLE();+ }++ PTR_FAIL_IF(push_inst(compiler, inst));++ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(TMP_REG1) | IMM_I12(0)));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;++ return jump;+}++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;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));++ if (src != SLJIT_IMM) {+ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));+ src = TMP_REG1;+ }+ return push_inst(compiler, JIRL | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RJ(src) | IMM_I12(0));+ }++ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_CALL : 0));+ jump->u.target = (sljit_uw)srcw;++ jump->addr = compiler->size;+ FAIL_IF(push_inst(compiler, JIRL | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RJ(TMP_REG1) | IMM_I12(0)));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(arg_types);+ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));+ src = TMP_REG1;+ }++ if (type & SLJIT_CALL_RETURN) {+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(src) | IMM_I12(0)));+ src = TMP_REG1;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 0));+ type = SLJIT_JUMP;+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+}++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_s32 src_r, dst_r, invert;+ sljit_s32 saved_op = op;+ sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+ dst_r = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));++ if (type < SLJIT_F_EQUAL) {+ src_r = OTHER_FLAG;+ invert = type & 0x1;++ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_NOT_EQUAL:+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(EQUAL_FLAG) | IMM_I12(1)));+ src_r = dst_r;+ break;+ case SLJIT_ATOMIC_STORED:+ case SLJIT_ATOMIC_NOT_STORED:+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(EQUAL_FLAG) | IMM_I12(1)));+ src_r = dst_r;+ invert ^= 0x1;+ break;+ case SLJIT_OVERFLOW:+ case SLJIT_NOT_OVERFLOW:+ if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {+ src_r = OTHER_FLAG;+ break;+ }+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(OTHER_FLAG) | IMM_I12(1)));+ src_r = dst_r;+ invert ^= 0x1;+ break;+ }+ } else {+ invert = 0;+ src_r = OTHER_FLAG;++ switch (type) {+ case SLJIT_ORDERED_NOT_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_ORDERED:+ invert = 1;+ break;+ }+ }++ if (invert) {+ FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RJ(src_r) | IMM_I12(1)));+ src_r = dst_r;+ }++ if (op < SLJIT_ADD) {+ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, mem_type, src_r, dst, dstw);++ if (src_r != dst_r)+ return push_inst(compiler, ADDI_D | RD(dst_r) | RJ(src_r) | IMM_I12(0));+ return SLJIT_SUCCESS;+ }++ mem_type |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;++ if (dst & SLJIT_MEM)+ return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, src_r, 0);+ return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+ sljit_ins *ptr;+ sljit_uw size;+ sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));+ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (dst_reg != src2_reg) {+ if (dst_reg == src1) {+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else {+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(dst_reg) | IMM_I12(0)));++ if ((src1 & REG_MASK) == dst_reg)+ src1 = (src1 & ~REG_MASK) | TMP_REG1;++ if (OFFS_REG(src1) == dst_reg)+ src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);+ }++ FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_reg) | RJ(src2_reg) | IMM_I12(0)));+ }+ }++ size = compiler->size;++ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size++;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));+ } else if (src1 == SLJIT_IMM) {+ if (type & SLJIT_32)+ src1w = (sljit_s32)src1w;+ FAIL_IF(load_immediate(compiler, dst_reg, src1w));+ } else+ FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_reg) | RJ(src1) | IMM_I12(0)));++ *ptr = get_jump_instruction(type & ~SLJIT_32) | IMM_I16(compiler->size - size);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+ sljit_s32 invert = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if ((type & ~SLJIT_32) == SLJIT_EQUAL || (type & ~SLJIT_32) == SLJIT_NOT_EQUAL) {+ if ((type & ~SLJIT_32) == SLJIT_EQUAL)+ invert = 1;+ FAIL_IF(push_inst(compiler, MOVGR2CF | FCD(F_OTHER_FLAG) | RJ(EQUAL_FLAG)));+ } else {+ if (get_jump_instruction(type & ~SLJIT_32) == (BNE | RJ(OTHER_FLAG) | RD(TMP_ZERO)))+ invert = 1;+ FAIL_IF(push_inst(compiler, MOVGR2CF | FCD(F_OTHER_FLAG) | RJ(OTHER_FLAG)));+ }++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG2, src1, src1w));+ if (invert)+ return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(TMP_FREG2) | FRK(src2_freg) | FCA(F_OTHER_FLAG));+ return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(src2_freg) | FRK(TMP_FREG2) | FCA(F_OTHER_FLAG));+ } else {+ if (invert)+ return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(src1) | FRK(src2_freg) | FCA(F_OTHER_FLAG));+ return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(src2_freg) | FRK(src1) | FCA(F_OTHER_FLAG));+ }+}++#undef FLOAT_DATA++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (!(reg & REG_PAIR_MASK))+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ memw &= 0x3;++ if (SLJIT_UNLIKELY(memw != 0)) {+ FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG1) | RJ(OFFS_REG(mem)) | IMM_I12(memw)));+ FAIL_IF(push_inst(compiler, ADD_D| RD(TMP_REG1) | RJ(TMP_REG1) | RK(mem & REG_MASK)));+ } else+ FAIL_IF(push_inst(compiler, ADD_D| RD(TMP_REG1) | RJ(mem & REG_MASK) | RK(OFFS_REG(mem))));++ mem = TMP_REG1;+ memw = 0;+ } else if (memw > I12_MAX - SSIZE_OF(sw) || memw < I12_MIN) {+ if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw)));+ memw &= 0xfff;+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw));+ memw = 0;+ }++ if (mem & REG_MASK)+ FAIL_IF(push_inst(compiler, ADD_D| RD(TMP_REG1) | RJ(TMP_REG1) | RK(mem & REG_MASK)));++ mem = TMP_REG1;+ } else {+ mem &= REG_MASK;+ memw &= 0xfff;+ }++ SLJIT_ASSERT((memw >= 0 && memw <= I12_MAX - SSIZE_OF(sw)) || (memw > I12_MAX && memw <= 0xfff));++ if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {+ FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), (memw + SSIZE_OF(sw)) & 0xfff));+ return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw);+ }++ flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0);++ FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw));+ return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), (memw + SSIZE_OF(sw)) & 0xfff);+}++#undef TO_ARGW_HI++static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw)+{+ sljit_s32 mem = *mem_ptr;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ *mem_ptr = TMP_REG3;+ FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG3) | RJ(OFFS_REG(mem)) | IMM_I12(memw & 0x3)));+ return push_inst(compiler, ADD_D | RD(TMP_REG3) | RJ(TMP_REG3) | RK(mem & REG_MASK));+ }++ if (!(mem & REG_MASK)) {+ *mem_ptr = TMP_REG3;+ return load_immediate(compiler, TMP_REG3, memw);+ }++ mem &= REG_MASK;++ if (memw == 0) {+ *mem_ptr = mem;+ return SLJIT_SUCCESS;+ }++ *mem_ptr = TMP_REG3;++ FAIL_IF(load_immediate(compiler, TMP_REG3, memw));+ return push_inst(compiler, ADD_D | RD(TMP_REG3) | RJ(TMP_REG3) | RK(mem));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 5 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (!(srcdst & SLJIT_MEM)) {+ if (type & SLJIT_SIMD_STORE)+ ins = FRD(srcdst) | FRJ(freg) | FRK(freg);+ else+ ins = FRD(freg) | FRJ(srcdst) | FRK(srcdst);++ if (reg_size == 5)+ ins |= VOR_V | (sljit_ins)1 << 26;+ else+ ins |= VOR_V;++ return push_inst(compiler, ins);+ }++ ins = (type & SLJIT_SIMD_STORE) ? VST : VLD;++ if (reg_size == 5)+ ins = (type & SLJIT_SIMD_STORE) ? XVST : XVLD;++ if (FAST_IS_REG(srcdst) && srcdst >= 0 && (srcdstw >= I12_MIN && srcdstw <= I12_MAX))+ return push_inst(compiler, ins | FRD(freg) | RJ((sljit_u8)srcdst) | IMM_I12(srcdstw));+ else {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));+ return push_inst(compiler, ins | FRD(freg) | RJ(srcdst) | IMM_I12(0));+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 5 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (src & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));++ if (reg_size == 5)+ ins = (sljit_ins)1 << 25;++ return push_inst(compiler, VLDREPL | ins | FRD(freg) | RJ(src) | (sljit_ins)1 << (23 - elem_size));+ }++ if (reg_size == 5)+ ins = (sljit_ins)1 << 26;++ if (type & SLJIT_SIMD_FLOAT) {+ if (src == SLJIT_IMM)+ return push_inst(compiler, VREPLGR2VR | ins | FRD(freg) | RJ(TMP_ZERO) | (sljit_ins)elem_size << 10);++ FAIL_IF(push_inst(compiler, VREPLVE | ins | FRD(freg) | FRJ(src) | RK(TMP_ZERO) | (sljit_ins)elem_size << 15));++ if (reg_size == 5) {+ ins = (sljit_ins)(0x44 << 10);+ return push_inst(compiler, XVPERMI | ins | FRD(freg) | FRJ(freg));+ }++ return SLJIT_SUCCESS;+ }++ ins |= VREPLGR2VR | (sljit_ins)elem_size << 10;++ if (src == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));+ src = TMP_REG2;+ }++ return push_inst(compiler, ins | FRD(freg) | RJ(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 5 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (type & SLJIT_SIMD_LANE_ZERO) {+ ins = (reg_size == 5) ? ((sljit_ins)1 << 26) : 0;++ if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) {+ FAIL_IF(push_inst(compiler, VOR_V | ins | FRD(TMP_FREG1) | FRJ(freg) | FRK(freg)));+ srcdst = TMP_FREG1;+ srcdstw = 0;+ }++ FAIL_IF(push_inst(compiler, VXOR_V | ins | FRD(freg) | FRJ(freg) | FRK(freg)));+ }++ if (srcdst & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));++ if (reg_size == 5)+ ins = (sljit_ins)1 << 25;++ if (type & SLJIT_SIMD_STORE) {+ ins |= (sljit_ins)lane_index << 18 | (sljit_ins)(1 << (23 - elem_size));+ return push_inst(compiler, VSTELM | ins | FRD(freg) | RJ(srcdst));+ } else {+ emit_op_mem(compiler, (elem_size == 3 ? WORD_DATA : (elem_size == 2 ? INT_DATA : (elem_size == 1 ? HALF_DATA : BYTE_DATA))) | LOAD_DATA, TMP_REG1, srcdst | SLJIT_MEM, 0);+ srcdst = TMP_REG1;+ ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;++ if (reg_size == 5) {+ if (elem_size < 2) {+ FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(freg) | FRK(freg)));+ if (lane_index >= (2 << (3 - elem_size))) {+ FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(freg) | IMM_I8(1)));+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(TMP_FREG1) | RJ(srcdst) | IMM_V(lane_index % (2 << (3 - elem_size)))));+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(freg) | FRJ(TMP_FREG1) | IMM_I8(2));+ } else {+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(srcdst) | IMM_V(lane_index)));+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(freg) | FRJ(TMP_FREG1) | IMM_I8(18));+ }+ } else+ ins = (sljit_ins)(0x3f ^ (0x3f >> elem_size)) << 10 | (sljit_ins)1 << 26;+ }++ return push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(srcdst) | IMM_V(lane_index));+ }+ }++ if (type & SLJIT_SIMD_FLOAT) {+ ins = (reg_size == 5) ? (sljit_ins)(0x3f ^ (0x3f >> elem_size)) << 10 | (sljit_ins)1 << 26 : (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;++ if (type & SLJIT_SIMD_STORE) {+ FAIL_IF(push_inst(compiler, VPICKVE2GR_U | ins | RD(TMP_REG1) | FRJ(freg) | IMM_V(lane_index)));+ return push_inst(compiler, VINSGR2VR | ins | FRD(srcdst) | RJ(TMP_REG1) | IMM_V(0));+ } else {+ FAIL_IF(push_inst(compiler, VPICKVE2GR_U | ins | RD(TMP_REG1) | FRJ(srcdst) | IMM_V(0)));+ return push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(TMP_REG1) | IMM_V(lane_index));+ }+ }++ if (srcdst == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcdstw));+ srcdst = TMP_REG1;+ }++ if (type & SLJIT_SIMD_STORE) {+ ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;++ if (type & SLJIT_SIMD_LANE_SIGNED)+ ins |= (sljit_ins)(VPICKVE2GR_U ^ (0x7 << 18));+ else+ ins |= VPICKVE2GR_U;++ if (reg_size == 5) {+ if (elem_size < 2) {+ if (lane_index >= (2 << (3 - elem_size))) {+ if (type & SLJIT_SIMD_LANE_SIGNED)+ ins |= (sljit_ins)(VPICKVE2GR_U ^ (0x7 << 18));+ else+ ins |= VPICKVE2GR_U;++ FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(freg) | FRK(freg)));+ FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(freg) | IMM_I8(1)));+ return push_inst(compiler, ins | RD(srcdst) | FRJ(TMP_FREG1) | IMM_V(lane_index % (2 << (3 - elem_size))));+ }+ } else {+ ins ^= (sljit_ins)1 << (15 - elem_size);+ ins |= (sljit_ins)1 << 26;+ }+ }++ return push_inst(compiler, ins | RD(srcdst) | FRJ(freg) | IMM_V(lane_index));+ } else {+ ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;++ if (reg_size == 5) {+ if (elem_size < 2) {+ FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(freg) | FRK(freg)));+ if (lane_index >= (2 << (3 - elem_size))) {+ FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(freg) | IMM_I8(1)));+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(TMP_FREG1) | RJ(srcdst) | IMM_V(lane_index % (2 << (3 - elem_size)))));+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(freg) | FRJ(TMP_FREG1) | IMM_I8(2));+ } else {+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(srcdst) | IMM_V(lane_index)));+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(freg) | FRJ(TMP_FREG1) | IMM_I8(18));+ }+ } else+ ins = (sljit_ins)(0x3f ^ (0x3f >> elem_size)) << 10 | (sljit_ins)1 << 26;+ }++ return push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(srcdst) | IMM_V(lane_index));+ }++ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_s32 src_lane_index)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index));++ if (reg_size != 5 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;++ if (reg_size == 5) {+ FAIL_IF(push_inst(compiler, VREPLVEI | (sljit_ins)1 << 26 | ins | FRD(freg) | FRJ(src) | IMM_V(src_lane_index % (2 << (3 - elem_size)))));++ ins = (src_lane_index < (2 << (3 - elem_size))) ? (sljit_ins)(0x44 << 10) : (sljit_ins)(0xee << 10);++ return push_inst(compiler, XVPERMI | ins | FRD(freg) | FRJ(freg));+ }++ return push_inst(compiler, VREPLVEI | ins | FRD(freg) | FRJ(src) | IMM_V(src_lane_index));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 5 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (src & SLJIT_MEM) {+ ins = (type & SLJIT_SIMD_STORE) ? VST : VLD;++ if (reg_size == 5)+ ins = (type & SLJIT_SIMD_STORE) ? XVST : XVLD;++ if (FAST_IS_REG(src) && src >= 0 && (srcw >= I12_MIN && srcw <= I12_MAX))+ FAIL_IF(push_inst(compiler, ins | FRD(freg) | RJ(src) | IMM_I12(srcw)));+ else {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));+ FAIL_IF(push_inst(compiler, ins | FRD(freg) | RJ(src) | IMM_I12(0)));+ }+ src = freg;+ }++ if (type & SLJIT_SIMD_FLOAT) {+ if (elem_size != 2 || elem2_size != 3)+ return SLJIT_ERR_UNSUPPORTED;++ ins = 0;+ if (reg_size == 5) {+ ins = (sljit_ins)1 << 26;+ FAIL_IF(push_inst(compiler, XVPERMI | FRD(src) | FRJ(src) | IMM_I8(16)));+ }++ return push_inst(compiler, VFCVTL_D_S | ins | FRD(freg) | FRJ(src));+ }++ ins = (type & SLJIT_SIMD_EXTEND_SIGNED) ? VSLLWIL : (VSLLWIL | (sljit_ins)1 << 18);++ if (reg_size == 5)+ ins |= (sljit_ins)1 << 26;++ do {+ if (reg_size == 5)+ FAIL_IF(push_inst(compiler, XVPERMI | FRD(src) | FRJ(src) | IMM_I8(16)));++ FAIL_IF(push_inst(compiler, ins | ((sljit_ins)1 << (13 + elem_size)) | FRD(freg) | FRJ(src)));+ src = freg;+ } while (++elem_size < elem2_size);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins = 0;+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw));++ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (reg_size != 5 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))+ return SLJIT_ERR_UNSUPPORTED;++ if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ if (reg_size == 5)+ ins = (sljit_ins)1 << 26;++ FAIL_IF(push_inst(compiler, VMSKLTZ | ins | (sljit_ins)(elem_size << 10) | FRD(TMP_FREG1) | FRJ(freg)));++ FAIL_IF(push_inst(compiler, VPICKVE2GR_U | (sljit_ins)(0x3c << 10) | RD(dst_r) | FRJ(TMP_FREG1)));++ if (reg_size == 5) {+ FAIL_IF(push_inst(compiler, VPICKVE2GR_U | (sljit_ins)(0x38 << 10) | ins | RD(TMP_REG3) | FRJ(TMP_FREG1) | IMM_V(2)));+ FAIL_IF(push_inst(compiler, SLLI_W | RD(TMP_REG3) | RJ(TMP_REG3) | IMM_I12(2 << (3 - elem_size))));+ FAIL_IF(push_inst(compiler, OR | RD(dst_r) | RJ(dst_r) | RK(TMP_REG3)));+ }++ if (dst_r == TMP_REG2)+ return emit_op_mem(compiler, ((type & SLJIT_32) ? INT_DATA : WORD_DATA), TMP_REG2, dst, dstw);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg));++ if (reg_size != 5 && reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ switch (SLJIT_SIMD_GET_OPCODE(type)) {+ case SLJIT_SIMD_OP2_AND:+ ins = VAND_V;+ break;+ case SLJIT_SIMD_OP2_OR:+ ins = VOR_V;+ break;+ case SLJIT_SIMD_OP2_XOR:+ ins = VXOR_V;+ break;+ }++ if (reg_size == 5)+ ins |= (sljit_ins)1 << 26;++ return push_inst(compiler, ins | FRD(dst_freg) | FRJ(src1_freg) | FRK(src2_freg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler,+ sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 mem_reg)+{+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));++ switch(GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ ins = LD_BU;+ break;+ case SLJIT_MOV_U16:+ ins = LD_HU;+ break;+ case SLJIT_MOV32:+ ins = LD_W;+ break;+ case SLJIT_MOV_U32:+ ins = LD_WU;+ break;+ default:+ ins = LD_D;+ break;+ }++ return push_inst(compiler, ins | RD(dst_reg) | RJ(mem_reg) | IMM_I12(0));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler,+ sljit_s32 op,+ sljit_s32 src_reg,+ sljit_s32 mem_reg,+ sljit_s32 temp_reg)+{+ sljit_ins ins = 0;+ sljit_ins unsign = 0;+ sljit_s32 tmp = temp_reg;++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ ins = AMCAS_B;+ unsign = BSTRPICK_D | (7 << 16);+ break;+ case SLJIT_MOV_U16:+ ins = AMCAS_H;+ unsign = BSTRPICK_D | (15 << 16);+ break;+ case SLJIT_MOV32:+ ins = AMCAS_W;+ break;+ case SLJIT_MOV_U32:+ ins = AMCAS_W;+ unsign = BSTRPICK_D | (31 << 16);+ break;+ default:+ ins = AMCAS_D;+ break;+ }++ if (op & SLJIT_SET_ATOMIC_STORED) {+ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RJ(temp_reg) | RK(TMP_ZERO)));+ tmp = TMP_REG1;+ }+ FAIL_IF(push_inst(compiler, ins | RD(tmp) | RJ(mem_reg) | RK(src_reg)));+ if (!(op & SLJIT_SET_ATOMIC_STORED))+ return SLJIT_SUCCESS;++ if (unsign)+ FAIL_IF(push_inst(compiler, unsign | RD(tmp) | RJ(tmp)));++ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(tmp) | RK(temp_reg)));+ return push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RJ(EQUAL_FLAG) | IMM_I12(1));+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)+{+ SLJIT_UNUSED_ARG(last_ins);++ FAIL_IF(push_inst(compiler, LU12I_W | RD(dst) | (sljit_ins)(((init_value & 0xffffffff) >> 12) << 5)));+ FAIL_IF(push_inst(compiler, LU32I_D | RD(dst) | (sljit_ins)(((init_value >> 32) & 0xfffff) << 5)));+ FAIL_IF(push_inst(compiler, LU52I_D | RD(dst) | RJ(dst) | (sljit_ins)(IMM_I12(init_value >> 52))));+ return push_inst(compiler, ORI | RD(dst) | RJ(dst) | IMM_I12(init_value));+}++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_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);++ SLJIT_ASSERT((inst[0] & OPC_1RI20(0x7f)) == LU12I_W);+ inst[0] = (inst[0] & (OPC_1RI20(0x7f) | 0x1f)) | (sljit_ins)(((new_target & 0xffffffff) >> 12) << 5);++ SLJIT_ASSERT((inst[1] & OPC_1RI20(0x7f)) == LU32I_D);+ inst[1] = (inst[1] & (OPC_1RI20(0x7f) | 0x1f)) | (sljit_ins)(sljit_ins)(((new_target >> 32) & 0xfffff) << 5);++ SLJIT_ASSERT((inst[2] & OPC_2RI12(0x3ff)) == LU52I_D);+ inst[2] = (inst[2] & (OPC_2RI12(0x3ff) | 0x3ff)) | IMM_I12(new_target >> 52);++ SLJIT_ASSERT((inst[3] & OPC_2RI12(0x3ff)) == ORI || (inst[3] & OPC_2RI16(0x3f)) == JIRL);+ if ((inst[3] & OPC_2RI12(0x3ff)) == ORI)+ inst[3] = (inst[3] & (OPC_2RI12(0x3ff) | 0x3ff)) | IMM_I12(new_target);+ else+ inst[3] = (inst[3] & (OPC_2RI16(0x3f) | 0x3ff)) | IMM_I12((new_target & 0xfff) >> 2);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);++ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 4);+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, 0));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));++ compiler->size += JUMP_MAX_SIZE - 1;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);+}
src/c/pcre2/src/sljit/sljitNativeMIPS_32.c view
@@ -26,6 +26,49 @@ /* mips 32-bit arch dependent functions. */ +static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_sw src1, sljit_sw src2, sljit_sw dst)+{+ int is_32 = (op & SLJIT_32);+ sljit_ins mfhc = MFC1, mthc = MTC1;+ sljit_ins src1_r = FS(src1), src2_r = FS(src2), dst_r = FS(dst);++ if (!is_32) {+ switch (cpu_feature_list & CPU_FEATURE_FR) {+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+ case CPU_FEATURE_FR:+ mfhc = MFHC1;+ mthc = MTHC1;+ break;+#endif /* SLJIT_MIPS_REV >= 2 */+ default:+ src1_r |= (1 << 11);+ src2_r |= (1 << 11);+ dst_r |= (1 << 11);+ break;+ }+ }++ FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG1) | src1_r, DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG2) | src2_r, DR(TMP_REG2)));+ if (!is_32 && src1 != dst)+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(src1) | FD(dst), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ else+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ FAIL_IF(push_inst(compiler, XOR | T(TMP_REG1) | D(TMP_REG2) | S(TMP_REG2), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, SLL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, XOR | T(TMP_REG2) | D(TMP_REG1) | S(TMP_REG1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, mthc | T(TMP_REG1) | dst_r, MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ if (mthc == MTC1)+ return push_inst(compiler, NOP, UNMOVABLE_INS);+#endif /* MIPS III */+ return SLJIT_SUCCESS;+}+ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) { if (!(imm & ~0xffff))@@ -38,387 +81,112 @@ return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS; } -#define EMIT_LOGICAL(op_imm, op_norm) \- if (flags & SRC2_IMM) { \- if (op & SLJIT_SET_Z) \- FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \- if (!(flags & UNUSED_DEST)) \- FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \- } \- else { \- if (op & SLJIT_SET_Z) \- FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \- 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_Z) \- FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \- 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_Z) \- FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \- if (!(flags & UNUSED_DEST)) \- FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \- }--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)+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) {- sljit_s32 is_overflow, is_carry, is_handled;-- switch (GET_OPCODE(op)) {- case SLJIT_MOV:- 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_U8:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))- return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_MOV_S8:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)- return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));-#else /* SLJIT_MIPS_REV < 1 */- FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));- return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));-#endif /* SLJIT_MIPS_REV >= 1 */- }- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_MOV_U16:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))- return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_MOV_S16:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)- return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));-#else /* SLJIT_MIPS_REV < 1 */- FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));- return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));-#endif /* SLJIT_MIPS_REV >= 1 */- }- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_NOT:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if (op & SLJIT_SET_Z)- FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));- 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_REV && SLJIT_MIPS_REV >= 1)- if (op & SLJIT_SET_Z)- FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));- if (!(flags & UNUSED_DEST))- FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));-#else /* SLJIT_MIPS_REV < 1 */- if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {- FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));- return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);- }- /* Nearly all instructions are unmovable in the following sequence. */- FAIL_IF(push_inst(compiler, 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(32), UNMOVABLE_INS));- FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst)));- /* Loop for searching the highest bit. */- 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));-#endif /* SLJIT_MIPS_REV >= 1 */- 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 (is_overflow) {- if (src2 >= 0)- 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(EQUAL_FLAG), EQUAL_FLAG));- }- else if (op & SLJIT_SET_Z)- FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));-- if (is_overflow || is_carry) {- if (src2 >= 0)- 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(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 (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))- FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));- }- else {- 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 (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 (!(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 (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(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 (is_carry) {- if (src2 >= 0)- 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(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 (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 (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(OTHER_FLAG) | D(dst), DR(dst)));- if (!is_carry)- return SLJIT_SUCCESS;-- /* 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(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);-- case SLJIT_SUB:- 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;+ 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));+} - 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;- }+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ union {+ struct {+#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN+ sljit_s32 lo;+ sljit_s32 hi;+#else /* !SLJIT_LITTLE_ENDIAN */+ sljit_s32 hi;+ sljit_s32 lo;+#endif /* SLJIT_LITTLE_ENDIAN */+ } bin;+ sljit_f64 value;+ } u; - 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));- }- }+ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value)); - 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;- }+ u.value = value; - is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;- is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);+ if (u.bin.lo != 0)+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.bin.lo));+ if (u.bin.hi != 0)+ FAIL_IF(load_immediate(compiler, DR(TMP_REG2), u.bin.hi)); - if (flags & SRC2_IMM) {- if (is_overflow) {- if (src2 >= 0)- 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(EQUAL_FLAG), EQUAL_FLAG));- }- else if (op & SLJIT_SET_Z)- FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, MTC1 | (u.bin.lo != 0 ? T(TMP_REG1) : TA(0)) | FS(freg), MOVABLE_INS));+ switch (cpu_feature_list & CPU_FEATURE_FR) {+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+ case CPU_FEATURE_FR:+ return push_inst(compiler, MTHC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg), MOVABLE_INS);+#endif /* SLJIT_MIPS_REV >= 2 */+ default:+ FAIL_IF(push_inst(compiler, MTC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg) | (1 << 11), MOVABLE_INS));+ break;+ }+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ return SLJIT_SUCCESS;+} - 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 (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))- FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));- }- else {- 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));+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_s32 reg2 = 0;+ sljit_ins inst = FS(freg);+ sljit_ins mthc = MTC1, mfhc = MFC1;+ int is_32 = (op & SLJIT_32); - 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 (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))- FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));- }+ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); - if (!is_overflow)- return SLJIT_SUCCESS;- 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);+ op = GET_OPCODE(op);+ if (reg & REG_PAIR_MASK) {+ reg2 = REG_PAIR_SECOND(reg);+ reg = REG_PAIR_FIRST(reg); - case SLJIT_SUBC:- 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;- }+ inst |= T(reg2); - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);+ if (op == SLJIT_COPY_TO_F64)+ FAIL_IF(push_inst(compiler, MTC1 | inst, MOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, MFC1 | inst, DR(reg2))); - if (flags & SRC2_IMM) {- 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 (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)));+ inst = FS(freg) | (1 << 11);+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+ if (cpu_feature_list & CPU_FEATURE_FR) {+ mthc = MTHC1;+ mfhc = MFHC1;+ inst = FS(freg); }-- 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(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));+#endif /* SLJIT_MIPS_REV >= 2 */+ } - if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)- return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));-#else /* SLJIT_MIPS_REV < 1 */- FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));- return push_inst(compiler, MFLO | D(dst), DR(dst));-#endif /* SLJIT_MIPS_REV >= 1 */+ inst |= T(reg);+ if (!is_32 && !reg2) {+ switch (cpu_feature_list & CPU_FEATURE_FR) {+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+ case CPU_FEATURE_FR:+ mthc = MTHC1;+ mfhc = MFHC1;+ break;+#endif /* SLJIT_MIPS_REV >= 2 */+ default:+ inst |= (1 << 11);+ break; }--#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)- FAIL_IF(push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)));- FAIL_IF(push_inst(compiler, MUH | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));-#else /* SLJIT_MIPS_REV < 6 */- FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));- FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));- FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));-#endif /* SLJIT_MIPS_REV >= 6 */- 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);- return SLJIT_SUCCESS;-- case SLJIT_OR:- EMIT_LOGICAL(ORI, OR);- return SLJIT_SUCCESS;-- case SLJIT_XOR:- EMIT_LOGICAL(XORI, XOR);- return SLJIT_SUCCESS;-- case SLJIT_SHL:- EMIT_SHIFT(SLL, SLLV);- return SLJIT_SUCCESS;-- case SLJIT_LSHR:- EMIT_SHIFT(SRL, SRLV);- return SLJIT_SUCCESS;-- case SLJIT_ASHR:- EMIT_SHIFT(SRA, SRAV);- return SLJIT_SUCCESS; } - SLJIT_UNREACHABLE();- return SLJIT_SUCCESS;-}+ if (op == SLJIT_COPY_TO_F64)+ FAIL_IF(push_inst(compiler, mthc | inst, MOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, mfhc | inst, DR(reg))); -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));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ if (mthc == MTC1 || mfhc == MFC1)+ return push_inst(compiler, NOP, UNMOVABLE_INS);+#endif /* MIPS III */+ return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)@@ -451,8 +219,13 @@ sljit_ins ins = NOP; sljit_u8 offsets[4]; sljit_u8 *offsets_ptr = offsets;+#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN+ sljit_ins f64_hi = TA(7), f64_lo = TA(6);+#else+ sljit_ins f64_hi = TA(6), f64_lo = TA(7);+#endif /* SLJIT_LITTLE_ENDIAN */ - SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);+ SLJIT_ASSERT(reg_map[TMP_REG2] == 4 && freg_map[TMP_FREG1] == 12); arg_types >>= SLJIT_ARG_SHIFT; @@ -515,20 +288,28 @@ switch (types & SLJIT_ARG_MASK) { case SLJIT_ARG_TYPE_F64:- if (*offsets_ptr < 4 * sizeof (sljit_sw)) {+ if (*offsets_ptr < 4 * sizeof(sljit_sw)) { if (prev_ins != NOP) FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); /* Must be preceded by at least one other argument, * and its starting offset must be 8 because of alignment. */ SLJIT_ASSERT((*offsets_ptr >> 2) == 2);-- prev_ins = MFC1 | TA(6) | FS(float_arg_count) | (1 << 11);- ins = MFC1 | TA(7) | FS(float_arg_count);+ switch (cpu_feature_list & CPU_FEATURE_FR) {+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+ case CPU_FEATURE_FR:+ prev_ins = MFHC1 | f64_hi | FS(float_arg_count);+ break;+#endif /* SLJIT_MIPS_REV >= 2 */+ default:+ prev_ins = MFC1 | f64_hi | FS(float_arg_count) | (1 << 11);+ break;+ }+ ins = MFC1 | f64_lo | FS(float_arg_count); } else if (*offsets_ptr < 254) ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr); else if (*offsets_ptr == 254)- ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);+ ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1); float_arg_count--; break;@@ -538,7 +319,7 @@ else if (*offsets_ptr < 254) ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr); else if (*offsets_ptr == 254)- ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);+ ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1); float_arg_count--; break;@@ -573,8 +354,8 @@ sljit_s32 arg_types) { struct sljit_jump *jump;- sljit_u32 extra_space = (sljit_u32)type;- sljit_ins ins;+ sljit_u32 extra_space = 0;+ sljit_ins ins = NOP; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));@@ -583,14 +364,23 @@ PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); - PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {+ extra_space = (sljit_u32)type;+ PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));+ } else if (type & SLJIT_CALL_RETURN)+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins)); - SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);+ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25); - PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));+ if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)+ jump->flags |= IS_MOVABLE; if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) {- jump->flags |= IS_JAL | IS_CALL;+ jump->flags |= IS_JAL;++ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ jump->flags |= IS_CALL;+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); } else PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));@@ -598,6 +388,9 @@ jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); + /* Maximum number of instructions required for generating a constant. */+ compiler->size += 2;+ if (extra_space == 0) return jump; @@ -623,16 +416,37 @@ CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); - SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);-- if (src & SLJIT_IMM)- FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));- else if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));- else if (src & SLJIT_MEM) {+ if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));+ src = PIC_ADDR_REG;+ srcw = 0; }++ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {+ if (type & SLJIT_CALL_RETURN) {+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));+ src = PIC_ADDR_REG;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));++ if (ins != NOP)+ FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+ }++ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25);++ if (src == SLJIT_IMM)+ FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));+ else if (src != PIC_ADDR_REG)+ FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
src/c/pcre2/src/sljit/sljitNativeMIPS_64.c view
@@ -26,6 +26,23 @@ /* mips 64-bit arch dependent functions. */ +static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_s32 src2, sljit_s32 dst)+{+ FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG1) | FS(src1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG2) | FS(src2), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG2) | T(TMP_REG1) | D(TMP_REG2), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | T(TMP_REG1) | FS(dst), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ if (!(op & SLJIT_32))+ return push_inst(compiler, NOP, UNMOVABLE_INS);+#endif /* MIPS III */+ return SLJIT_SUCCESS;+}+ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) { sljit_s32 shift = 32;@@ -118,431 +135,67 @@ return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar); } -#define SELECT_OP(a, b) \- (!(op & SLJIT_32) ? a : b)--#define EMIT_LOGICAL(op_imm, op_norm) \- if (flags & SRC2_IMM) { \- if (op & SLJIT_SET_Z) \- FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \- if (!(flags & UNUSED_DEST)) \- FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \- } \- else { \- if (op & SLJIT_SET_Z) \- FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \- 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_32)); \- ins = op_dimm32; \- src2 -= 32; \- } \- else \- ins = (op & SLJIT_32) ? 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 (!(flags & UNUSED_DEST)) \- FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \- } \- else { \- ins = (op & SLJIT_32) ? 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 (!(flags & UNUSED_DEST)) \- FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \- }--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)+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) {- sljit_ins ins;- sljit_s32 is_overflow, is_carry, is_handled;-- switch (GET_OPCODE(op)) {- case SLJIT_MOV:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if (dst != src2)- return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));- return SLJIT_SUCCESS;-- case SLJIT_MOV_U8:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))- return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_MOV_S8:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)- if (op & SLJIT_32)- return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));-#endif /* SLJIT_MIPS_REV >= 1 */- 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));- }- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_MOV_U16:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))- return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_MOV_S16:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)- if (op & SLJIT_32)- return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));-#endif /* SLJIT_MIPS_REV >= 1 */- 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));- }- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_MOV_U32:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)- if (dst == src2)- return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11) | (0 << 11), DR(dst));-#endif /* SLJIT_MIPS_REV >= 2 */- 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));- }- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_MOV_S32:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {- return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));- }- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_NOT:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- if (op & SLJIT_SET_Z)- FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));- 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_REV && SLJIT_MIPS_REV >= 1)- 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 (!(flags & UNUSED_DEST))- FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));-#else /* SLJIT_MIPS_REV < 1 */- if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {- FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));- return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);- }- /* Nearly all instructions are unmovable in the following sequence. */- 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_32) ? 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));-#endif /* SLJIT_MIPS_REV >= 1 */- 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 (is_overflow) {- if (src2 >= 0)- 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(EQUAL_FLAG), EQUAL_FLAG));- }- 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 (is_overflow || is_carry) {- if (src2 >= 0)- 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(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 (!(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 (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 (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 (!(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 (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(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 (is_carry) {- if (src2 >= 0)- 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(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 (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 (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(OTHER_FLAG) | D(dst), DR(dst)));- if (!is_carry)- return SLJIT_SUCCESS;-- /* 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(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);-- case SLJIT_SUB:- 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, 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(EQUAL_FLAG), EQUAL_FLAG));- else- FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));- }- 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 (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 (!(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 (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 (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 (!(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 (!is_overflow)- return SLJIT_SUCCESS;- 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) {- FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));- src2 = TMP_REG2;- flags &= ~SRC2_IMM;- }-- is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);-- if (flags & SRC2_IMM) {- 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 (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 (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(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;+ 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)));+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));+ FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));+ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));+} - case SLJIT_MUL:- SLJIT_ASSERT(!(flags & SRC2_IMM));+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ union {+ sljit_sw imm;+ sljit_f64 value;+ } u; - if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)- return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));-#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)- if (op & SLJIT_32)- 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));-#else /* SLJIT_MIPS_REV < 1 */- FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));- return push_inst(compiler, MFLO | D(dst), DR(dst));-#endif /* SLJIT_MIPS_REV >= 6 */- }+ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value)); -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)- FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));- FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));-#else /* SLJIT_MIPS_REV < 6 */- FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));- FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));- FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));-#endif /* SLJIT_MIPS_REV >= 6 */- 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);+ u.value = value; - case SLJIT_AND:- EMIT_LOGICAL(ANDI, AND);+ if (u.imm == 0) {+ FAIL_IF(push_inst(compiler, DMTC1 | TA(0) | FS(freg), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */ return SLJIT_SUCCESS;+ } - case SLJIT_OR:- EMIT_LOGICAL(ORI, OR);- return SLJIT_SUCCESS;+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));+ FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ return SLJIT_SUCCESS;+} - case SLJIT_XOR:- EMIT_LOGICAL(XORI, XOR);- return SLJIT_SUCCESS;+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_ins inst; - case SLJIT_SHL:- EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);- return SLJIT_SUCCESS;+ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); - case SLJIT_LSHR:- EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);- return SLJIT_SUCCESS;+ inst = T(reg) | FS(freg); - case SLJIT_ASHR:- EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);- return SLJIT_SUCCESS;- }+ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)+ FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | inst, MOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | inst, DR(reg))); - SLJIT_UNREACHABLE();+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ if (!(op & SLJIT_32))+ return push_inst(compiler, NOP, UNMOVABLE_INS);+#endif /* MIPS III */ return SLJIT_SUCCESS; } -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)));- FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));- FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));- FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(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_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr;@@ -572,7 +225,7 @@ sljit_ins prev_ins = *ins_ptr; sljit_ins ins = NOP; - SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);+ SLJIT_ASSERT(reg_map[TMP_REG2] == 4 && freg_map[TMP_FREG1] == 12); arg_types >>= SLJIT_ARG_SHIFT; @@ -598,17 +251,17 @@ switch (types & SLJIT_ARG_MASK) { case SLJIT_ARG_TYPE_F64: if (arg_count != float_arg_count)- ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count);+ ins = MOV_fmt(FMT_D) | FS(float_arg_count) | FD(arg_count); else if (arg_count == 1)- ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);+ ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1); arg_count--; float_arg_count--; break; case SLJIT_ARG_TYPE_F32: if (arg_count != float_arg_count)- ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count);+ ins = MOV_fmt(FMT_S) | FS(float_arg_count) | FD(arg_count); else if (arg_count == 1)- ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);+ ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1); arg_count--; float_arg_count--; break;@@ -653,14 +306,20 @@ if (type & SLJIT_CALL_RETURN) PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins)); - PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins)); - SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);+ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25); - PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));+ if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)+ jump->flags |= IS_MOVABLE; if (!(type & SLJIT_CALL_RETURN)) {- jump->flags |= IS_JAL | IS_CALL;+ jump->flags |= IS_JAL;++ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ jump->flags |= IS_CALL;+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); } else PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));@@ -668,6 +327,8 @@ jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); + /* Maximum number of instructions required for generating a constant. */+ compiler->size += 6; return jump; } @@ -680,16 +341,37 @@ CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); - SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);-- if (src & SLJIT_IMM)- FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));- else if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));- else if (src & SLJIT_MEM) {+ if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));+ src = PIC_ADDR_REG;+ srcw = 0; }++ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {+ if (type & SLJIT_CALL_RETURN) {+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));+ src = PIC_ADDR_REG;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));++ if (ins != NOP)+ FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+ }++ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG1);++ if (src == SLJIT_IMM)+ FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));+ else if (src != PIC_ADDR_REG)+ FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); if (type & SLJIT_CALL_RETURN) FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
src/c/pcre2/src/sljit/sljitNativeMIPS_common.c view
@@ -26,2485 +26,4234 @@ /* Latest MIPS architecture. */ -#ifndef __mips_hard_float-/* Disable automatic detection, covers both -msoft-float and -mno-float */-#undef SLJIT_IS_FPU_AVAILABLE-#define SLJIT_IS_FPU_AVAILABLE 0-#endif--SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)-{-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- return "MIPS32-R6" SLJIT_CPUINFO;-#else /* !SLJIT_CONFIG_MIPS_32 */- return "MIPS64-R6" SLJIT_CPUINFO;-#endif /* SLJIT_CONFIG_MIPS_32 */--#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- return "MIPS32-R1" SLJIT_CPUINFO;-#else /* !SLJIT_CONFIG_MIPS_32 */- return "MIPS64-R1" SLJIT_CPUINFO;-#endif /* SLJIT_CONFIG_MIPS_32 */--#else /* SLJIT_MIPS_REV < 1 */- return "MIPS III" SLJIT_CPUINFO;-#endif /* SLJIT_MIPS_REV >= 6 */-}--/* Length of an instruction word- Both for mips-32 and mips-64 */-typedef sljit_u32 sljit_ins;--#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)-#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)-#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)--/* For position independent code, t9 must contain the function address. */-#define PIC_ADDR_REG TMP_REG2--/* Floating point status register. */-#define FCSR_REG 31-/* Return address register. */-#define RETURN_ADDR_REG 31--/* Flags are kept in volatile registers. */-#define EQUAL_FLAG 3-#define OTHER_FLAG 1--#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)-#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)-#define TMP_FREG3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3)--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, 4, 25, 31-};--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)--static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {- 0, 0, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20, 12, 10, 16-};--#else--static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {- 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 31, 30, 29, 28, 27, 26, 25, 24, 12, 11, 10-};--#endif--/* --------------------------------------------------------------------- */-/* Instrucion forms */-/* --------------------------------------------------------------------- */--#define S(s) ((sljit_ins)reg_map[s] << 21)-#define T(t) ((sljit_ins)reg_map[t] << 16)-#define D(d) ((sljit_ins)reg_map[d] << 11)-#define FT(t) ((sljit_ins)freg_map[t] << 16)-#define FS(s) ((sljit_ins)freg_map[s] << 11)-#define FD(d) ((sljit_ins)freg_map[d] << 6)-/* Absolute registers. */-#define SA(s) ((sljit_ins)(s) << 21)-#define TA(t) ((sljit_ins)(t) << 16)-#define DA(d) ((sljit_ins)(d) << 11)-#define IMM(imm) ((sljit_ins)(imm) & 0xffff)-#define SH_IMM(imm) ((sljit_ins)(imm) << 6)--#define DR(dr) (reg_map[dr])-#define FR(dr) (freg_map[dr])-#define HI(opcode) ((sljit_ins)(opcode) << 26)-#define LO(opcode) ((sljit_ins)(opcode))-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)-/* CMP.cond.fmt */-/* S = (20 << 21) D = (21 << 21) */-#define CMP_FMT_S (20 << 21)-#endif /* SLJIT_MIPS_REV >= 6 */-/* S = (16 << 21) D = (17 << 21) */-#define FMT_S (16 << 21)-#define FMT_D (17 << 21)--#define ABS_S (HI(17) | FMT_S | LO(5))-#define ADD_S (HI(17) | FMT_S | LO(0))-#define ADDIU (HI(9))-#define ADDU (HI(0) | LO(33))-#define AND (HI(0) | LO(36))-#define ANDI (HI(12))-#define B (HI(4))-#define BAL (HI(1) | (17 << 16))-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)-#define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3))-#define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3))-#else /* SLJIT_MIPS_REV < 6 */-#define BC1F (HI(17) | (8 << 21))-#define BC1T (HI(17) | (8 << 21) | (1 << 16))-#endif /* SLJIT_MIPS_REV >= 6 */-#define BEQ (HI(4))-#define BGEZ (HI(1) | (1 << 16))-#define BGTZ (HI(7))-#define BLEZ (HI(6))-#define BLTZ (HI(1) | (0 << 16))-#define BNE (HI(5))-#define BREAK (HI(0) | LO(13))-#define CFC1 (HI(17) | (2 << 21))-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)-#define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))-#define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))-#define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))-#define C_UN_S (HI(17) | CMP_FMT_S | LO(1))-#define C_FD (FD(TMP_FREG3))-#else /* SLJIT_MIPS_REV < 6 */-#define C_UEQ_S (HI(17) | FMT_S | LO(51))-#define C_ULE_S (HI(17) | FMT_S | LO(55))-#define C_ULT_S (HI(17) | FMT_S | LO(53))-#define C_UN_S (HI(17) | FMT_S | LO(49))-#define C_FD (0)-#endif /* SLJIT_MIPS_REV >= 6 */-#define CVT_S_S (HI(17) | FMT_S | LO(32))-#define DADDIU (HI(25))-#define DADDU (HI(0) | LO(45))-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)-#define DDIV (HI(0) | (2 << 6) | LO(30))-#define DDIVU (HI(0) | (2 << 6) | LO(31))-#define DMOD (HI(0) | (3 << 6) | LO(30))-#define DMODU (HI(0) | (3 << 6) | LO(31))-#define DIV (HI(0) | (2 << 6) | LO(26))-#define DIVU (HI(0) | (2 << 6) | LO(27))-#define DMUH (HI(0) | (3 << 6) | LO(28))-#define DMUHU (HI(0) | (3 << 6) | LO(29))-#define DMUL (HI(0) | (2 << 6) | LO(28))-#define DMULU (HI(0) | (2 << 6) | LO(29))-#else /* SLJIT_MIPS_REV < 6 */-#define DDIV (HI(0) | LO(30))-#define DDIVU (HI(0) | LO(31))-#define DIV (HI(0) | LO(26))-#define DIVU (HI(0) | LO(27))-#define DMULT (HI(0) | LO(28))-#define DMULTU (HI(0) | LO(29))-#endif /* SLJIT_MIPS_REV >= 6 */-#define DIV_S (HI(17) | FMT_S | LO(3))-#define DINSU (HI(31) | LO(6))-#define DSLL (HI(0) | LO(56))-#define DSLL32 (HI(0) | LO(60))-#define DSLLV (HI(0) | LO(20))-#define DSRA (HI(0) | LO(59))-#define DSRA32 (HI(0) | LO(63))-#define DSRAV (HI(0) | LO(23))-#define DSRL (HI(0) | LO(58))-#define DSRL32 (HI(0) | LO(62))-#define DSRLV (HI(0) | LO(22))-#define DSUBU (HI(0) | LO(47))-#define J (HI(2))-#define JAL (HI(3))-#define JALR (HI(0) | LO(9))-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)-#define JR (HI(0) | LO(9))-#else /* SLJIT_MIPS_REV < 6 */-#define JR (HI(0) | LO(8))-#endif /* SLJIT_MIPS_REV >= 6 */-#define LD (HI(55))-#define LDC1 (HI(53))-#define LUI (HI(15))-#define LW (HI(35))-#define LWC1 (HI(49))-#define MFC1 (HI(17))-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)-#define MOD (HI(0) | (3 << 6) | LO(26))-#define MODU (HI(0) | (3 << 6) | LO(27))-#else /* SLJIT_MIPS_REV < 6 */-#define MFHI (HI(0) | LO(16))-#define MFLO (HI(0) | LO(18))-#endif /* SLJIT_MIPS_REV >= 6 */-#define MOV_S (HI(17) | FMT_S | LO(6))-#define MTC1 (HI(17) | (4 << 21))-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)-#define MUH (HI(0) | (3 << 6) | LO(24))-#define MUHU (HI(0) | (3 << 6) | LO(25))-#define MUL (HI(0) | (2 << 6) | LO(24))-#define MULU (HI(0) | (2 << 6) | LO(25))-#else /* SLJIT_MIPS_REV < 6 */-#define MULT (HI(0) | LO(24))-#define MULTU (HI(0) | LO(25))-#endif /* SLJIT_MIPS_REV >= 6 */-#define MUL_S (HI(17) | FMT_S | LO(2))-#define NEG_S (HI(17) | FMT_S | LO(7))-#define NOP (HI(0) | LO(0))-#define NOR (HI(0) | LO(39))-#define OR (HI(0) | LO(37))-#define ORI (HI(13))-#define SD (HI(63))-#define SDC1 (HI(61))-#define SLT (HI(0) | LO(42))-#define SLTI (HI(10))-#define SLTIU (HI(11))-#define SLTU (HI(0) | LO(43))-#define SLL (HI(0) | LO(0))-#define SLLV (HI(0) | LO(4))-#define SRL (HI(0) | LO(2))-#define SRLV (HI(0) | LO(6))-#define SRA (HI(0) | LO(3))-#define SRAV (HI(0) | LO(7))-#define SUB_S (HI(17) | FMT_S | LO(1))-#define SUBU (HI(0) | LO(35))-#define SW (HI(43))-#define SWC1 (HI(57))-#define TRUNC_W_S (HI(17) | FMT_S | LO(13))-#define XOR (HI(0) | LO(38))-#define XORI (HI(14))--#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)-#define CLZ (HI(28) | LO(32))-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)-#define DCLZ (LO(18))-#else /* SLJIT_MIPS_REV < 6 */-#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))-#endif /* SLJIT_MIPS_REV >= 6 */-#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 /* SLJIT_MIPS_REV >= 1 */--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)-#define ADDU_W ADDU-#define ADDIU_W ADDIU-#define SLL_W SLL-#define SUBU_W SUBU-#else-#define ADDU_W DADDU-#define ADDIU_W DADDIU-#define SLL_W DSLL-#define SUBU_W DSUBU-#endif--#define SIMM_MAX (0x7fff)-#define SIMM_MIN (-0x8000)-#define UIMM_MAX (0xffff)--/* dest_reg is the absolute name of the register- Useful for reordering instructions in the delay slot. */-static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)-{- sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));- SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS- || (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)- || (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));- FAIL_IF(!ptr);- *ptr = ins;- compiler->size++;- compiler->delay_slot = delay_slot;- return SLJIT_SUCCESS;-}--static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)-{- if (flags & IS_BIT26_COND)- return (1 << 26);-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)- if (flags & IS_BIT23_COND)- return (1 << 23);-#endif /* SLJIT_MIPS_REV >= 6 */- return (1 << 16);-}--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;- sljit_ins *inst;- sljit_ins saved_inst;--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))- return code_ptr;-#else- if (jump->flags & SLJIT_REWRITABLE_JUMP)- return code_ptr;-#endif-- if (jump->flags & JUMP_ADDR)- target_addr = jump->u.target;- else {- SLJIT_ASSERT(jump->flags & JUMP_LABEL);- target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;- }-- inst = (sljit_ins *)jump->addr;- if (jump->flags & IS_COND)- inst--;--#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- if (jump->flags & IS_CALL)- goto keep_address;-#endif-- /* B instructions. */- if (jump->flags & IS_MOVABLE) {- diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;- if (diff <= SIMM_MAX && diff >= SIMM_MIN) {- jump->flags |= PATCH_B;-- if (!(jump->flags & IS_COND)) {- inst[0] = inst[-1];- inst[-1] = (jump->flags & IS_JAL) ? BAL : B;- jump->addr -= sizeof(sljit_ins);- return inst;- }- saved_inst = inst[0];- inst[0] = inst[-1];- inst[-1] = saved_inst ^ invert_branch(jump->flags);- jump->addr -= 2 * sizeof(sljit_ins);- return inst;- }- }- else {- diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;- if (diff <= SIMM_MAX && diff >= SIMM_MIN) {- jump->flags |= PATCH_B;-- if (!(jump->flags & IS_COND)) {- inst[0] = (jump->flags & IS_JAL) ? BAL : B;- inst[1] = NOP;- return inst + 1;- }- inst[0] ^= invert_branch(jump->flags);- inst[1] = NOP;- jump->addr -= sizeof(sljit_ins);- return inst + 1;- }- }-- if (jump->flags & IS_COND) {- if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {- jump->flags |= PATCH_J;- saved_inst = inst[0];- inst[0] = inst[-1];- inst[-1] = (saved_inst & 0xffff0000) | 3;- inst[1] = J;- inst[2] = NOP;- return inst + 2;- }- else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {- jump->flags |= PATCH_J;- inst[0] = (inst[0] & 0xffff0000) | 3;- inst[1] = NOP;- inst[2] = J;- inst[3] = NOP;- jump->addr += sizeof(sljit_ins);- return inst + 3;- }- }- else {- /* J instuctions. */- if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {- jump->flags |= PATCH_J;- inst[0] = inst[-1];- inst[-1] = (jump->flags & IS_JAL) ? JAL : J;- jump->addr -= sizeof(sljit_ins);- return inst;- }-- if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {- jump->flags |= PATCH_J;- inst[0] = (jump->flags & IS_JAL) ? JAL : J;- inst[1] = NOP;- return inst + 1;- }- }--#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)-keep_address:- if (target_addr <= 0x7fffffff) {- jump->flags |= PATCH_ABS32;- if (jump->flags & IS_COND) {- inst[0] -= 4;- inst++;- }- inst[2] = inst[6];- inst[3] = inst[7];- return inst + 3;- }- if (target_addr <= 0x7fffffffffffl) {- jump->flags |= PATCH_ABS48;- if (jump->flags & IS_COND) {- inst[0] -= 2;- inst++;- }- inst[4] = inst[6];- inst[5] = inst[7];- return inst + 5;- }-#endif-- return code_ptr;-}--#ifdef __GNUC__-static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)-{- SLJIT_CACHE_FLUSH(code, code_ptr);-}-#endif--#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)--static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)-{- if (max_label < 0x80000000l) {- put_label->flags = 0;- return 1;- }-- if (max_label < 0x800000000000l) {- put_label->flags = 1;- return 3;- }-- put_label->flags = 2;- return 5;-}--static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)-{- sljit_uw addr = put_label->label->addr;- sljit_ins *inst = (sljit_ins *)put_label->addr;- sljit_u32 reg = *inst;-- if (put_label->flags == 0) {- SLJIT_ASSERT(addr < 0x80000000l);- inst[0] = LUI | T(reg) | IMM(addr >> 16);- }- else if (put_label->flags == 1) {- SLJIT_ASSERT(addr < 0x800000000000l);- inst[0] = LUI | T(reg) | IMM(addr >> 32);- inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);- inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);- inst += 2;- }- else {- inst[0] = LUI | T(reg) | IMM(addr >> 48);- inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);- inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);- inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);- inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);- inst += 4;- }-- inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);-}--#endif--SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)-{- struct sljit_memory_fragment *buf;- sljit_ins *code;- sljit_ins *code_ptr;- sljit_ins *buf_ptr;- sljit_ins *buf_end;- sljit_uw word_count;- sljit_uw next_addr;- sljit_sw executable_offset;- sljit_uw addr;-- struct sljit_label *label;- struct sljit_jump *jump;- struct sljit_const *const_;- struct sljit_put_label *put_label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_generate_code(compiler));- reverse_buf(compiler);-- code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);- PTR_FAIL_WITH_EXEC_IF(code);- buf = compiler->buf;-- code_ptr = code;- word_count = 0;- next_addr = 0;- executable_offset = SLJIT_EXEC_OFFSET(code);-- label = compiler->labels;- jump = compiler->jumps;- const_ = compiler->consts;- put_label = compiler->put_labels;-- do {- buf_ptr = (sljit_ins*)buf->memory;- buf_end = buf_ptr + (buf->used_size >> 2);- do {- *code_ptr = *buf_ptr++;- if (next_addr == word_count) {- SLJIT_ASSERT(!label || label->size >= word_count);- SLJIT_ASSERT(!jump || jump->addr >= word_count);- SLJIT_ASSERT(!const_ || const_->addr >= word_count);- SLJIT_ASSERT(!put_label || put_label->addr >= word_count);-- /* These structures are ordered by their address. */- if (label && label->size == word_count) {- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }- if (jump && jump->addr == word_count) {-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- jump->addr = (sljit_uw)(code_ptr - 3);-#else- jump->addr = (sljit_uw)(code_ptr - 7);-#endif- code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);- jump = jump->next;- }- if (const_ && const_->addr == word_count) {- const_->addr = (sljit_uw)code_ptr;- const_ = const_->next;- }- if (put_label && put_label->addr == word_count) {- SLJIT_ASSERT(put_label->label);- put_label->addr = (sljit_uw)code_ptr;-#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));- word_count += 5;-#endif- put_label = put_label->next;- }- next_addr = compute_next_addr(label, jump, const_, put_label);- }- code_ptr ++;- word_count ++;- } while (buf_ptr < buf_end);-- buf = buf->next;- } while (buf);-- if (label && label->size == word_count) {- label->addr = (sljit_uw)code_ptr;- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }-- SLJIT_ASSERT(!label);- SLJIT_ASSERT(!jump);- SLJIT_ASSERT(!const_);- SLJIT_ASSERT(!put_label);- SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);-- jump = compiler->jumps;- while (jump) {- do {- addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;- buf_ptr = (sljit_ins *)jump->addr;-- if (jump->flags & PATCH_B) {- addr = (sljit_uw)((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) | ((sljit_ins)addr & 0xffff);- break;- }- if (jump->flags & PATCH_J) {- SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)- == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));- buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;- break;- }-- /* Set the fields of immediate loads. */-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);- buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;- buf_ptr[1] |= (sljit_ins)addr & 0xffff;-#else- if (jump->flags & PATCH_ABS32) {- SLJIT_ASSERT(addr <= 0x7fffffff);- SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);- buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;- buf_ptr[1] |= (sljit_ins)addr & 0xffff;- break;- }-- if (jump->flags & PATCH_ABS48) {- SLJIT_ASSERT(addr <= 0x7fffffffffffl);- SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3]) & 0xffff) == 0);- buf_ptr[0] |= (sljit_ins)(addr >> 32) & 0xffff;- buf_ptr[1] |= (sljit_ins)(addr >> 16) & 0xffff;- buf_ptr[3] |= (sljit_ins)addr & 0xffff;- break;- }-- SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3] | buf_ptr[5]) & 0xffff) == 0);- buf_ptr[0] |= (sljit_ins)(addr >> 48) & 0xffff;- buf_ptr[1] |= (sljit_ins)(addr >> 32) & 0xffff;- buf_ptr[3] |= (sljit_ins)(addr >> 16) & 0xffff;- buf_ptr[5] |= (sljit_ins)addr & 0xffff;-#endif- } while (0);- jump = jump->next;- }-- put_label = compiler->put_labels;- while (put_label) {-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- addr = put_label->label->addr;- buf_ptr = (sljit_ins *)put_label->addr;-- SLJIT_ASSERT((buf_ptr[0] & 0xffe00000) == LUI && (buf_ptr[1] & 0xfc000000) == ORI);- buf_ptr[0] |= (addr >> 16) & 0xffff;- buf_ptr[1] |= addr & 0xffff;-#else- put_label_set(put_label);-#endif- put_label = put_label->next;- }-- compiler->error = SLJIT_ERR_COMPILED;- compiler->executable_offset = executable_offset;- compiler->executable_size = (sljit_uw)(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- /* GCC workaround for invalid code generation with -O2. */- sljit_cache_flush(code, code_ptr);-#endif- SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);- return code;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)-{-#if defined(__GNUC__) && !defined(SLJIT_IS_FPU_AVAILABLE)- sljit_sw fir = 0;-#endif /* __GNUC__ && !SLJIT_IS_FPU_AVAILABLE */-- switch (feature_type) {- case SLJIT_HAS_FPU:-#ifdef SLJIT_IS_FPU_AVAILABLE- return SLJIT_IS_FPU_AVAILABLE;-#elif defined(__GNUC__)- __asm__ ("cfc1 %0, $0" : "=r"(fir));- return (fir >> 22) & 0x1;-#else-#error "FIR check is not implemented for this architecture"-#endif- case SLJIT_HAS_ZERO_REGISTER:- return 1;--#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)- case SLJIT_HAS_CLZ:- case SLJIT_HAS_CMOV:- case SLJIT_HAS_PREFETCH:- return 1;-#endif /* SLJIT_MIPS_REV >= 1 */-- default:- return 0;- }-}--/* --------------------------------------------------------------------- */-/* Entry, exit */-/* --------------------------------------------------------------------- */--/* Creates an index in data_transfer_insts array. */-#define LOAD_DATA 0x01-#define WORD_DATA 0x00-#define BYTE_DATA 0x02-#define HALF_DATA 0x04-#define INT_DATA 0x06-#define SIGNED_DATA 0x08-/* Separates integer and floating point registers */-#define GPR_REG 0x0f-#define DOUBLE_DATA 0x10-#define SINGLE_DATA 0x12--#define MEM_MASK 0x1f--#define ARG_TEST 0x00020-#define ALT_KEEP_CACHE 0x00040-#define CUMULATIVE_OP 0x00080-#define LOGICAL_OP 0x00100-#define IMM_OP 0x00200-#define MOVE_OP 0x00400-#define SRC2_IMM 0x00800--#define UNUSED_DEST 0x01000-#define REG_DEST 0x02000-#define REG1_SOURCE 0x04000-#define REG2_SOURCE 0x08000-#define SLOW_SRC1 0x10000-#define SLOW_SRC2 0x20000-#define SLOW_DEST 0x40000--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)-#define STACK_STORE SW-#define STACK_LOAD LW-#else-#define STACK_STORE SD-#define STACK_LOAD LD-#endif--static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);-static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)-#include "sljitNativeMIPS_32.c"-#else-#include "sljitNativeMIPS_64.c"-#endif--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_ins base;- sljit_s32 i, tmp, offset;- sljit_s32 arg_count, word_arg_count, saved_arg_count, float_arg_count;-- CHECK_ERROR();- CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {- if ((local_size & SSIZE_OF(sw)) != 0)- local_size += SSIZE_OF(sw);- local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));- }-- local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;-#else- local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));- local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;-#endif- compiler->local_size = local_size;--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- tmp = arg_types >> SLJIT_ARG_SHIFT;- arg_count = 0;- offset = 0;-- while (tmp) {- offset = arg_count;- if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {- if ((arg_count & 0x1) != 0)- arg_count++;- arg_count++;- }-- arg_count++;- tmp >>= SLJIT_ARG_SHIFT;- }-- compiler->args_size = (sljit_uw)arg_count << 2;- offset = (offset >= 4) ? (offset << 2) : 0;-#else /* !SLJIT_CONFIG_MIPS_32 */- offset = 0;-#endif /* SLJIT_CONFIG_MIPS_32 */-- if (local_size + offset <= -SIMM_MIN) {- /* Frequent case. */- FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));- base = S(SLJIT_SP);- offset = local_size - SSIZE_OF(sw);- } else {- FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));- FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));- FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));- base = S(TMP_REG2);- offset = -SSIZE_OF(sw);-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- local_size = 0;-#endif- }-- FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offset), MOVABLE_INS));-- tmp = SLJIT_S0 - saveds;- for (i = SLJIT_S0; i > tmp; i--) {- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS));- }-- for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS));- }--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- /* This alignment is valid because offset is not used after storing FPU regs. */- if ((offset & SSIZE_OF(sw)) != 0)- offset -= SSIZE_OF(sw);-#endif-- tmp = SLJIT_FS0 - fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- offset -= SSIZE_OF(f64);- FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));- }-- for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- offset -= SSIZE_OF(f64);- FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));- }-- arg_types >>= SLJIT_ARG_SHIFT;- arg_count = 0;- word_arg_count = 0;- saved_arg_count = 0;- float_arg_count = 0;--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- /* The first maximum two floating point arguments are passed in floating point- registers if no integer argument precedes them. The first 16 byte data is- passed in four integer registers, the rest is placed onto the stack.- The floating point registers are also part of the first 16 byte data, so- their corresponding integer registers are not used when they are present. */-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- float_arg_count++;- if ((arg_count & 0x1) != 0)- arg_count++;-- if (word_arg_count == 0 && float_arg_count <= 2) {- if (float_arg_count == 1)- FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));- } else if (arg_count < 4) {- FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));- FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));- } else- FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));- arg_count++;- break;- case SLJIT_ARG_TYPE_F32:- float_arg_count++;-- if (word_arg_count == 0 && float_arg_count <= 2) {- if (float_arg_count == 1)- FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));- } else if (arg_count < 4)- FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));- else- FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));- break;- default:- word_arg_count++;-- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- tmp = SLJIT_S0 - saved_arg_count;- saved_arg_count++;- } else if (word_arg_count != arg_count + 1 || arg_count == 0)- tmp = word_arg_count;- else- break;-- if (arg_count < 4)- FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));- else- FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));- break;- }- arg_count++;- arg_types >>= SLJIT_ARG_SHIFT;- }-- SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);-#else /* !SLJIT_CONFIG_MIPS_32 */- while (arg_types) {- arg_count++;- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- float_arg_count++;- if (arg_count != float_arg_count)- FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));- else if (arg_count == 1)- FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));- break;- case SLJIT_ARG_TYPE_F32:- float_arg_count++;- if (arg_count != float_arg_count)- FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));- else if (arg_count == 1)- FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));- break;- default:- word_arg_count++;-- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- tmp = SLJIT_S0 - saved_arg_count;- saved_arg_count++;- } else if (word_arg_count != arg_count || word_arg_count <= 1)- tmp = word_arg_count;- else- break;-- FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));- break;- }- arg_types >>= SLJIT_ARG_SHIFT;- }-#endif /* SLJIT_CONFIG_MIPS_32 */-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- CHECK_ERROR();- CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {- if ((local_size & SSIZE_OF(sw)) != 0)- local_size += SSIZE_OF(sw);- local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));- }-- compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;-#else- local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));- compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;-#endif- return SLJIT_SUCCESS;-}--static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)-{- sljit_s32 local_size, i, tmp, offset;- sljit_s32 scratches = compiler->scratches;- sljit_s32 saveds = compiler->saveds;- sljit_s32 fsaveds = compiler->fsaveds;- sljit_s32 fscratches = compiler->fscratches;-- local_size = compiler->local_size;-- tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {- if ((tmp & SSIZE_OF(sw)) != 0)- tmp += SSIZE_OF(sw);- tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));- }-#else- tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));-#endif-- if (local_size <= SIMM_MAX) {- if (local_size < frame_size) {- FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));- local_size = frame_size;- }- } else {- if (tmp < frame_size)- tmp = frame_size;-- FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size - tmp));- FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(SLJIT_SP), DR(SLJIT_SP)));- local_size = tmp;- }-- SLJIT_ASSERT(local_size >= frame_size);-- offset = local_size - SSIZE_OF(sw);- if (frame_size == 0)- FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));-- tmp = SLJIT_S0 - saveds;- for (i = SLJIT_S0; i > tmp; i--) {- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));- }-- for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));- }--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- /* This alignment is valid because offset is not used after storing FPU regs. */- if ((offset & SSIZE_OF(sw)) != 0)- offset -= SSIZE_OF(sw);-#endif-- tmp = SLJIT_FS0 - fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- offset -= SSIZE_OF(f64);- FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));- }-- for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- offset -= SSIZE_OF(f64);- FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));- }-- if (local_size > frame_size)- *ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);- else- *ins_ptr = NOP;-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)-{- sljit_ins ins;-- CHECK_ERROR();- CHECK(check_sljit_emit_return_void(compiler));-- emit_stack_frame_release(compiler, 0, &ins);-- FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));- return push_inst(compiler, ins, UNMOVABLE_INS);-}--#undef STACK_STORE-#undef STACK_LOAD--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)-#define ARCH_32_64(a, b) a-#else-#define ARCH_32_64(a, b) b-#endif--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 */,-/* u b l */ HI(36) /* lbu */,-/* u h s */ HI(41) /* sh */,-/* u h l */ HI(37) /* lhu */,-/* u i s */ HI(43) /* sw */,-/* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),--/* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),-/* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),-/* s b s */ HI(40) /* sb */,-/* s b l */ HI(32) /* lb */,-/* s h s */ HI(41) /* sh */,-/* s h l */ HI(33) /* lh */,-/* s i s */ HI(43) /* sw */,-/* s i l */ HI(35) /* lw */,--/* d s */ HI(61) /* sdc1 */,-/* d l */ HI(53) /* ldc1 */,-/* s s */ HI(57) /* swc1 */,-/* s l */ HI(49) /* lwc1 */,-};--#undef ARCH_32_64--/* reg_ar is an absoulute register! */--/* Can perform an operation using at most 1 instruction. */-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);-- if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {- /* Works for both absoulte and relative addresses. */- if (SLJIT_UNLIKELY(flags & ARG_TEST))- return 1;- FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)- | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));- return -1;- }- return 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_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));-- /* Simple operation except for updates. */- if (arg & OFFS_REG_MASK) {- argw &= 0x3;- next_argw &= 0x3;- if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))- return 1;- return 0;- }-- if (arg == next_arg) {- if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))- return 1;- return 0;- }-- return 0;-}--/* Emit the necessary instructions. See can_cache above. */-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_s32 tmp_ar, base, delay_slot;-- SLJIT_ASSERT(arg & SLJIT_MEM);- if (!(next_arg & SLJIT_MEM)) {- next_arg = 0;- next_argw = 0;- }-- if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {- tmp_ar = reg_ar;- delay_slot = reg_ar;- }- else {- tmp_ar = DR(TMP_REG1);- delay_slot = MOVABLE_INS;- }- base = arg & REG_MASK;-- if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {- argw &= 0x3;-- /* Using the cache. */- if (argw == compiler->cache_argw) {- 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);- }- 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);- }- }-- if (SLJIT_UNLIKELY(argw)) {- compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);- compiler->cache_argw = argw;- FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));- }-- 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 (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {- if (argw != compiler->cache_argw) {- FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));- compiler->cache_argw = argw;- }- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);- }-- if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {- if (argw != compiler->cache_argw)- FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));- }- else {- compiler->cache_arg = SLJIT_MEM;- FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));- }- compiler->cache_argw = argw;-- if (!base)- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);-- if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {- compiler->cache_arg = arg;- FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | 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(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);-}--static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)-{- sljit_s32 tmp_ar, base, delay_slot;-- if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))- return compiler->error;-- if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {- tmp_ar = reg_ar;- delay_slot = reg_ar;- }- else {- tmp_ar = DR(TMP_REG1);- delay_slot = MOVABLE_INS;- }- base = arg & REG_MASK;-- if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {- argw &= 0x3;-- if (SLJIT_UNLIKELY(argw)) {- FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));- }- else- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);- }-- FAIL_IF(load_immediate(compiler, tmp_ar, argw));-- if (base != 0)- FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));-- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);-}--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_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_s32 dst_r = TMP_REG2;- sljit_s32 src1_r;- sljit_sw src2_r = 0;- sljit_s32 sugg_src2_r = TMP_REG2;-- if (!(flags & ALT_KEEP_CACHE)) {- compiler->cache_arg = 0;- compiler->cache_argw = 0;- }-- if (dst == TMP_REG2) {- SLJIT_ASSERT(HAS_FLAGS(op));- flags |= UNUSED_DEST;- }- else if (FAST_IS_REG(dst)) {- dst_r = dst;- flags |= REG_DEST;- if (flags & MOVE_OP)- sugg_src2_r = dst_r;- }- else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))- flags |= SLOW_DEST;-- if (flags & IMM_OP) {- if ((src2 & SLJIT_IMM) && src2w) {- if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_MAX && src2w >= SIMM_MIN))- || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_MAX))) {- flags |= SRC2_IMM;- src2_r = src2w;- }- }- if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {- if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN))- || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) {- flags |= SRC2_IMM;- src2_r = src1w;-- /* And swap arguments. */- src1 = src2;- src1w = src2w;- src2 = SLJIT_IMM;- /* src2w = src2_r unneeded. */- }- }- }-- /* Source 1. */- if (FAST_IS_REG(src1)) {- src1_r = src1;- flags |= REG1_SOURCE;- }- else if (src1 & SLJIT_IMM) {- if (src1w) {- FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));- src1_r = TMP_REG1;- }- else- src1_r = 0;- }- else {- if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))- FAIL_IF(compiler->error);- else- flags |= SLOW_SRC1;- src1_r = TMP_REG1;- }-- /* Source 2. */- if (FAST_IS_REG(src2)) {- src2_r = src2;- flags |= REG2_SOURCE;- if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)- dst_r = (sljit_s32)src2_r;- }- else if (src2 & SLJIT_IMM) {- if (!(flags & SRC2_IMM)) {- if (src2w) {- FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w));- src2_r = sugg_src2_r;- }- else {- src2_r = 0;- if (flags & MOVE_OP) {- if (dst & SLJIT_MEM)- dst_r = 0;- else- op = SLJIT_MOV;- }- }- }- }- else {- if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w))- FAIL_IF(compiler->error);- else- flags |= SLOW_SRC2;- src2_r = sugg_src2_r;- }-- if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {- SLJIT_ASSERT(src2_r == TMP_REG2);- if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));- }- else {- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));- }- }- else if (flags & SLOW_SRC1)- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));- else if (flags & SLOW_SRC2)- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w, dst, dstw));-- FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));-- if (dst & SLJIT_MEM) {- if (!(flags & SLOW_DEST)) {- getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);- return compiler->error;- }- return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);- }-- return SLJIT_SUCCESS;-}--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_s32 int_op = op & SLJIT_32;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_op0(compiler, op));-- op = GET_OPCODE(op);- switch (op) {- case SLJIT_BREAKPOINT:- return push_inst(compiler, BREAK, UNMOVABLE_INS);- case SLJIT_NOP:- return push_inst(compiler, NOP, UNMOVABLE_INS);- case SLJIT_LMUL_UW:- case SLJIT_LMUL_SW:-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)-#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));- FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));-#else /* !SLJIT_CONFIG_MIPS_64 */- FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));- FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));-#endif /* SLJIT_CONFIG_MIPS_64 */- FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));- return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));-#else /* SLJIT_MIPS_REV < 6 */-#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));-#else /* !SLJIT_CONFIG_MIPS_64 */- FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));-#endif /* SLJIT_CONFIG_MIPS_64 */- FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));- return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));-#endif /* SLJIT_MIPS_REV >= 6 */- 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_REV && SLJIT_MIPS_REV >= 6)-#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- if (int_op) {- FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));- FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));- }- else {- FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));- FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));- }-#else /* !SLJIT_CONFIG_MIPS_64 */- FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));- FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));-#endif /* SLJIT_CONFIG_MIPS_64 */- FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));- return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));-#else /* SLJIT_MIPS_REV < 6 */-#if !(defined SLJIT_MIPS_REV)- FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));- FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));-#endif /* !SLJIT_MIPS_REV */-#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- if (int_op)- 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_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));-#else /* !SLJIT_CONFIG_MIPS_64 */- FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));-#endif /* SLJIT_CONFIG_MIPS_64 */- FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));- return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));-#endif /* SLJIT_MIPS_REV >= 6 */- case SLJIT_ENDBR:- case SLJIT_SKIP_FRAMES_BEFORE_RETURN:- return SLJIT_SUCCESS;- }-- return SLJIT_SUCCESS;-}--#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)-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_MIPS_REV >= 1 */--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_s32 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 (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- if (op & SLJIT_32)- flags = INT_DATA | SIGNED_DATA;-#endif-- switch (GET_OPCODE(op)) {- case SLJIT_MOV:-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:-#endif- case SLJIT_MOV_P:- return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);--#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- case SLJIT_MOV_U32:- return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);-- case SLJIT_MOV_S32:- case SLJIT_MOV32:- return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw);-#endif-- case SLJIT_MOV_U8:- return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);-- case SLJIT_MOV_S8:- return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);-- case SLJIT_MOV_U16:- return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);-- case SLJIT_MOV_S16:- return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, 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);-- case SLJIT_CLZ:- return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);- }-- SLJIT_UNREACHABLE();- return SLJIT_SUCCESS;-}--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_s32 flags = 0;-- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);--#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- if (op & SLJIT_32) {- flags |= INT_DATA | SIGNED_DATA;- if (src1 & SLJIT_IMM)- src1w = (sljit_s32)src1w;- if (src2 & SLJIT_IMM)- src2w = (sljit_s32)src2w;- }-#endif-- switch (GET_OPCODE(op)) {- case SLJIT_ADD:- case SLJIT_ADDC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_SUB:- case SLJIT_SUBC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_MUL:- compiler->status_flags_state = 0;- return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_AND:- case SLJIT_OR:- case SLJIT_XOR:- return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_SHL:- case SLJIT_LSHR:- case SLJIT_ASHR:-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- if (src2 & SLJIT_IMM)- src2w &= 0x1f;-#else- if (src2 & SLJIT_IMM) {- if (op & SLJIT_32)- src2w &= 0x1f;- else- src2w &= 0x3f;- }-#endif- return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);- }-- SLJIT_UNREACHABLE();- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 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_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- switch (op) {- case SLJIT_FAST_RETURN:- if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));- else- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));-- FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));- return push_inst(compiler, NOP, UNMOVABLE_INS);- case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:- return SLJIT_SUCCESS;- case SLJIT_PREFETCH_L1:- case SLJIT_PREFETCH_L2:- case SLJIT_PREFETCH_L3:- case SLJIT_PREFETCH_ONCE:-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)- return emit_prefetch(compiler, src, srcw);-#else /* SLJIT_MIPS_REV < 1 */- return SLJIT_SUCCESS;-#endif /* SLJIT_MIPS_REV >= 1 */- }-- return SLJIT_SUCCESS;-}--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_s32 sljit_get_float_register_index(sljit_s32 reg)-{- CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));- return FR(reg);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_custom(compiler, instruction, size));-- return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);-}--/* --------------------------------------------------------------------- */-/* Floating point operators */-/* --------------------------------------------------------------------- */--#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))-#define FMT(op) ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) << (21 - 8))--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 (sljit_u32)0-#else- sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;-#endif-- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));- src = TMP_FREG1;- }-- FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));-- if (FAST_IS_REG(dst))- return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);-- /* Store the integer value from a VFP register. */- return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)-# undef is_long-#endif-}--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 (sljit_u32)0-#else- sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;-#endif-- sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));- else if (src & SLJIT_MEM) {- /* Load the integer value into a VFP register. */- FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));- }- else {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- 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) | ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));-- if (dst & SLJIT_MEM)- return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);- return SLJIT_SUCCESS;--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)-# undef flags-#endif-}--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, FR(TMP_FREG1), src1, src1w, src2, src2w));- src1 = TMP_FREG1;- }-- if (src2 & SLJIT_MEM) {- FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));- src2 = TMP_FREG2;- }-- 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) | C_FD, UNMOVABLE_INS);-}--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_s32 dst_r;-- CHECK_ERROR();- compiler->cache_arg = 0;- compiler->cache_argw = 0;-- SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);- SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);-- if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)- op ^= SLJIT_32;-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));- src = dst_r;- }-- switch (GET_OPCODE(op)) {- 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));- else- dst_r = src;- }- break;- case SLJIT_NEG_F64:- FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));- break;- case SLJIT_ABS_F64:- FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));- break;- case SLJIT_CONV_F64_FROM_F32:- FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));- op ^= SLJIT_32;- break;- }-- if (dst & SLJIT_MEM)- return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);- return SLJIT_SUCCESS;-}--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_s32 dst_r, flags = 0;-- CHECK_ERROR();- CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- compiler->cache_arg = 0;- compiler->cache_argw = 0;-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;-- if (src1 & SLJIT_MEM) {- if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {- FAIL_IF(compiler->error);- src1 = TMP_FREG1;- } else- flags |= SLOW_SRC1;- }-- if (src2 & SLJIT_MEM) {- if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {- FAIL_IF(compiler->error);- src2 = TMP_FREG2;- } 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, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));- }- else {- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));- }- }- else if (flags & SLOW_SRC1)- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));- else if (flags & SLOW_SRC2)- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));-- if (flags & SLOW_SRC1)- src1 = TMP_FREG1;- if (flags & SLOW_SRC2)- src2 = TMP_FREG2;-- switch (GET_OPCODE(op)) {- 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_SUB_F64:- FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));- break;-- 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_DIV_F64:- FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));- break;- }-- if (dst_r == TMP_FREG2)- FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));-- return SLJIT_SUCCESS;-}--/* --------------------------------------------------------------------- */-/* Other instructions */-/* --------------------------------------------------------------------- */--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);-- if (FAST_IS_REG(dst))- return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);-- /* Memory. */- FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw));- compiler->delay_slot = UNMOVABLE_INS;- return SLJIT_SUCCESS;-}--/* --------------------------------------------------------------------- */-/* Conditional instructions */-/* --------------------------------------------------------------------- */--SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)-{- struct sljit_label *label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_label(compiler));-- if (compiler->last_label && compiler->last_label->size == compiler->size)- return compiler->last_label;-- label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));- PTR_FAIL_IF(!label);- set_label(label, compiler);- compiler->delay_slot = UNMOVABLE_INS;- return label;-}--#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)-#define JUMP_LENGTH 4-#else-#define JUMP_LENGTH 8-#endif--#define BR_Z(src) \- inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \- flags = IS_BIT26_COND; \- delay_check = src;--#define BR_NZ(src) \- inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \- flags = IS_BIT26_COND; \- delay_check = src;--#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)--#define BR_T() \- inst = BC1NEZ; \- flags = IS_BIT23_COND; \- delay_check = FCSR_FCC;-#define BR_F() \- inst = BC1EQZ; \- flags = IS_BIT23_COND; \- delay_check = FCSR_FCC;--#else /* SLJIT_MIPS_REV < 6 */--#define BR_T() \- inst = BC1T | JUMP_LENGTH; \- flags = IS_BIT16_COND; \- delay_check = FCSR_FCC;-#define BR_F() \- inst = BC1F | JUMP_LENGTH; \- flags = IS_BIT16_COND; \- delay_check = FCSR_FCC;--#endif /* SLJIT_MIPS_REV >= 6 */--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_u32 flags = 0;- sljit_s32 delay_check = UNMOVABLE_INS;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_jump(compiler, type));-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);- type &= 0xff;-- switch (type) {- case SLJIT_EQUAL:- BR_NZ(EQUAL_FLAG);- break;- case SLJIT_NOT_EQUAL:- BR_Z(EQUAL_FLAG);- break;- case SLJIT_LESS:- case SLJIT_GREATER:- case SLJIT_SIG_LESS:- case SLJIT_SIG_GREATER:- case SLJIT_OVERFLOW:- case SLJIT_CARRY:- 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_NOT_CARRY:- BR_NZ(OTHER_FLAG);- break;- 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;- break;- }-- jump->flags |= flags;- if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))- jump->flags |= IS_MOVABLE;-- if (inst)- PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));-- PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));-- if (type <= SLJIT_JUMP)- PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));- else {- jump->flags |= IS_JAL;- PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));- }-- jump->addr = compiler->size;- PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));- return jump;-}--#define RESOLVE_IMM1() \- if (src1 & SLJIT_IMM) { \- if (src1w) { \- PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \- src1 = TMP_REG1; \- } \- else \- src1 = 0; \- }--#define RESOLVE_IMM2() \- if (src2 & SLJIT_IMM) { \- if (src2w) { \- PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \- src2 = TMP_REG2; \- } \- else \- src2 = 0; \- }--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_s32 flags;- sljit_ins inst;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- compiler->cache_arg = 0;- compiler->cache_argw = 0;- flags = ((type & SLJIT_32) ? 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;- }- if (src2 & SLJIT_MEM) {- PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0));- src2 = TMP_REG2;- }-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);- type &= 0xff;-- if (type <= SLJIT_NOT_EQUAL) {- RESOLVE_IMM1();- RESOLVE_IMM2();- jump->flags |= IS_BIT26_COND;- if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))- jump->flags |= IS_MOVABLE;- PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | JUMP_LENGTH, UNMOVABLE_INS));- }- else if (type >= SLJIT_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) {- inst = NOP;- if ((src1 & SLJIT_IMM) && (src1w == 0)) {- RESOLVE_IMM2();- switch (type) {- case SLJIT_SIG_LESS:- inst = BLEZ;- jump->flags |= IS_BIT26_COND;- break;- case SLJIT_SIG_GREATER_EQUAL:- inst = BGTZ;- jump->flags |= IS_BIT26_COND;- break;- case SLJIT_SIG_GREATER:- inst = BGEZ;- jump->flags |= IS_BIT16_COND;- break;- case SLJIT_SIG_LESS_EQUAL:- inst = BLTZ;- jump->flags |= IS_BIT16_COND;- break;- }- src1 = src2;- }- else {- RESOLVE_IMM1();- switch (type) {- case SLJIT_SIG_LESS:- inst = BGEZ;- jump->flags |= IS_BIT16_COND;- break;- case SLJIT_SIG_GREATER_EQUAL:- inst = BLTZ;- jump->flags |= IS_BIT16_COND;- break;- case SLJIT_SIG_GREATER:- inst = BLEZ;- jump->flags |= IS_BIT26_COND;- break;- case SLJIT_SIG_LESS_EQUAL:- inst = BGTZ;- jump->flags |= IS_BIT26_COND;- break;- }- }- PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | JUMP_LENGTH, UNMOVABLE_INS));- }- else {- if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {- RESOLVE_IMM1();- if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN)- PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));- else {- RESOLVE_IMM2();- PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));- }- type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;- }- else {- RESOLVE_IMM2();- if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN)- PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));- else {- RESOLVE_IMM1();- PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));- }- type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;- }-- jump->flags |= IS_BIT26_COND;- PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | 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 RESOLVE_IMM1-#undef RESOLVE_IMM2--#undef JUMP_LENGTH-#undef BR_Z-#undef BR_NZ-#undef BR_T-#undef BR_F--#undef FLOAT_DATA-#undef FMT--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;-- CHECK_ERROR();- CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- if (src & SLJIT_IMM) {- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- FAIL_IF(!jump);- set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));- jump->u.target = (sljit_uw)srcw;-- if (compiler->delay_slot != UNMOVABLE_INS)- jump->flags |= IS_MOVABLE;-- FAIL_IF(emit_const(compiler, TMP_REG2, 0));- src = TMP_REG2;- }- else if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw));- src = TMP_REG2;- }-- FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));- if (jump)- jump->addr = compiler->size;- FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));- return SLJIT_SUCCESS;-}--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_s32 src_ar, dst_ar;- sljit_s32 saved_op = op;-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- sljit_s32 mem_type = WORD_DATA;-#else- sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));- ADJUST_LOCAL_OFFSET(dst, dstw);-- op = GET_OPCODE(op);- 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 && (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(dst_ar) | IMM(1), dst_ar));- src_ar = dst_ar;- break;- case SLJIT_OVERFLOW:- case SLJIT_NOT_OVERFLOW:- if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {- src_ar = OTHER_FLAG;- break;- }- 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_GREATER_F64:- case SLJIT_LESS_EQUAL_F64:- type ^= 0x1; /* Flip type bit for the XORI below. */- /* fallthrough */- 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:-#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)- FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));-#else /* SLJIT_MIPS_REV < 6 */- FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));-#endif /* SLJIT_MIPS_REV >= 6 */- 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:- src_ar = OTHER_FLAG;- break;- }-- if (type & 0x1) {- 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 (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(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);-}--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_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)- sljit_ins ins;-#endif /* SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6 */-- CHECK_ERROR();- CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));--#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)-- if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {-#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)- if (dst_reg & SLJIT_32)- srcw = (sljit_s32)srcw;-#endif- FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));- src = TMP_REG1;- srcw = 0;- }-- dst_reg &= ~SLJIT_32;-- 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:- 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:- 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 /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */- return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);-#endif /* SLJIT_MIPS_REV >= 1 */-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)-{- struct sljit_const *const_;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));- ADJUST_LOCAL_OFFSET(dst, dstw);-- const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));- PTR_FAIL_IF(!const_);- set_const(const_, compiler);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;- PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));-- return const_;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- struct sljit_put_label *put_label;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);-- put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));- PTR_FAIL_IF(!put_label);- set_put_label(put_label, compiler, 0);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)- PTR_FAIL_IF(emit_const(compiler, dst_r, 0));-#else- PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));- compiler->size += 5;-#endif-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));-- return put_label;+#ifdef HAVE_PRCTL+#include <sys/prctl.h>+#endif++#if !defined(__mips_hard_float) || defined(__mips_single_float)+/* Disable automatic detection, covers both -msoft-float and -mno-float */+#define SLJIT_IS_FPU_AVAILABLE 0+#endif++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return "MIPS32-R6" SLJIT_CPUINFO;+#else /* !SLJIT_CONFIG_MIPS_32 */+ return "MIPS64-R6" SLJIT_CPUINFO;+#endif /* SLJIT_CONFIG_MIPS_32 */++#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 5)++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return "MIPS32-R5" SLJIT_CPUINFO;+#else /* !SLJIT_CONFIG_MIPS_32 */+ return "MIPS64-R5" SLJIT_CPUINFO;+#endif /* SLJIT_CONFIG_MIPS_32 */++#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return "MIPS32-R2" SLJIT_CPUINFO;+#else /* !SLJIT_CONFIG_MIPS_32 */+ return "MIPS64-R2" SLJIT_CPUINFO;+#endif /* SLJIT_CONFIG_MIPS_32 */++#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return "MIPS32-R1" SLJIT_CPUINFO;+#else /* !SLJIT_CONFIG_MIPS_32 */+ return "MIPS64-R1" SLJIT_CPUINFO;+#endif /* SLJIT_CONFIG_MIPS_32 */++#else /* SLJIT_MIPS_REV < 1 */+ return "MIPS III" SLJIT_CPUINFO;+#endif /* SLJIT_MIPS_REV >= 6 */+}++/* Length of an instruction word+ Both for mips-32 and mips-64 */+typedef sljit_u32 sljit_ins;++#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)++/* For position independent code, t9 must contain the function address. */+#define PIC_ADDR_REG TMP_REG1++/* Floating point status register. */+#define FCSR_REG 31+/* Return address register. */+#define RETURN_ADDR_REG 31++/* Flags are kept in volatile registers. */+#define EQUAL_FLAG 3+#define OTHER_FLAG 1++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {+ 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 25, 4, 31, 3, 1+};++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)+#define TMP_FREG3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3)++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)++static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3) << 1) + 1] = {+ 0,+ 0, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20,+ 12, 10, 16,+ 1, 15, 3, 5, 7, 9, 19, 31, 29, 27, 25, 23, 21,+ 13, 11, 17+};++#else /* !SLJIT_CONFIG_MIPS_32 */++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {+ 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 31, 30, 29, 28, 27, 26, 25, 24, 12, 11, 10+};++#endif /* SLJIT_CONFIG_MIPS_32 */++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++#define S(s) ((sljit_ins)reg_map[s] << 21)+#define T(t) ((sljit_ins)reg_map[t] << 16)+#define D(d) ((sljit_ins)reg_map[d] << 11)+#define FT(t) ((sljit_ins)freg_map[t] << 16)+#define FS(s) ((sljit_ins)freg_map[s] << 11)+#define FD(d) ((sljit_ins)freg_map[d] << 6)+/* Absolute registers. */+#define SA(s) ((sljit_ins)(s) << 21)+#define TA(t) ((sljit_ins)(t) << 16)+#define DA(d) ((sljit_ins)(d) << 11)+#define IMM(imm) ((sljit_ins)(imm) & 0xffff)+#define SH_IMM(imm) ((sljit_ins)(imm) << 6)++#define DR(dr) (reg_map[dr])+#define FR(dr) (freg_map[dr])+#define HI(opcode) ((sljit_ins)(opcode) << 26)+#define LO(opcode) ((sljit_ins)(opcode))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+/* CMP.cond.fmt */+/* S = (20 << 21) D = (21 << 21) */+#define CMP_FMT_S (20 << 21)+#endif /* SLJIT_MIPS_REV >= 6 */+/* S = (16 << 21) D = (17 << 21) */+#define FMT_S (16 << 21)+#define FMT_D (17 << 21)++#define ABS_S (HI(17) | FMT_S | LO(5))+#define ADD_S (HI(17) | FMT_S | LO(0))+#define ADDIU (HI(9))+#define ADDU (HI(0) | LO(33))+#define AND (HI(0) | LO(36))+#define ANDI (HI(12))+#define B (HI(4))+#define BAL (HI(1) | (17 << 16))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3))+#define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3))+#else /* SLJIT_MIPS_REV < 6 */+#define BC1F (HI(17) | (8 << 21))+#define BC1T (HI(17) | (8 << 21) | (1 << 16))+#endif /* SLJIT_MIPS_REV >= 6 */+#define BEQ (HI(4))+#define BGEZ (HI(1) | (1 << 16))+#define BGTZ (HI(7))+#define BLEZ (HI(6))+#define BLTZ (HI(1) | (0 << 16))+#define BNE (HI(5))+#define BREAK (HI(0) | LO(13))+#define CFC1 (HI(17) | (2 << 21))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define C_EQ_S (HI(17) | CMP_FMT_S | LO(2))+#define C_OLE_S (HI(17) | CMP_FMT_S | LO(6))+#define C_OLT_S (HI(17) | CMP_FMT_S | LO(4))+#define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))+#define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))+#define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))+#define C_UN_S (HI(17) | CMP_FMT_S | LO(1))+#define C_FD (FD(TMP_FREG3))+#else /* SLJIT_MIPS_REV < 6 */+#define C_EQ_S (HI(17) | FMT_S | LO(50))+#define C_OLE_S (HI(17) | FMT_S | LO(54))+#define C_OLT_S (HI(17) | FMT_S | LO(52))+#define C_UEQ_S (HI(17) | FMT_S | LO(51))+#define C_ULE_S (HI(17) | FMT_S | LO(55))+#define C_ULT_S (HI(17) | FMT_S | LO(53))+#define C_UN_S (HI(17) | FMT_S | LO(49))+#define C_FD (0)+#endif /* SLJIT_MIPS_REV >= 6 */+#define CVT_S_S (HI(17) | FMT_S | LO(32))+#define DADDIU (HI(25))+#define DADDU (HI(0) | LO(45))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define DDIV (HI(0) | (2 << 6) | LO(30))+#define DDIVU (HI(0) | (2 << 6) | LO(31))+#define DMOD (HI(0) | (3 << 6) | LO(30))+#define DMODU (HI(0) | (3 << 6) | LO(31))+#define DIV (HI(0) | (2 << 6) | LO(26))+#define DIVU (HI(0) | (2 << 6) | LO(27))+#define DMUH (HI(0) | (3 << 6) | LO(28))+#define DMUHU (HI(0) | (3 << 6) | LO(29))+#define DMUL (HI(0) | (2 << 6) | LO(28))+#define DMULU (HI(0) | (2 << 6) | LO(29))+#else /* SLJIT_MIPS_REV < 6 */+#define DDIV (HI(0) | LO(30))+#define DDIVU (HI(0) | LO(31))+#define DIV (HI(0) | LO(26))+#define DIVU (HI(0) | LO(27))+#define DMULT (HI(0) | LO(28))+#define DMULTU (HI(0) | LO(29))+#endif /* SLJIT_MIPS_REV >= 6 */+#define DIV_S (HI(17) | FMT_S | LO(3))+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+#define DINSU (HI(31) | LO(6))+#endif /* SLJIT_MIPS_REV >= 2 */+#define DMFC1 (HI(17) | (1 << 21))+#define DMTC1 (HI(17) | (5 << 21))+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+#define DROTR (HI(0) | (1 << 21) | LO(58))+#define DROTR32 (HI(0) | (1 << 21) | LO(62))+#define DROTRV (HI(0) | (1 << 6) | LO(22))+#define DSBH (HI(31) | (2 << 6) | LO(36))+#define DSHD (HI(31) | (5 << 6) | LO(36))+#endif /* SLJIT_MIPS_REV >= 2 */+#define DSLL (HI(0) | LO(56))+#define DSLL32 (HI(0) | LO(60))+#define DSLLV (HI(0) | LO(20))+#define DSRA (HI(0) | LO(59))+#define DSRA32 (HI(0) | LO(63))+#define DSRAV (HI(0) | LO(23))+#define DSRL (HI(0) | LO(58))+#define DSRL32 (HI(0) | LO(62))+#define DSRLV (HI(0) | LO(22))+#define DSUBU (HI(0) | LO(47))+#define J (HI(2))+#define JAL (HI(3))+#define JALR (HI(0) | LO(9))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define JR (HI(0) | LO(9))+#else /* SLJIT_MIPS_REV < 6 */+#define JR (HI(0) | LO(8))+#endif /* SLJIT_MIPS_REV >= 6 */+#define LD (HI(55))+#define LDL (HI(26))+#define LDR (HI(27))+#define LDC1 (HI(53))+#define LUI (HI(15))+#define LW (HI(35))+#define LWL (HI(34))+#define LWR (HI(38))+#define LWC1 (HI(49))+#define MFC1 (HI(17))+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+#define MFHC1 (HI(17) | (3 << 21))+#endif /* SLJIT_MIPS_REV >= 2 */+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define MOD (HI(0) | (3 << 6) | LO(26))+#define MODU (HI(0) | (3 << 6) | LO(27))+#else /* SLJIT_MIPS_REV < 6 */+#define MFHI (HI(0) | LO(16))+#define MFLO (HI(0) | LO(18))+#endif /* SLJIT_MIPS_REV >= 6 */+#define MTC1 (HI(17) | (4 << 21))+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+#define MTHC1 (HI(17) | (7 << 21))+#endif /* SLJIT_MIPS_REV >= 2 */+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define MUH (HI(0) | (3 << 6) | LO(24))+#define MUHU (HI(0) | (3 << 6) | LO(25))+#define MUL (HI(0) | (2 << 6) | LO(24))+#define MULU (HI(0) | (2 << 6) | LO(25))+#else /* SLJIT_MIPS_REV < 6 */+#define MULT (HI(0) | LO(24))+#define MULTU (HI(0) | LO(25))+#endif /* SLJIT_MIPS_REV >= 6 */+#define MUL_S (HI(17) | FMT_S | LO(2))+#define NEG_S (HI(17) | FMT_S | LO(7))+#define NOP (HI(0) | LO(0))+#define NOR (HI(0) | LO(39))+#define OR (HI(0) | LO(37))+#define ORI (HI(13))+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+#define ROTR (HI(0) | (1 << 21) | LO(2))+#define ROTRV (HI(0) | (1 << 6) | LO(6))+#endif /* SLJIT_MIPS_REV >= 2 */+#define SD (HI(63))+#define SDL (HI(44))+#define SDR (HI(45))+#define SDC1 (HI(61))+#define SLT (HI(0) | LO(42))+#define SLTI (HI(10))+#define SLTIU (HI(11))+#define SLTU (HI(0) | LO(43))+#define SLL (HI(0) | LO(0))+#define SLLV (HI(0) | LO(4))+#define SRL (HI(0) | LO(2))+#define SRLV (HI(0) | LO(6))+#define SRA (HI(0) | LO(3))+#define SRAV (HI(0) | LO(7))+#define SUB_S (HI(17) | FMT_S | LO(1))+#define SUBU (HI(0) | LO(35))+#define SW (HI(43))+#define SWL (HI(42))+#define SWR (HI(46))+#define SWC1 (HI(57))+#define TRUNC_W_S (HI(17) | FMT_S | LO(13))+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+#define WSBH (HI(31) | (2 << 6) | LO(32))+#endif /* SLJIT_MIPS_REV >= 2 */+#define XOR (HI(0) | LO(38))+#define XORI (HI(14))++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+#define CLZ (HI(28) | LO(32))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define DCLZ (LO(18))+#else /* SLJIT_MIPS_REV < 6 */+#define DCLZ (HI(28) | LO(36))+#define MOVF (HI(0) | (0 << 16) | LO(1))+#define MOVF_S (HI(17) | FMT_S | (0 << 16) | LO(17))+#define MOVN (HI(0) | LO(11))+#define MOVN_S (HI(17) | FMT_S | LO(19))+#define MOVT (HI(0) | (1 << 16) | LO(1))+#define MOVT_S (HI(17) | FMT_S | (1 << 16) | LO(17))+#define MOVZ (HI(0) | LO(10))+#define MOVZ_S (HI(17) | FMT_S | LO(18))+#define MUL (HI(28) | LO(2))+#endif /* SLJIT_MIPS_REV >= 6 */+#define PREF (HI(51))+#define PREFX (HI(19) | LO(15))+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+#define SEB (HI(31) | (16 << 6) | LO(32))+#define SEH (HI(31) | (24 << 6) | LO(32))+#endif /* SLJIT_MIPS_REV >= 2 */+#endif /* SLJIT_MIPS_REV >= 1 */++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define ADDU_W ADDU+#define ADDIU_W ADDIU+#define SLL_W SLL+#define SRA_W SRA+#define SUBU_W SUBU+#define STORE_W SW+#define LOAD_W LW+#else+#define ADDU_W DADDU+#define ADDIU_W DADDIU+#define SLL_W DSLL+#define SRA_W DSRA+#define SUBU_W DSUBU+#define STORE_W SD+#define LOAD_W LD+#endif++#define MOV_fmt(f) (HI(17) | f | LO(6))++#define SIMM_MAX (0x7fff)+#define SIMM_MIN (-0x8000)+#define UIMM_MAX (0xffff)++#define CPU_FEATURE_DETECTED (1 << 0)+#define CPU_FEATURE_FPU (1 << 1)+#define CPU_FEATURE_FP64 (1 << 2)+#define CPU_FEATURE_FR (1 << 3)++static sljit_u32 cpu_feature_list = 0;++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \+ && (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)++static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)+{+ if (compiler->scratches == -1)+ return 0;++ if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))+ fr -= SLJIT_F64_SECOND(0);++ return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches))+ || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0)+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));+}++#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_ARGUMENT_CHECKS */++static void get_cpu_features(void)+{+#if !defined(SLJIT_IS_FPU_AVAILABLE) && defined(__GNUC__)+ sljit_u32 fir = 0;+#endif /* !SLJIT_IS_FPU_AVAILABLE && __GNUC__ */+ sljit_u32 feature_list = CPU_FEATURE_DETECTED;++#if defined(SLJIT_IS_FPU_AVAILABLE)+#if SLJIT_IS_FPU_AVAILABLE+ feature_list |= CPU_FEATURE_FPU;+#if SLJIT_IS_FPU_AVAILABLE == 64+ feature_list |= CPU_FEATURE_FP64;+#endif /* SLJIT_IS_FPU_AVAILABLE == 64 */+#endif /* SLJIT_IS_FPU_AVAILABLE */+#elif defined(__GNUC__)+ __asm__ ("cfc1 %0, $0" : "=r"(fir));+ if ((fir & (0x3 << 16)) == (0x3 << 16))+ feature_list |= CPU_FEATURE_FPU;++#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64) \+ && (!defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV < 2)+ if ((feature_list & CPU_FEATURE_FPU))+ feature_list |= CPU_FEATURE_FP64;+#else /* SLJIT_CONFIG_MIPS32 || SLJIT_MIPS_REV >= 2 */+ if ((fir & (1 << 22)))+ feature_list |= CPU_FEATURE_FP64;+#endif /* SLJIT_CONFIG_MIPS_64 && SLJIT_MIPS_REV < 2 */+#endif /* SLJIT_IS_FPU_AVAILABLE */++ if ((feature_list & CPU_FEATURE_FPU) && (feature_list & CPU_FEATURE_FP64)) {+#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 6+ feature_list |= CPU_FEATURE_FR;+#elif defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 0+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 5+ feature_list |= CPU_FEATURE_FR;+#endif /* SLJIT_MIPS_REV >= 5 */+#else+ sljit_s32 flag = -1;+#ifndef FR_GET_FP_MODE+ sljit_f64 zero = 0.0;+#else /* PR_GET_FP_MODE */+ flag = prctl(PR_GET_FP_MODE);++ if (flag > 0)+ feature_list |= CPU_FEATURE_FR;+#endif /* FP_GET_PR_MODE */+#if ((defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 2) \+ || (!defined(PR_GET_FP_MODE) && (!defined(SLJIT_DETECT_FR) || SLJIT_DETECT_FR >= 1))) \+ && (defined(__GNUC__) && (defined(__mips) && __mips >= 2))+ if (flag < 0) {+ __asm__ (".set oddspreg\n"+ "lwc1 $f17, %0\n"+ "ldc1 $f16, %1\n"+ "swc1 $f17, %0\n"+ : "+m" (flag) : "m" (zero) : "$f16", "$f17");+ if (flag)+ feature_list |= CPU_FEATURE_FR;+ }+#endif /* (!PR_GET_FP_MODE || (PR_GET_FP_MODE && SLJIT_DETECT_FR == 2)) && __GNUC__ */+#endif /* SLJIT_MIPS_REV >= 6 */+#else /* !SLJIT_CONFIG_MIPS_32 */+ /* StatusFR=1 is the only mode supported by the code in MIPS64 */+ feature_list |= CPU_FEATURE_FR;+#endif /* SLJIT_CONFIG_MIPS_32 */+ }++ cpu_feature_list = feature_list;+}++/* dest_reg is the absolute name of the register+ Useful for reordering instructions in the delay slot. */+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)+{+ sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS+ || (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)+ || (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));+ FAIL_IF(!ptr);+ *ptr = ins;+ compiler->size++;+ compiler->delay_slot = delay_slot;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)+{+ if (flags & IS_BIT26_COND)+ return (1 << 26);+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ if (flags & IS_BIT23_COND)+ return (1 << 23);+#endif /* SLJIT_MIPS_REV >= 6 */+ return (1 << 16);+}++static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_sw diff;+ sljit_uw target_addr;+ sljit_ins *inst;+ sljit_ins saved_inst;++ inst = (sljit_ins *)jump->addr;++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))+ goto exit;+#else+ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ goto exit;+#endif++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->u.label != NULL);+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;+ }++ if (jump->flags & IS_COND)+ inst--;++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (jump->flags & IS_CALL)+ goto preserve_addr;+#endif++ /* B instructions. */+ if (jump->flags & IS_MOVABLE) {+ diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;+ if (diff <= SIMM_MAX && diff >= SIMM_MIN) {+ jump->flags |= PATCH_B;++ if (!(jump->flags & IS_COND)) {+ inst[0] = inst[-1];+ inst[-1] = (jump->flags & IS_JAL) ? BAL : B;+ jump->addr -= sizeof(sljit_ins);+ return inst;+ }+ saved_inst = inst[0];+ inst[0] = inst[-1];+ inst[-1] = saved_inst ^ invert_branch(jump->flags);+ jump->addr -= 2 * sizeof(sljit_ins);+ return inst;+ }+ } else {+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;+ if (diff <= SIMM_MAX && diff >= SIMM_MIN) {+ jump->flags |= PATCH_B;++ if (!(jump->flags & IS_COND)) {+ inst[0] = (jump->flags & IS_JAL) ? BAL : B;+ /* Keep inst[1] */+ return inst + 1;+ }+ inst[0] ^= invert_branch(jump->flags);+ inst[1] = NOP;+ jump->addr -= sizeof(sljit_ins);+ return inst + 1;+ }+ }++ if (jump->flags & IS_COND) {+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {+ jump->flags |= PATCH_J;+ saved_inst = inst[0];+ inst[0] = inst[-1];+ inst[-1] = (saved_inst & 0xffff0000) | 3;+ inst[1] = J;+ inst[2] = NOP;+ return inst + 2;+ }+ else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {+ jump->flags |= PATCH_J;+ inst[0] = (inst[0] & 0xffff0000) | 3;+ inst[1] = NOP;+ inst[2] = J;+ inst[3] = NOP;+ jump->addr += sizeof(sljit_ins);+ return inst + 3;+ }+ }+ else {+ /* J instuctions. */+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {+ jump->flags |= PATCH_J;+ inst[0] = inst[-1];+ inst[-1] = (jump->flags & IS_JAL) ? JAL : J;+ jump->addr -= sizeof(sljit_ins);+ return inst;+ }++ if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {+ jump->flags |= PATCH_J;+ inst[0] = (jump->flags & IS_JAL) ? JAL : J;+ /* Keep inst[1] */+ return inst + 1;+ }+ }++ if (jump->flags & IS_COND)+ inst++;++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+preserve_addr:+ if (target_addr <= 0x7fffffff) {+ jump->flags |= PATCH_ABS32;+ if (jump->flags & IS_COND)+ inst[-1] -= 4;++ inst[2] = inst[0];+ inst[3] = inst[1];+ return inst + 3;+ }+ if (target_addr <= 0x7fffffffffffl) {+ jump->flags |= PATCH_ABS48;+ if (jump->flags & IS_COND)+ inst[-1] -= 2;++ inst[4] = inst[0];+ inst[5] = inst[1];+ return inst + 5;+ }+#endif++exit:+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ inst[2] = inst[0];+ inst[3] = inst[1];+ return inst + 3;+#else+ inst[6] = inst[0];+ inst[7] = inst[1];+ return inst + 7;+#endif+}++#ifdef __GNUC__+static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)+{+ SLJIT_CACHE_FLUSH(code, code_ptr);+}+#endif++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)++static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_uw addr;+ SLJIT_UNUSED_ARG(executable_offset);++ if (jump->flags & JUMP_ADDR)+ addr = jump->u.target;+ else+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ if (addr < 0x80000000l) {+ jump->flags |= PATCH_ABS32;+ return 1;+ }++ if (addr < 0x800000000000l) {+ jump->flags |= PATCH_ABS48;+ return 3;+ }++ return 5;+}++#endif /* SLJIT_CONFIG_MIPS_64 */++static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump)+{+ sljit_uw flags = jump->flags;+ sljit_ins *ins = (sljit_ins*)jump->addr;+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;+ sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : PIC_ADDR_REG;++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ ins[0] = LUI | T(reg) | IMM(addr >> 16);+#else /* !SLJIT_CONFIG_MIPS_32 */+ if (flags & PATCH_ABS32) {+ SLJIT_ASSERT(addr < 0x80000000l);+ ins[0] = LUI | T(reg) | IMM(addr >> 16);+ }+ else if (flags & PATCH_ABS48) {+ SLJIT_ASSERT(addr < 0x800000000000l);+ ins[0] = LUI | T(reg) | IMM(addr >> 32);+ ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);+ ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);+ ins += 2;+ }+ else {+ ins[0] = LUI | T(reg) | IMM(addr >> 48);+ ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);+ ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);+ ins[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);+ ins[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);+ ins += 4;+ }+#endif /* SLJIT_CONFIG_MIPS_32 */++ ins[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_sw executable_offset;+ sljit_uw addr;+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);+ PTR_FAIL_WITH_EXEC_IF(code);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();+ SLJIT_GET_NEXT_MIN();++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ *code_ptr = *buf_ptr++;+ if (next_min_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);++ /* These structures are ordered by their address. */+ if (next_min_addr == next_label_size) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_jump_addr) {+ if (!(jump->flags & JUMP_MOV_ADDR)) {+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ word_count += 2;+#else /* !SLJIT_CONFIG_MIPS_32 */+ word_count += 6;+#endif /* SLJIT_CONFIG_MIPS_32 */+ jump->addr = (sljit_uw)(code_ptr - 1);+ code_ptr = detect_jump_type(jump, code, executable_offset);+ } else {+ jump->addr = (sljit_uw)code_ptr;+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ code_ptr += 1;+ word_count += 1;+#else /* !SLJIT_CONFIG_MIPS_32 */+ code_ptr += mov_addr_get_length(jump, code, executable_offset);+ word_count += 5;+#endif /* SLJIT_CONFIG_MIPS_32 */+ }++ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ } else if (next_min_addr == next_const_addr) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ }++ SLJIT_GET_NEXT_MIN();+ }+ code_ptr++;+ word_count++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->u.addr = (sljit_uw)code_ptr;+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ do {+ addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;+ buf_ptr = (sljit_ins *)jump->addr;++ if (jump->flags & PATCH_B) {+ addr = (sljit_uw)((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) | ((sljit_ins)addr & 0xffff);+ break;+ }+ if (jump->flags & PATCH_J) {+ SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)+ == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));+ buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;+ break;+ }++ load_addr_to_reg(jump);+ } while (0);++ jump = jump->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (sljit_uw)(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+ /* GCC workaround for invalid code generation with -O2. */+ sljit_cache_flush(code, code_ptr);+#endif+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ return code;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ switch (feature_type) {+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \+ && (!defined(SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE)+ case SLJIT_HAS_F64_AS_F32_PAIR:+ if (!cpu_feature_list)+ get_cpu_features();++ return (cpu_feature_list & CPU_FEATURE_FR) != 0;+#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_IS_FPU_AVAILABLE */+ case SLJIT_HAS_FPU:+ if (!cpu_feature_list)+ get_cpu_features();++ return (cpu_feature_list & CPU_FEATURE_FPU) != 0;+ case SLJIT_HAS_ZERO_REGISTER:+ case SLJIT_HAS_COPY_F32:+ case SLJIT_HAS_COPY_F64:+ return 1;+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CMOV:+ case SLJIT_HAS_PREFETCH:+ return 1;++ case SLJIT_HAS_CTZ:+ return 2;+#endif /* SLJIT_MIPS_REV >= 1 */+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)+ case SLJIT_HAS_REV:+ case SLJIT_HAS_ROT:+ return 1;+#endif /* SLJIT_MIPS_REV >= 2 */+ default:+ return 0;+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)+{+ SLJIT_UNUSED_ARG(type);+ return 0;+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++/* Creates an index in data_transfer_insts array. */+#define LOAD_DATA 0x01+#define WORD_DATA 0x00+#define BYTE_DATA 0x02+#define HALF_DATA 0x04+#define INT_DATA 0x06+#define SIGNED_DATA 0x08+/* Separates integer and floating point registers */+#define GPR_REG 0x0f+#define DOUBLE_DATA 0x10+#define SINGLE_DATA 0x12++#define MEM_MASK 0x1f++#define ARG_TEST 0x00020+#define ALT_KEEP_CACHE 0x00040+#define CUMULATIVE_OP 0x00080+#define LOGICAL_OP 0x00100+#define IMM_OP 0x00200+#define MOVE_OP 0x00400+#define SRC2_IMM 0x00800++#define UNUSED_DEST 0x01000+#define REG_DEST 0x02000+#define REG1_SOURCE 0x04000+#define REG2_SOURCE 0x08000+#define SLOW_SRC1 0x10000+#define SLOW_SRC2 0x20000+#define SLOW_DEST 0x40000++static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define SELECT_OP(d, w) (w)+#else+#define SELECT_OP(d, w) (!(op & SLJIT_32) ? (d) : (w))+#endif++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#include "sljitNativeMIPS_32.c"+#else+#include "sljitNativeMIPS_64.c"+#endif++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_ins base;+ sljit_s32 i, tmp, offset;+ sljit_s32 arg_count, word_arg_count, float_arg_count;+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ if ((local_size & SSIZE_OF(sw)) != 0)+ local_size += SSIZE_OF(sw);+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+ }++ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;+#else+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;+#endif+ compiler->local_size = local_size;++ offset = 0;+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (!(options & SLJIT_ENTER_REG_ARG)) {+ tmp = arg_types >> SLJIT_ARG_SHIFT;+ arg_count = 0;++ while (tmp) {+ offset = arg_count;+ if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {+ if ((arg_count & 0x1) != 0)+ arg_count++;+ arg_count++;+ }++ arg_count++;+ tmp >>= SLJIT_ARG_SHIFT;+ }++ compiler->args_size = (sljit_uw)arg_count << 2;+ offset = (offset >= 4) ? (offset << 2) : 0;+ }+#endif /* SLJIT_CONFIG_MIPS_32 */++ if (local_size + offset <= -SIMM_MIN) {+ /* Frequent case. */+ FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));+ base = S(SLJIT_SP);+ offset = local_size - SSIZE_OF(sw);+ } else {+ FAIL_IF(load_immediate(compiler, OTHER_FLAG, local_size));+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | TA(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));+ base = S(TMP_REG1);+ offset = -SSIZE_OF(sw);+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ local_size = 0;+#endif+ }++ FAIL_IF(push_inst(compiler, STORE_W | base | TA(RETURN_ADDR_REG) | IMM(offset), UNMOVABLE_INS));++ tmp = SLJIT_S0 - saveds;+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));+ }++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ /* This alignment is valid because offset is not used after storing FPU regs. */+ if ((offset & SSIZE_OF(sw)) != 0)+ offset -= SSIZE_OF(sw);+#endif++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));+ }++ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));+ }++ if (options & SLJIT_ENTER_REG_ARG)+ return SLJIT_SUCCESS;++ arg_types >>= SLJIT_ARG_SHIFT;+ arg_count = 0;+ word_arg_count = 0;+ float_arg_count = 0;++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ /* The first maximum two floating point arguments are passed in floating point+ registers if no integer argument precedes them. The first 16 byte data is+ passed in four integer registers, the rest is placed onto the stack.+ The floating point registers are also part of the first 16 byte data, so+ their corresponding integer registers are not used when they are present. */++ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ float_arg_count++;+ if ((arg_count & 0x1) != 0)+ arg_count++;++ if (word_arg_count == 0 && float_arg_count <= 2) {+ if (float_arg_count == 1)+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));+ } else if (arg_count < 4) {+ FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));+ switch (cpu_feature_list & CPU_FEATURE_FR) {+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+ case CPU_FEATURE_FR:+ FAIL_IF(push_inst(compiler, MTHC1 | TA(5 + arg_count) | FS(float_arg_count), MOVABLE_INS));+ break;+#endif /* SLJIT_MIPS_REV >= 2 */+ default:+ FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));+ break;+ }+ } else+ FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));+ arg_count++;+ break;+ case SLJIT_ARG_TYPE_F32:+ float_arg_count++;++ if (word_arg_count == 0 && float_arg_count <= 2) {+ if (float_arg_count == 1)+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));+ } else if (arg_count < 4)+ FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));+ break;+ default:+ word_arg_count++;++ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ tmp = SLJIT_S0 - saved_arg_count;+ saved_arg_count++;+ } else if (word_arg_count != arg_count + 1 || arg_count == 0)+ tmp = word_arg_count;+ else+ break;++ if (arg_count < 4)+ FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));+ else+ FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));+ break;+ }+ arg_count++;+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);+#else /* !SLJIT_CONFIG_MIPS_32 */+ while (arg_types) {+ arg_count++;+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ float_arg_count++;+ if (arg_count != float_arg_count)+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));+ else if (arg_count == 1)+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));+ break;+ case SLJIT_ARG_TYPE_F32:+ float_arg_count++;+ if (arg_count != float_arg_count)+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));+ else if (arg_count == 1)+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));+ break;+ default:+ word_arg_count++;++ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ tmp = SLJIT_S0 - saved_arg_count;+ saved_arg_count++;+ } else if (word_arg_count != arg_count || word_arg_count <= 1)+ tmp = word_arg_count;+ else+ break;++ FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));+ break;+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }+#endif /* SLJIT_CONFIG_MIPS_32 */++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ if ((local_size & SSIZE_OF(sw)) != 0)+ local_size += SSIZE_OF(sw);+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+ }++ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;+#else+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;+#endif+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)+{+ sljit_s32 local_size, i, tmp, offset;+ sljit_s32 load_return_addr = (frame_size == 0);+ sljit_s32 scratches = compiler->scratches;+ sljit_s32 saveds = compiler->saveds;+ sljit_s32 fsaveds = compiler->fsaveds;+ sljit_s32 fscratches = compiler->fscratches;+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);++ SLJIT_ASSERT(frame_size == 1 || (frame_size & 0xf) == 0);+ frame_size &= ~0xf;++ local_size = compiler->local_size;++ tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1);+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ if ((tmp & SSIZE_OF(sw)) != 0)+ tmp += SSIZE_OF(sw);+ tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+ }+#else+ tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+#endif++ if (local_size <= SIMM_MAX) {+ if (local_size < frame_size) {+ FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));+ local_size = frame_size;+ }+ } else {+ if (tmp < frame_size)+ tmp = frame_size;++ FAIL_IF(load_immediate(compiler, DR(TMP_REG2), local_size - tmp));+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG2) | D(SLJIT_SP), DR(SLJIT_SP)));+ local_size = tmp;+ }++ SLJIT_ASSERT(local_size >= frame_size);++ offset = local_size - SSIZE_OF(sw);+ if (load_return_addr)+ FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));++ tmp = SLJIT_S0 - saveds;+ for (i = SLJIT_S0 - kept_saveds_count; i > tmp; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));+ }++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ /* This alignment is valid because offset is not used after storing FPU regs. */+ if ((offset & SSIZE_OF(sw)) != 0)+ offset -= SSIZE_OF(sw);+#endif++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));+ }++ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));+ }++ if (local_size > frame_size)+ *ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);+ else+ *ins_ptr = NOP;++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)+{+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ emit_stack_frame_release(compiler, 0, &ins);++ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));+ return push_inst(compiler, ins, UNMOVABLE_INS);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));+ src = PIC_ADDR_REG;+ srcw = 0;+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));+ src = PIC_ADDR_REG;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 1, &ins));++ if (src != SLJIT_IMM) {+ FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));+ return push_inst(compiler, ins, UNMOVABLE_INS);+ }++ if (ins != NOP)+ FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define ARCH_32_64(a, b) a+#else+#define ARCH_32_64(a, b) b+#endif++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 */,+/* u b l */ HI(36) /* lbu */,+/* u h s */ HI(41) /* sh */,+/* u h l */ HI(37) /* lhu */,+/* u i s */ HI(43) /* sw */,+/* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),++/* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),+/* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),+/* s b s */ HI(40) /* sb */,+/* s b l */ HI(32) /* lb */,+/* s h s */ HI(41) /* sh */,+/* s h l */ HI(33) /* lh */,+/* s i s */ HI(43) /* sw */,+/* s i l */ HI(35) /* lw */,++/* d s */ HI(61) /* sdc1 */,+/* d l */ HI(53) /* ldc1 */,+/* s s */ HI(57) /* swc1 */,+/* s l */ HI(49) /* lwc1 */,+};++#undef ARCH_32_64++/* reg_ar is an absoulute register! */++/* Can perform an operation using at most 1 instruction. */+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);++ if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {+ /* Works for both absoulte and relative addresses. */+ if (SLJIT_UNLIKELY(flags & ARG_TEST))+ return 1;+ FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)+ | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));+ return -1;+ }+ return 0;+}++#define TO_ARGW_HI(argw) (((argw) & ~0xffff) + (((argw) & 0x8000) ? 0x10000 : 0))++/* See getput_arg below.+ Note: can_cache is called only for binary operators. */+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));++ /* Simple operation except for updates. */+ if (arg & OFFS_REG_MASK) {+ argw &= 0x3;+ next_argw &= 0x3;+ if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))+ return 1;+ return 0;+ }++ if (arg == next_arg) {+ if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)+ || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))+ return 1;+ return 0;+ }++ return 0;+}++/* Emit the necessary instructions. See can_cache above. */+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_s32 tmp_ar, base, delay_slot;+ sljit_sw offset, argw_hi;++ SLJIT_ASSERT(arg & SLJIT_MEM);+ if (!(next_arg & SLJIT_MEM)) {+ next_arg = 0;+ next_argw = 0;+ }++ /* Since tmp can be the same as base or offset registers,+ * these might be unavailable after modifying tmp. */+ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {+ tmp_ar = reg_ar;+ delay_slot = reg_ar;+ }+ else {+ tmp_ar = DR(TMP_REG1);+ delay_slot = MOVABLE_INS;+ }+ base = arg & REG_MASK;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ /* Using the cache. */+ if (argw == compiler->cache_argw) {+ 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);+ }+ 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);+ }+ }++ if (SLJIT_UNLIKELY(argw)) {+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);+ compiler->cache_argw = argw;+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));+ }++ 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 (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(argw - compiler->cache_argw), delay_slot);++ if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {+ offset = argw - compiler->cache_argw;+ } else {+ compiler->cache_arg = SLJIT_MEM;++ argw_hi = TO_ARGW_HI(argw);++ if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {+ FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));+ compiler->cache_argw = argw;+ offset = 0;+ } else {+ FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw_hi));+ compiler->cache_argw = argw_hi;+ offset = argw & 0xffff;+ argw = argw_hi;+ }+ }++ if (!base)+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);++ if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {+ compiler->cache_arg = arg;+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);+ }++ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(offset), delay_slot);+}++static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)+{+ sljit_s32 tmp_ar, base, delay_slot;++ if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))+ return compiler->error;++ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {+ tmp_ar = reg_ar;+ delay_slot = reg_ar;+ }+ else {+ tmp_ar = DR(TMP_REG1);+ delay_slot = MOVABLE_INS;+ }+ base = arg & REG_MASK;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ if (SLJIT_UNLIKELY(argw)) {+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));+ FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));+ }+ else+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);+ }++ FAIL_IF(load_immediate(compiler, tmp_ar, TO_ARGW_HI(argw)));++ if (base != 0)+ FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));++ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);+}++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);+}++#define EMIT_LOGICAL(op_imm, op_reg) \+ if (flags & SRC2_IMM) { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \+ } \+ else { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | D(dst), DR(dst))); \+ }++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)++#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \+ op_imm = (imm); \+ op_v = (v);++#else /* !SLJIT_CONFIG_MIPS_32 */+++#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \+ op_dimm = (dimm); \+ op_dimm32 = (dimm32); \+ op_imm = (imm); \+ op_dv = (dv); \+ op_v = (v);++#endif /* SLJIT_CONFIG_MIPS_32 */++#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV < 1)++static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)+{+ sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;+#else /* !SLJIT_CONFIG_MIPS_64 */+ sljit_ins word_size = 32;+#endif /* SLJIT_CONFIG_MIPS_64 */++ /* The TMP_REG2 is the next value. */+ if (src != TMP_REG2)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));++ FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(is_clz ? 13 : 14), UNMOVABLE_INS));+ /* The OTHER_FLAG is the counter. Delay slot. */+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(word_size), OTHER_FLAG));++ if (!is_clz) {+ FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG2) | T(TMP_REG1) | IMM(1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, BNE | S(TMP_REG1) | TA(0) | IMM(11), UNMOVABLE_INS));+ } else+ FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG2) | TA(0) | IMM(11), UNMOVABLE_INS));++ /* Delay slot. */+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(0), OTHER_FLAG));++ /* The TMP_REG1 is the next shift. */+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(word_size), DR(TMP_REG1)));++ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(TMP_REG2) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));++ FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG1) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, BNE | S(TMP_REG2) | TA(0) | IMM(-4), UNMOVABLE_INS));+ /* Delay slot. */+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));++ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(TMP_REG1) | T(TMP_REG2) | IMM(-1), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG2) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));++ FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(-7), UNMOVABLE_INS));+ /* Delay slot. */+ FAIL_IF(push_inst(compiler, OR | SA(OTHER_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG));++ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | SA(OTHER_FLAG) | TA(0) | D(dst), DR(dst));+}++#endif /* SLJIT_MIPS_REV < 1 */++static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)+{+#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64+ int is_32 = (op & SLJIT_32);+#endif /* SLJIT_CONFIG_MIPS_64 */++ op = GET_OPCODE(op);+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64+ if (!is_32 && (op == SLJIT_REV)) {+ FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));+ return push_inst(compiler, DSHD | T(dst) | D(dst), DR(dst));+ }+ if (op != SLJIT_REV && src != TMP_REG2) {+ FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG1), DR(TMP_REG1)));+ src = TMP_REG1;+ }+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));+ FAIL_IF(push_inst(compiler, ROTR | T(dst) | D(dst) | SH_IMM(16), DR(dst)));+#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64+ if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3)+ FAIL_IF(push_inst(compiler, DINSU | T(dst) | SA(0) | (31 << 11), DR(dst)));+#endif /* SLJIT_CONFIG_MIPS_64 */+#else /* SLJIT_MIPS_REV < 2 */+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (!is_32) {+ FAIL_IF(push_inst(compiler, DSRL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, ORI | SA(0) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));+ FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(dst) | SH_IMM(0), DR(dst)));+ FAIL_IF(push_inst(compiler, DSLL32 | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(0), OTHER_FLAG));+ FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));++ FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));+ FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));+ FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, DSLL | TA(OTHER_FLAG) | DA(EQUAL_FLAG) | SH_IMM(8), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));+ FAIL_IF(push_inst(compiler, XOR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));++ FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));+ FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));+ return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));+ }++ if (op != SLJIT_REV && src != TMP_REG2) {+ FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(0), DR(TMP_REG2)));+ src = TMP_REG2;+ }+#endif /* SLJIT_CONFIG_MIPS_64 */++ FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, LUI | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));+ FAIL_IF(push_inst(compiler, SLL | T(src) | D(dst) | SH_IMM(16), DR(dst)));+ FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));+ FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));++ FAIL_IF(push_inst(compiler, SRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));+ FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, SLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));+ FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3) {+ FAIL_IF(push_inst(compiler, DSLL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));+ FAIL_IF(push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));+ }+#endif /* SLJIT_CONFIG_MIPS_64 */+#endif /* SLJIT_MIPR_REV >= 2 */+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)+{+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32+ FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));+#else /* !SLJIT_CONFIG_MIPS_32 */+ FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));+#endif /* SLJIT_CONFIG_MIPS_32 */+ if (GET_OPCODE(op) == SLJIT_REV_U16)+ return push_inst(compiler, ANDI | S(dst) | T(dst) | 0xffff, DR(dst));+ else+ return push_inst(compiler, SEH | T(dst) | D(dst), DR(dst));+#else /* SLJIT_MIPS_REV < 2 */+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(src) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(src) | D(dst) | SH_IMM(24), DR(dst)));+ FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG1) | T(TMP_REG1) | 0xff, DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SELECT_OP(DSRL32, SRL) : SELECT_OP(DSRA32, SRA)) | T(dst) | D(dst) | SH_IMM(16), DR(dst)));+ return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));+#endif /* SLJIT_MIPS_REV >= 2 */+}++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, carry_src_ar, is_handled, reg;+ sljit_ins op_imm, op_v;+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ sljit_ins ins, op_dimm, op_dimm32, op_dv;+#endif++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if (dst != src2)+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)+ return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));+#else /* SLJIT_MIPS_REV < 2 */+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));+ return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));+#endif /* SLJIT_MIPS_REV >= 2 */+#else /* !SLJIT_CONFIG_MIPS_32 */+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)+ if (op & SLJIT_32)+ return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));+#endif /* SLJIT_MIPS_REV >= 2 */+ 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));+#endif /* SLJIT_CONFIG_MIPS_32 */+ }+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)+ return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));+#else /* SLJIT_MIPS_REV < 2 */+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));+ return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));+#endif /* SLJIT_MIPS_REV >= 2 */+#else /* !SLJIT_CONFIG_MIPS_32 */+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)+ if (op & SLJIT_32)+ return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));+#endif /* SLJIT_MIPS_REV >= 2 */+ 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));+#endif /* SLJIT_CONFIG_MIPS_32 */+ }+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ case SLJIT_MOV_U32:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)+ if (dst == src2)+ return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11), DR(dst));+#endif /* SLJIT_MIPS_REV >= 2 */+ 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));+ }+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_S32:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));+ }+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;+#endif /* SLJIT_CONFIG_MIPS_64 */++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ case SLJIT_CLZ:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | D(dst), DR(dst));+#else /* SLJIT_MIPS_REV < 6 */+ return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst));+#endif /* SLJIT_MIPS_REV >= 6 */+ case SLJIT_CTZ:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, AND | S(src2) | T(TMP_REG1) | D(dst), DR(dst)));+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | D(dst), DR(dst)));+#else /* SLJIT_MIPS_REV < 6 */+ FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | T(dst) | D(dst), DR(dst)));+#endif /* SLJIT_MIPS_REV >= 6 */+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(TMP_REG1) | IMM(SELECT_OP(-64, -32)), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(SELECT_OP(26, 27)), DR(TMP_REG1)));+ return push_inst(compiler, XOR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));+#else /* SLJIT_MIPS_REV < 1 */+ case SLJIT_CLZ:+ case SLJIT_CTZ:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ return emit_clz_ctz(compiler, op, dst, src2);+#endif /* SLJIT_MIPS_REV >= 1 */++ case SLJIT_REV:+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && src2 != TMP_REG1 && dst != TMP_REG1);+ return emit_rev(compiler, op, dst, src2);++ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ return emit_rev16(compiler, op, dst, src2);++ case SLJIT_ADD:+ /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ 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(EQUAL_FLAG), EQUAL_FLAG));+ }+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));++ /* Only the zero flag is needed. */+ 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 (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 (is_overflow || carry_src_ar != 0) {+ if (src1 != dst)+ carry_src_ar = DR(src1);+ else if (src2 != dst)+ carry_src_ar = DR(src2);+ else {+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));+ carry_src_ar = OTHER_FLAG;+ }+ }++ /* Only the zero flag is needed. */+ 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)));+ }++ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */+ if (is_overflow || carry_src_ar != 0) {+ if (flags & SRC2_IMM)+ FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ else+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(OTHER_FLAG), OTHER_FLAG));+ }++ if (!is_overflow)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));+ return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);++ case SLJIT_ADDC:+ carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));+ } else {+ if (carry_src_ar != 0) {+ if (src1 != dst)+ carry_src_ar = DR(src1);+ else if (src2 != dst)+ carry_src_ar = DR(src2);+ else {+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));+ carry_src_ar = EQUAL_FLAG;+ }+ }++ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));+ }++ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */+ if (carry_src_ar != 0) {+ if (flags & SRC2_IMM)+ FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));+ else+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(EQUAL_FLAG), EQUAL_FLAG));+ }++ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));++ if (carry_src_ar == 0)+ return SLJIT_SUCCESS;++ /* 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(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);++ case SLJIT_SUB:+ 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) {+ 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) {+ 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) {+ reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(reg) | IMM(src2), DR(reg)));+ src2 = reg;+ flags &= ~SRC2_IMM;+ }++ switch (GET_FLAG_TYPE(op)) {+ case SLJIT_LESS:+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ break;+ case SLJIT_GREATER:+ FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));+ break;+ case SLJIT_SIG_LESS:+ FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ break;+ case SLJIT_SIG_GREATER:+ FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));+ break;+ }+ }++ 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) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ 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(EQUAL_FLAG), EQUAL_FLAG));+ }+ 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 (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));++ /* Only the zero flag is needed. */+ 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 (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 (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));++ /* Only the zero flag is needed. */+ 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 (!is_overflow)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));+ return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);++ case SLJIT_SUBC:+ 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_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));++ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));+ }+ else {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));++ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));+ }++ 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(OTHER_FLAG) | D(dst), DR(dst)));++ if (!is_carry)+ return SLJIT_SUCCESS;++ return push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG);++ case SLJIT_MUL:+ SLJIT_ASSERT(!(flags & SRC2_IMM));++ if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));+#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));+#else /* !SLJIT_CONFIG_MIPS_32 */+ if (op & SLJIT_32)+ 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));+#endif /* SLJIT_CONFIG_MIPS_32 */+#else /* SLJIT_MIPS_REV < 1 */+ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));+ return push_inst(compiler, MFLO | D(dst), DR(dst));+#endif /* SLJIT_MIPS_REV >= 6 */+ }++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));+ FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+#else /* SLJIT_MIPS_REV < 6 */+ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));+ FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));+#endif /* SLJIT_MIPS_REV >= 6 */+ 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);+ return SLJIT_SUCCESS;++ case SLJIT_OR:+ EMIT_LOGICAL(ORI, OR);+ return SLJIT_SUCCESS;++ case SLJIT_XOR:+ if (!(flags & LOGICAL_OP)) {+ SLJIT_ASSERT((flags & SRC2_IMM) && src2 == -1);+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));+ if (!(flags & UNUSED_DEST))+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | D(dst), DR(dst)));+ return SLJIT_SUCCESS;+ }+ EMIT_LOGICAL(XORI, XOR);+ return SLJIT_SUCCESS;++ case SLJIT_SHL:+ case SLJIT_MSHL:+ EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);+ break;++ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);+ break;++ case SLJIT_ASHR:+ case SLJIT_MASHR:+ EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);+ break;++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)+ case SLJIT_ROTL:+ if ((flags & SRC2_IMM) || src2 == 0) {+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ src2 = -src2 & 0x1f;+#else /* !SLJIT_CONFIG_MIPS_32 */+ src2 = -src2 & ((op & SLJIT_32) ? 0x1f : 0x3f);+#endif /* SLJIT_CONFIG_MIPS_32 */+ } else {+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2)));+ src2 = TMP_REG2;+ }+ /* fallthrough */++ case SLJIT_ROTR:+ EMIT_SHIFT(DROTR, DROTR32, ROTR, DROTRV, ROTRV);+ break;+#else /* SLJIT_MIPS_REV < 1 */+ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (flags & SRC2_IMM) {+ SLJIT_ASSERT(src2 != 0);+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (!(op & SLJIT_32)) {+ if (GET_OPCODE(op) == SLJIT_ROTL)+ op_imm = ((src2 < 32) ? DSLL : DSLL32);+ else+ op_imm = ((src2 < 32) ? DSRL : DSRL32);++ FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | (((sljit_ins)src2 & 0x1f) << 6), OTHER_FLAG));++ src2 = 64 - src2;+ if (GET_OPCODE(op) == SLJIT_ROTL)+ op_imm = ((src2 < 32) ? DSRL : DSRL32);+ else+ op_imm = ((src2 < 32) ? DSLL : DSLL32);++ FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));+ return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));+ }+#endif /* SLJIT_CONFIG_MIPS_64 */++ op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | ((sljit_ins)src2 << 6), OTHER_FLAG));++ src2 = 32 - src2;+ op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));+ return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));+ }++ if (src2 == 0) {+ if (dst != src1)+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | D(dst), DR(dst));+ return SLJIT_SUCCESS;+ }++ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (!(op & SLJIT_32)) {+ op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSLLV : DSRLV;+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));+ op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSRLV : DSLLV;+ FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));+ return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));+ }+#endif /* SLJIT_CONFIG_MIPS_64 */++ op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLV : SRLV;+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));+ op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLV : SLLV;+ FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));+ return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));+#endif /* SLJIT_MIPS_REV >= 2 */++ default:+ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+ }++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if ((flags & SRC2_IMM) || src2 == 0) {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));++ if (flags & UNUSED_DEST)+ return SLJIT_SUCCESS;+ return push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst));+ }++ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));++ if (flags & UNUSED_DEST)+ return SLJIT_SUCCESS;+ return push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst));+#else /* !SLJIT_CONFIG_MIPS_32 */+ if ((flags & SRC2_IMM) || src2 == 0) {+ if (src2 >= 32) {+ SLJIT_ASSERT(!(op & SLJIT_32));+ ins = op_dimm32;+ src2 -= 32;+ }+ else+ ins = (op & SLJIT_32) ? 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 (flags & UNUSED_DEST)+ return SLJIT_SUCCESS;+ return push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst));+ }++ ins = (op & SLJIT_32) ? 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 (flags & UNUSED_DEST)+ return SLJIT_SUCCESS;+ return push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst));+#endif /* SLJIT_CONFIG_MIPS_32 */+}++#define CHECK_IMM(flags, srcw) \+ ((!((flags) & LOGICAL_OP) && ((srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)) \+ || (((flags) & LOGICAL_OP) && !((srcw) & ~UIMM_MAX)))++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_s32 dst_r = TMP_REG2;+ sljit_s32 src1_r;+ sljit_sw src2_r = 0;+ sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;++ if (!(flags & ALT_KEEP_CACHE)) {+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ }++ if (dst == 0) {+ SLJIT_ASSERT(HAS_FLAGS(op));+ flags |= UNUSED_DEST;+ dst = TMP_REG2;+ }+ else if (FAST_IS_REG(dst)) {+ dst_r = dst;+ flags |= REG_DEST;+ if (flags & MOVE_OP)+ src2_tmp_reg = dst_r;+ }+ else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))+ flags |= SLOW_DEST;++ if (flags & IMM_OP) {+ if (src2 == SLJIT_IMM && src2w != 0 && CHECK_IMM(flags, src2w)) {+ flags |= SRC2_IMM;+ src2_r = src2w;+ } else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && CHECK_IMM(flags, src1w)) {+ flags |= SRC2_IMM;+ src2_r = src1w;++ /* And swap arguments. */+ src1 = src2;+ src1w = src2w;+ src2 = SLJIT_IMM;+ /* src2w = src2_r unneeded. */+ }+ }++ /* Source 1. */+ if (FAST_IS_REG(src1)) {+ src1_r = src1;+ flags |= REG1_SOURCE;+ }+ else if (src1 == SLJIT_IMM) {+ if (src1w) {+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));+ src1_r = TMP_REG1;+ }+ else+ src1_r = 0;+ }+ else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC1;+ src1_r = TMP_REG1;+ }++ /* Source 2. */+ if (FAST_IS_REG(src2)) {+ src2_r = src2;+ flags |= REG2_SOURCE;+ if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)+ dst_r = (sljit_s32)src2_r;+ }+ else if (src2 == SLJIT_IMM) {+ if (!(flags & SRC2_IMM)) {+ if (src2w) {+ FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w));+ src2_r = src2_tmp_reg;+ }+ else {+ src2_r = 0;+ if (flags & MOVE_OP) {+ if (dst & SLJIT_MEM)+ dst_r = 0;+ else+ op = SLJIT_MOV;+ }+ }+ }+ }+ else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC2;+ src2_r = src2_tmp_reg;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ SLJIT_ASSERT(src2_r == TMP_REG2);+ if ((flags & SLOW_DEST) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));+ }+ else {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w, dst, dstw));++ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));++ if (dst & SLJIT_MEM) {+ if (!(flags & SLOW_DEST)) {+ getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);+ return compiler->error;+ }+ return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);+ }++ return SLJIT_SUCCESS;+}++#undef CHECK_IMM++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_s32 int_op = op & SLJIT_32;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ return push_inst(compiler, BREAK, UNMOVABLE_INS);+ case SLJIT_NOP:+ return push_inst(compiler, NOP, UNMOVABLE_INS);+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));+ return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));+#else /* SLJIT_MIPS_REV < 6 */+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));+ return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));+#endif /* SLJIT_MIPS_REV >= 6 */+ 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_REV && SLJIT_MIPS_REV >= 6)+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (int_op) {+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+ }+ else {+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+ }+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));+ return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));+#else /* SLJIT_MIPS_REV < 6 */+#if !(defined SLJIT_MIPS_REV)+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* !SLJIT_MIPS_REV */+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (int_op)+ 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_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));+ return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));+#endif /* SLJIT_MIPS_REV >= 6 */+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+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_MIPS_REV >= 1 */++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_s32 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 (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (op & SLJIT_32)+ flags = INT_DATA | SIGNED_DATA;+#endif++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+#endif+ case SLJIT_MOV_P:+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ case SLJIT_MOV_U32:+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);++ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);+#endif++ case SLJIT_MOV_U8:+ return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);++ case SLJIT_MOV_S8:+ return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);++ case SLJIT_MOV_U16:+ return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);++ case SLJIT_MOV_S16:+ return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);++ case SLJIT_CLZ:+ case SLJIT_CTZ:+ case SLJIT_REV:+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++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_s32 flags = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (op & SLJIT_32) {+ flags |= INT_DATA | SIGNED_DATA;+ if (src1 == SLJIT_IMM)+ src1w = (sljit_s32)src1w;+ if (src2 == SLJIT_IMM)+ src2w = (sljit_s32)src2w;+ }+#endif++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ case SLJIT_ADDC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUB:+ case SLJIT_SUBC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_MUL:+ compiler->status_flags_state = 0;+ return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_XOR:+ if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);+ }+ /* fallthrough */+ case SLJIT_AND:+ case SLJIT_OR:+ return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_MSHL:+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ case SLJIT_ROTL:+ case SLJIT_ROTR:+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (src2 == SLJIT_IMM)+ src2w &= 0x1f;+#else+ if (src2 == SLJIT_IMM) {+ if (op & SLJIT_32)+ src2w &= 0x1f;+ else+ src2w &= 0x3f;+ }+#endif+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);+}++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+#define SELECT_OP3(op, src2w, D, D32, W) (((op & SLJIT_32) ? (W) : ((src2w) < 32) ? (D) : (D32)) | (((sljit_ins)src2w & 0x1f) << 6))+#else /* !SLJIT_CONFIG_MIPS_64 */+#define SELECT_OP3(op, src2w, D, D32, W) ((W) | ((sljit_ins)(src2w) << 6))+#endif /* SLJIT_CONFIG_MIPS_64 */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));++ switch (GET_OPCODE(op)) {+ case SLJIT_MULADD:+ SLJIT_SKIP_CHECKS(compiler);+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst_reg) | T(TMP_REG2) | D(dst_reg), DR(dst_reg));+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+ sljit_s32 is_left;+ sljit_ins ins1, ins2, ins3;+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;+#else /* !SLJIT_CONFIG_MIPS_64 */+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;+ sljit_sw bit_length = 32;+#endif /* SLJIT_CONFIG_MIPS_64 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));++ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);++ if (src1_reg == src2_reg) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);+ }++ ADJUST_LOCAL_OFFSET(src3, src3w);++ if (src3 == SLJIT_IMM) {+ src3w &= bit_length - 1;++ if (src3w == 0)+ return SLJIT_SUCCESS;++ if (is_left) {+ ins1 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);+ src3w = bit_length - src3w;+ ins2 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);+ } else {+ ins1 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);+ src3w = bit_length - src3w;+ ins2 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);+ }++ FAIL_IF(push_inst(compiler, ins1 | T(src1_reg) | D(dst_reg), DR(dst_reg)));+ FAIL_IF(push_inst(compiler, ins2 | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));+ return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));+ }++ if (src3 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG2), src3, src3w));+ src3 = TMP_REG2;+ } else if (dst_reg == src3) {+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src3) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));+ src3 = TMP_REG2;+ }++ if (is_left) {+ ins1 = SELECT_OP(DSRL, SRL);+ ins2 = SELECT_OP(DSLLV, SLLV);+ ins3 = SELECT_OP(DSRLV, SRLV);+ } else {+ ins1 = SELECT_OP(DSLL, SLL);+ ins2 = SELECT_OP(DSRLV, SRLV);+ ins3 = SELECT_OP(DSLLV, SLLV);+ }++ FAIL_IF(push_inst(compiler, ins2 | S(src3) | T(src1_reg) | D(dst_reg), DR(dst_reg)));++ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {+ FAIL_IF(push_inst(compiler, ins1 | T(src2_reg) | D(TMP_REG1) | (1 << 6), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, XORI | S(src3) | T(TMP_REG2) | ((sljit_ins)bit_length - 1), DR(TMP_REG2)));+ src2_reg = TMP_REG1;+ } else+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src3) | D(TMP_REG2), DR(TMP_REG2)));++ FAIL_IF(push_inst(compiler, ins3 | S(TMP_REG2) | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));+ return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));+}++#undef SELECT_OP3++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));++ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));+ return push_inst(compiler, NOP, UNMOVABLE_INS);+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ return emit_prefetch(compiler, src, srcw);+#else /* SLJIT_MIPS_REV < 1 */+ return SLJIT_SUCCESS;+#endif /* SLJIT_MIPS_REV >= 1 */+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 dst_ar = RETURN_ADDR_REG;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ switch (op) {+ case SLJIT_FAST_ENTER:+ if (FAST_IS_REG(dst))+ return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);+ break;+ case SLJIT_GET_RETURN_ADDRESS:+ dst_ar = DR(FAST_IS_REG(dst) ? dst : TMP_REG2);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_ar, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));+ break;+ }++ if (dst & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw));++ if (op == SLJIT_FAST_ENTER)+ compiler->delay_slot = UNMOVABLE_INS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));++ if (type == SLJIT_GP_REGISTER)+ return reg_map[reg];++ if (type != SLJIT_FLOAT_REGISTER)+ return -1;++ return FR(reg);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+ SLJIT_UNUSED_ARG(size);++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))+#define FMT(op) (FMT_S | (~(sljit_ins)op & SLJIT_32) << (21 - (5 + 3)))++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)+ sljit_u32 flags = 0;+#else+ sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;+#endif++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));++ if (FAST_IS_REG(dst)) {+ FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ return SLJIT_SUCCESS;+ }++ return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);+}++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)+ sljit_u32 flags = 0;+#else+ sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;+#endif+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM)+ FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));+ else {+ if (src == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)+ srcw = (sljit_s32)srcw;+#endif+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));+ src = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ }++ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(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)+ sljit_u32 flags = 0;+#else+ sljit_u32 flags = 1 << 21;+#endif+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW ? WORD_DATA : INT_DATA) | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));+ src = TMP_REG1;+ } else if (src == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)+ srcw = (sljit_u32)srcw;+#endif+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));+ src = TMP_REG1;+ }++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {+ if (src != TMP_REG1) {+ FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, DSRL32 | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));+ }++ FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV)+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */++ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+ }+#else /* !SLJIT_CONFIG_MIPS_64 */+ if (!(op & SLJIT_32)) {+ FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));++ FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG2) | FS(TMP_FREG1), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */++ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | 1 | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));++#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)+ FAIL_IF(push_inst(compiler, BGEZ | S(src) | 5, UNMOVABLE_INS));+#else /* SLJIT_MIPS_REV >= 1 */+ FAIL_IF(push_inst(compiler, BGEZ | S(src) | 4, UNMOVABLE_INS));+#endif /* SLJIT_MIPS_REV < 1 */++ FAIL_IF(push_inst(compiler, LUI | T(TMP_REG2) | IMM(0x41e0), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, MTC1 | TA(0) | FS(TMP_FREG2), UNMOVABLE_INS));+ switch (cpu_feature_list & CPU_FEATURE_FR) {+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+ case CPU_FEATURE_FR:+ FAIL_IF(push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(TMP_FREG2), UNMOVABLE_INS));+ break;+#endif /* SLJIT_MIPS_REV >= 2 */+ default:+ FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(TMP_FREG2) | (1 << 11), UNMOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ break;+ }+ FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(TMP_FREG2) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+ }+#endif /* SLJIT_CONFIG_MIPS_64 */++#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)+ FAIL_IF(push_inst(compiler, BLTZ | S(src) | 5, UNMOVABLE_INS));+#else /* SLJIT_MIPS_REV >= 1 */+ FAIL_IF(push_inst(compiler, BLTZ | S(src) | 4, UNMOVABLE_INS));+#endif /* SLJIT_MIPS_REV < 1 */+ FAIL_IF(push_inst(compiler, ANDI | S(src) | T(TMP_REG2) | IMM(1), DR(TMP_REG2)));++ FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV)+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* !SLJIT_MIPS_REV */++ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));++#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)+ FAIL_IF(push_inst(compiler, BEQ | 6, UNMOVABLE_INS));+#else /* SLJIT_MIPS_REV >= 1 */+ FAIL_IF(push_inst(compiler, BEQ | 5, UNMOVABLE_INS));+#endif /* SLJIT_MIPS_REV < 1 */++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ FAIL_IF(push_inst(compiler, DSRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));+#endif /* SLJIT_CONFIG_MIPS_64 */++ FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));++ FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV)+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* !SLJIT_MIPS_REV */++ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));+ FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(dst_r) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++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, FR(TMP_FREG1), src1, src1w, src2, src2w));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));+ src2 = TMP_FREG2;+ }++ switch (GET_FLAG_TYPE(op)) {+ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ inst = C_EQ_S;+ break;+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ inst = C_UEQ_S;+ break;+ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ inst = C_OLT_S;+ break;+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_LESS:+ inst = C_ULT_S;+ break;+ case SLJIT_F_GREATER:+ case SLJIT_ORDERED_GREATER:+ inst = C_ULE_S;+ break;+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER:+ inst = C_OLE_S;+ break;+ default:+ SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED);+ inst = C_UN_S;+ break;+ }+ return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);+}++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_s32 dst_r;++ CHECK_ERROR();+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)+ op ^= SLJIT_32;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (!(dst & SLJIT_MEM))+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT(op)) | FS(src) | FD(dst_r), MOVABLE_INS));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */+ FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));+ op ^= SLJIT_32;+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++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_s32 dst_r, flags = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;++ if (src1 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {+ FAIL_IF(compiler->error);+ src1 = TMP_FREG1;+ } else+ flags |= SLOW_SRC1;+ }++ if (src2 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {+ FAIL_IF(compiler->error);+ src2 = TMP_FREG2;+ } else+ flags |= SLOW_SRC2;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));+ } else {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));++ if (flags & SLOW_SRC1)+ src1 = TMP_FREG1;+ if (flags & SLOW_SRC2)+ src2 = TMP_FREG2;++ switch (GET_OPCODE(op)) {+ 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_SUB_F64:+ FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));+ break;+ 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_DIV_F64:+ FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));+ break;+ case SLJIT_COPYSIGN_F64:+ return emit_copysign(compiler, op, src1, src2, dst_r);+ }++ if (dst_r == TMP_FREG2)+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+ union {+ sljit_s32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++ if (u.imm == 0)+ return push_inst(compiler, MTC1 | TA(0) | FS(freg), MOVABLE_INS);++ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));+ return push_inst(compiler, MTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ compiler->delay_slot = UNMOVABLE_INS;+ return label;+}++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define BRANCH_LENGTH 4+#else+#define BRANCH_LENGTH 8+#endif++#define BR_Z(src) \+ inst = BEQ | SA(src) | TA(0) | BRANCH_LENGTH; \+ flags = IS_BIT26_COND; \+ delay_check = src;++#define BR_NZ(src) \+ inst = BNE | SA(src) | TA(0) | BRANCH_LENGTH; \+ flags = IS_BIT26_COND; \+ delay_check = src;++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)++#define BR_T() \+ inst = BC1NEZ; \+ flags = IS_BIT23_COND; \+ delay_check = FCSR_FCC;+#define BR_F() \+ inst = BC1EQZ; \+ flags = IS_BIT23_COND; \+ delay_check = FCSR_FCC;++#else /* SLJIT_MIPS_REV < 6 */++#define BR_T() \+ inst = BC1T | BRANCH_LENGTH; \+ flags = IS_BIT16_COND; \+ delay_check = FCSR_FCC;+#define BR_F() \+ inst = BC1F | BRANCH_LENGTH; \+ flags = IS_BIT16_COND; \+ delay_check = FCSR_FCC;++#endif /* SLJIT_MIPS_REV >= 6 */++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_u32 flags = 0;+ sljit_s32 delay_check = UNMOVABLE_INS;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ switch (type) {+ case SLJIT_EQUAL:+ BR_NZ(EQUAL_FLAG);+ break;+ case SLJIT_NOT_EQUAL:+ BR_Z(EQUAL_FLAG);+ break;+ case SLJIT_LESS:+ case SLJIT_GREATER:+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_GREATER:+ case SLJIT_OVERFLOW:+ case SLJIT_CARRY:+ 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_NOT_CARRY:+ BR_NZ(OTHER_FLAG);+ break;+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_F_GREATER:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ case SLJIT_ORDERED:+ BR_T();+ break;+ case SLJIT_F_EQUAL:+ case SLJIT_F_LESS:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ case SLJIT_ORDERED_LESS:+ case SLJIT_UNORDERED_OR_LESS:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ case SLJIT_UNORDERED:+ BR_F();+ break;+ default:+ /* Not conditional branch. */+ inst = 0;+ break;+ }++ jump->flags |= flags;+ if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))+ jump->flags |= IS_MOVABLE;++ if (inst)+ PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));++ if (type <= SLJIT_JUMP)+ PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));+ else {+ jump->flags |= IS_JAL;+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));+ }++ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));++ /* Maximum number of instructions required for generating a constant. */+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ compiler->size += 2;+#else+ compiler->size += 6;+#endif+ return jump;+}++#define RESOLVE_IMM1() \+ if (src1 == SLJIT_IMM) { \+ if (src1w) { \+ PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \+ src1 = TMP_REG1; \+ } \+ else \+ src1 = 0; \+ }++#define RESOLVE_IMM2() \+ if (src2 == SLJIT_IMM) { \+ if (src2w) { \+ PTR_FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w)); \+ src2 = src2_tmp_reg; \+ } \+ else \+ src2 = 0; \+ }++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_s32 flags;+ sljit_ins inst;+ sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ flags = WORD_DATA | LOAD_DATA;+#else /* !SLJIT_CONFIG_MIPS_32 */+ flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;+#endif /* SLJIT_CONFIG_MIPS_32 */++ if (src1 & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));+ src1 = TMP_REG1;+ }++ if (src2 & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(src2_tmp_reg), src2, src2w, 0, 0));+ src2 = src2_tmp_reg;+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ if (type <= SLJIT_NOT_EQUAL) {+ RESOLVE_IMM1();+ RESOLVE_IMM2();+ jump->flags |= IS_BIT26_COND;+ if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))+ jump->flags |= IS_MOVABLE;+ PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | BRANCH_LENGTH, UNMOVABLE_INS));+ } else if (type >= SLJIT_SIG_LESS && ((src1 == SLJIT_IMM && src1w == 0) || (src2 == SLJIT_IMM && src2w == 0))) {+ inst = NOP;+ if (src1 == SLJIT_IMM && src1w == 0) {+ RESOLVE_IMM2();+ switch (type) {+ case SLJIT_SIG_LESS:+ inst = BLEZ;+ jump->flags |= IS_BIT26_COND;+ break;+ case SLJIT_SIG_GREATER_EQUAL:+ inst = BGTZ;+ jump->flags |= IS_BIT26_COND;+ break;+ case SLJIT_SIG_GREATER:+ inst = BGEZ;+ jump->flags |= IS_BIT16_COND;+ break;+ case SLJIT_SIG_LESS_EQUAL:+ inst = BLTZ;+ jump->flags |= IS_BIT16_COND;+ break;+ }+ src1 = src2;+ }+ else {+ RESOLVE_IMM1();+ switch (type) {+ case SLJIT_SIG_LESS:+ inst = BGEZ;+ jump->flags |= IS_BIT16_COND;+ break;+ case SLJIT_SIG_GREATER_EQUAL:+ inst = BLTZ;+ jump->flags |= IS_BIT16_COND;+ break;+ case SLJIT_SIG_GREATER:+ inst = BLEZ;+ jump->flags |= IS_BIT26_COND;+ break;+ case SLJIT_SIG_LESS_EQUAL:+ inst = BGTZ;+ jump->flags |= IS_BIT26_COND;+ break;+ }+ }+ PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | BRANCH_LENGTH, UNMOVABLE_INS));+ }+ else {+ if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {+ RESOLVE_IMM1();+ if (src2 == SLJIT_IMM && src2w <= SIMM_MAX && src2w >= SIMM_MIN)+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));+ else {+ RESOLVE_IMM2();+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));+ }+ type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;+ }+ else {+ RESOLVE_IMM2();+ if (src1 == SLJIT_IMM && src1w <= SIMM_MAX && src1w >= SIMM_MIN)+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));+ else {+ RESOLVE_IMM1();+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));+ }+ type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;+ }++ jump->flags |= IS_BIT26_COND;+ PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | BRANCH_LENGTH, UNMOVABLE_INS));+ }++ PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));+ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));++ /* Maximum number of instructions required for generating a constant. */+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ compiler->size += 2;+#else+ compiler->size += 6;+#endif+ return jump;+}++#undef RESOLVE_IMM1+#undef RESOLVE_IMM2++#undef BRANCH_LENGTH+#undef BR_Z+#undef BR_NZ+#undef BR_T+#undef BR_F++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;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));++ if (src == SLJIT_IMM) {+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));+ jump->u.target = (sljit_uw)srcw;++ if (compiler->delay_slot != UNMOVABLE_INS)+ jump->flags |= IS_MOVABLE;++ src = PIC_ADDR_REG;+ } else if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));+ src = PIC_ADDR_REG;+ }++ if (type <= SLJIT_JUMP)+ FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, JALR | S(src) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));++ if (jump != NULL) {+ jump->addr = compiler->size;++ /* Maximum number of instructions required for generating a constant. */+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ compiler->size += 2;+#else+ compiler->size += 6;+#endif+ }++ return push_inst(compiler, NOP, UNMOVABLE_INS);+}++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_s32 src_ar, dst_ar, invert;+ sljit_s32 saved_op = op;+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ sljit_s32 mem_type = WORD_DATA;+#else+ sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+ 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 && (dst & SLJIT_MEM))+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));++ if (type < SLJIT_F_EQUAL) {+ src_ar = OTHER_FLAG;+ invert = type & 0x1;++ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_NOT_EQUAL:+ FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));+ src_ar = dst_ar;+ break;+ case SLJIT_OVERFLOW:+ case SLJIT_NOT_OVERFLOW:+ if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {+ src_ar = OTHER_FLAG;+ break;+ }+ FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));+ src_ar = dst_ar;+ invert ^= 0x1;+ break;+ }+ } else {+ invert = 0;++ switch (type) {+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_F_GREATER:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ case SLJIT_ORDERED:+ invert = 1;+ break;+ }++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));+#else /* SLJIT_MIPS_REV < 6 */+ FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));+#endif /* SLJIT_MIPS_REV >= 6 */+ 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;+ }++ if (invert) {+ 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 (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(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 (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)++static sljit_ins get_select_cc(sljit_s32 type, sljit_s32 is_float)+{+ switch (type & ~SLJIT_32) {+ case SLJIT_EQUAL:+ return (is_float ? MOVZ_S : MOVZ) | TA(EQUAL_FLAG);+ case SLJIT_NOT_EQUAL:+ return (is_float ? MOVN_S : MOVN) | TA(EQUAL_FLAG);+ case SLJIT_LESS:+ case SLJIT_GREATER:+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_GREATER:+ case SLJIT_OVERFLOW:+ case SLJIT_CARRY:+ return (is_float ? MOVN_S : MOVN) | TA(OTHER_FLAG);+ case SLJIT_GREATER_EQUAL:+ case SLJIT_LESS_EQUAL:+ case SLJIT_SIG_GREATER_EQUAL:+ case SLJIT_SIG_LESS_EQUAL:+ case SLJIT_NOT_OVERFLOW:+ case SLJIT_NOT_CARRY:+ return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);+ case SLJIT_F_EQUAL:+ case SLJIT_F_LESS:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ case SLJIT_ORDERED_LESS:+ case SLJIT_UNORDERED_OR_LESS:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ case SLJIT_UNORDERED:+ return is_float ? MOVT_S : MOVT;+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_F_GREATER:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ case SLJIT_ORDERED:+ return is_float ? MOVF_S : MOVF;+ default:+ SLJIT_UNREACHABLE();+ return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);+ }+}++#endif /* SLJIT_MIPS_REV >= 1 */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;+ sljit_ins mov_ins = (type & SLJIT_32) ? ADDU : DADDU;+#else /* !SLJIT_CONFIG_MIPS_64 */+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;+ sljit_ins mov_ins = ADDU;+#endif /* SLJIT_CONFIG_MIPS_64 */++#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)+ struct sljit_label *label;+ struct sljit_jump *jump;+#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));+ ADJUST_LOCAL_OFFSET(src1, src1w);++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)+ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));+ src1 = TMP_REG1;+ } else if (src1 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (type & SLJIT_32)+ src1w = (sljit_s32)src1w;+#endif+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));+ src1 = TMP_REG1;+ }++ if (dst_reg != src2_reg) {+ if (dst_reg == src1) {+ src1 = src2_reg;+ type ^= 0x1;+ } else+ FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));+ }++ return push_inst(compiler, get_select_cc(type, 0) | S(src1) | D(dst_reg), DR(dst_reg));++#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */+ if (dst_reg != src2_reg) {+ if (dst_reg == src1) {+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else {+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ FAIL_IF(push_inst(compiler, ADDU_W | S(dst_reg) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));++ if ((src1 & REG_MASK) == dst_reg)+ src1 = (src1 & ~REG_MASK) | TMP_REG1;++ if (OFFS_REG(src1) == dst_reg)+ src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);+ }++ FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));+ }+ }++ SLJIT_SKIP_CHECKS(compiler);+ jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);+ FAIL_IF(!jump);++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, DR(dst_reg), src1, src1w));+ } else if (src1 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (type & SLJIT_32)+ src1w = (sljit_s32)src1w;+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(load_immediate(compiler, DR(dst_reg), src1w));+ } else+ FAIL_IF(push_inst(compiler, mov_ins | S(src1) | TA(0) | D(dst_reg), DR(dst_reg)));++ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ FAIL_IF(!label);++ sljit_set_label(jump, label);+ return SLJIT_SUCCESS;+#endif /* SLJIT_MIPS_REV >= 1 */+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)+ struct sljit_label *label;+ struct sljit_jump *jump;+#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */++ CHECK_ERROR();+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (dst_freg != src2_freg) {+ if (dst_freg == src1) {+ src1 = src2_freg;+ src1w = 0;+ type ^= 0x1;+ } else+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src2_freg) | FD(dst_freg), MOVABLE_INS));+ }++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)+ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(TMP_FREG2), src1, src1w));+ src1 = TMP_FREG2;+ }++ return push_inst(compiler, get_select_cc(type, 1) | FMT(type) | FS(src1) | FD(dst_freg), MOVABLE_INS);++#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */+ SLJIT_SKIP_CHECKS(compiler);+ jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);+ FAIL_IF(!jump);++ if (src1 & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(dst_freg), src1, src1w));+ else+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src1) | FD(dst_freg), MOVABLE_INS));++ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ FAIL_IF(!label);++ sljit_set_label(jump, label);+ return SLJIT_SUCCESS;+#endif /* SLJIT_MIPS_REV >= 1 */+}++#undef FLOAT_DATA+#undef FMT++static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset)+{+ sljit_s32 arg = *mem;+ sljit_sw argw = *memw;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ if (SLJIT_UNLIKELY(argw)) {+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1)));+ } else+ FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1)));++ *mem = TMP_REG1;+ *memw = 0;++ return SLJIT_SUCCESS;+ }++ if (argw <= max_offset && argw >= SIMM_MIN) {+ *mem = arg & REG_MASK;+ return SLJIT_SUCCESS;+ }++ *mem = TMP_REG1;++ if ((sljit_s16)argw > max_offset) {+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw));+ *memw = 0;+ } else {+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw)));+ *memw = (sljit_s16)argw;+ }++ if ((arg & REG_MASK) == 0)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1));+}++#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#define IMM_LEFT(memw) IMM((memw) + SSIZE_OF(sw) - 1)+#define IMM_RIGHT(memw) IMM(memw)+#define IMM_32_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)+#define IMM_32_RIGHT(memw) IMM(memw)+#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)+#define IMM_F64_FIRST_RIGHT(memw) IMM(memw)+#define IMM_F64_SECOND_LEFT(memw) IMM((memw) + SSIZE_OF(f64) - 1)+#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32))+#define IMM_16_FIRST(memw) IMM((memw) + 1)+#define IMM_16_SECOND(memw) IMM(memw)+#else /* !SLJIT_LITTLE_ENDIAN */+#define IMM_LEFT(memw) IMM(memw)+#define IMM_RIGHT(memw) IMM((memw) + SSIZE_OF(sw) - 1)+#define IMM_32_LEFT(memw) IMM(memw)+#define IMM_32_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)+#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32))+#define IMM_F64_FIRST_RIGHT(memw) IMM((memw) + SSIZE_OF(f64) - 1)+#define IMM_F64_SECOND_LEFT(memw) IMM(memw)+#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)+#define IMM_16_FIRST(memw) IMM(memw)+#define IMM_16_SECOND(memw) IMM((memw) + 1)+#endif /* SLJIT_LITTLE_ENDIAN */++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16))+#else /* !SLJIT_CONFIG_MIPS_32 */+#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))+#endif /* SLJIT_CONFIG_MIPS_32 */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 op = type & 0xff;+ sljit_s32 flags = 0;+ sljit_ins ins;+#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ sljit_ins ins_right;+#endif /* !(SLJIT_MIPS_REV >= 6) */++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (reg & REG_PAIR_MASK) {+ ADJUST_LOCAL_OFFSET(mem, memw);++#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ if (MEM_CHECK_UNALIGNED(type)) {+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (2 * SSIZE_OF(sw) - 1)));++ if (!(type & SLJIT_MEM_STORE) && (mem == REG_PAIR_FIRST(reg) || mem == REG_PAIR_SECOND(reg))) {+ FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));+ mem = TMP_REG1;+ }++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ ins = ((type & SLJIT_MEM_STORE) ? SWL : LWL) | S(mem);+ ins_right = ((type & SLJIT_MEM_STORE) ? SWR : LWR) | S(mem);+#else /* !SLJIT_CONFIG_MIPS_32 */+ ins = ((type & SLJIT_MEM_STORE) ? SDL : LDL) | S(mem);+ ins_right = ((type & SLJIT_MEM_STORE) ? SDR : LDR) | S(mem);+#endif /* SLJIT_CONFIG_MIPS_32 */++ FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM_LEFT(memw), DR(REG_PAIR_FIRST(reg))));+ FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM_RIGHT(memw), DR(REG_PAIR_FIRST(reg))));+ FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM_LEFT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));+ return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM_RIGHT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));+ }+#endif /* !(SLJIT_MIPS_REV >= 6) */++ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - SSIZE_OF(sw)));++ ins = ((type & SLJIT_MEM_STORE) ? STORE_W : LOAD_W) | S(mem);++ if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {+ FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));+ return push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)));+ }++ FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg))));+ return push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));+ }++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);+#else /* !(SLJIT_MIPS_REV >= 6) */+ ADJUST_LOCAL_OFFSET(mem, memw);++ switch (op) {+ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ flags = BYTE_DATA;+ if (!(type & SLJIT_MEM_STORE))+ flags |= LOAD_DATA;++ if (op == SLJIT_MOV_S8)+ flags |= SIGNED_DATA;++ return emit_op_mem(compiler, flags, DR(reg), mem, memw);++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1));+ SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);++ if (type & SLJIT_MEM_STORE) {+ FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), MOVABLE_INS));+ return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), MOVABLE_INS);+ }++ flags = BYTE_DATA | LOAD_DATA;++ if (op == SLJIT_MOV_S16)+ flags |= SIGNED_DATA;++ FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), DR(reg)));+ FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));+ return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg));++ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (type & SLJIT_MEM_ALIGNED_32) {+ flags = WORD_DATA;+ if (!(type & SLJIT_MEM_STORE))+ flags |= LOAD_DATA;++ return emit_op_mem(compiler, flags, DR(reg), mem, memw);+ }+#else /* !SLJIT_CONFIG_MIPS_32 */+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7));+ SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);++ if (type & SLJIT_MEM_STORE) {+ FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM_LEFT(memw), MOVABLE_INS));+ return push_inst(compiler, SDR | S(mem) | T(reg) | IMM_RIGHT(memw), MOVABLE_INS);+ }++ if (mem == reg) {+ FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));+ mem = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM_LEFT(memw), DR(reg)));+ return push_inst(compiler, LDR | S(mem) | T(reg) | IMM_RIGHT(memw), DR(reg));+#endif /* SLJIT_CONFIG_MIPS_32 */+ }++ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3));+ SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);++ if (type & SLJIT_MEM_STORE) {+ FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM_32_LEFT(memw), MOVABLE_INS));+ return push_inst(compiler, SWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), MOVABLE_INS);+ }++ if (mem == reg) {+ FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));+ mem = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM_32_LEFT(memw), DR(reg)));+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg));+#else /* !SLJIT_CONFIG_MIPS_32 */+ FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg)));++ if (op != SLJIT_MOV_U32)+ return SLJIT_SUCCESS;++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)+ return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11), DR(reg));+#else /* SLJIT_MIPS_REV < 2 */+ FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)));+ return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg));+#endif /* SLJIT_MIPS_REV >= 2 */+#endif /* SLJIT_CONFIG_MIPS_32 */+#endif /* SLJIT_MIPS_REV >= 6 */+}++#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));++ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7));+ SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);++ if (type & SLJIT_MEM_STORE) {+ if (type & SLJIT_32) {+ FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));+#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), MOVABLE_INS));+ return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), MOVABLE_INS);+ }++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), MOVABLE_INS));+ FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), MOVABLE_INS));+ switch (cpu_feature_list & CPU_FEATURE_FR) {+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+ case CPU_FEATURE_FR:+ FAIL_IF(push_inst(compiler, MFHC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));+ break;+#endif /* SLJIT_MIPS_REV >= 2 */+ default:+ FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg) | (1 << 11), DR(TMP_REG2)));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif+ break;+ }++ FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), MOVABLE_INS));+ return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), MOVABLE_INS);+#else /* !SLJIT_CONFIG_MIPS_32 */+ FAIL_IF(push_inst(compiler, DMFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), MOVABLE_INS));+ return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), MOVABLE_INS);+#endif /* SLJIT_CONFIG_MIPS_32 */+ }++ if (type & SLJIT_32) {+ FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), DR(TMP_REG2)));++ FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));+#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ return SLJIT_SUCCESS;+ }++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));++ FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), DR(TMP_REG2)));+ switch (cpu_feature_list & CPU_FEATURE_FR) {+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2+ case CPU_FEATURE_FR:+ return push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS);+#endif /* SLJIT_MIPS_REV >= 2 */+ default:+ FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg) | (1 << 11), MOVABLE_INS));+ break;+ }+#else /* !SLJIT_CONFIG_MIPS_32 */+ FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), DR(TMP_REG2)));++ FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));+#endif /* SLJIT_CONFIG_MIPS_32 */+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* MIPS III */+ return SLJIT_SUCCESS;+}++#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */++#undef IMM_16_SECOND+#undef IMM_16_FIRST+#undef IMM_F64_SECOND_RIGHT+#undef IMM_F64_SECOND_LEFT+#undef IMM_F64_FIRST_RIGHT+#undef IMM_F64_FIRST_LEFT+#undef IMM_32_RIGHT+#undef IMM_32_LEFT+#undef IMM_RIGHT+#undef IMM_LEFT+#undef MEM_CHECK_UNALIGNED++#undef TO_ARGW_HI++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ compiler->size += 1;+#else+ compiler->size += 5;+#endif++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));++ return jump; }
src/c/pcre2/src/sljit/sljitNativePPC_32.c view
@@ -38,12 +38,15 @@ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; } +/* Simplified mnemonics: clrlwi. */ #define INS_CLEAR_LEFT(dst, src, from) \- (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))+ (RLWINM | S(src) | A(dst) | RLWI_MBE(from, 31)) 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_u32 imm;+ switch (op) { case SLJIT_MOV: case SLJIT_MOV_U32:@@ -82,14 +85,20 @@ } return SLJIT_SUCCESS; - case SLJIT_NOT:- SLJIT_ASSERT(src1 == TMP_REG1);- return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));- case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1); return push_inst(compiler, CNTLZW | S(src2) | A(dst)); + case SLJIT_CTZ:+ SLJIT_ASSERT(src1 == TMP_REG1);+ FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));+ FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));+ FAIL_IF(push_inst(compiler, CNTLZW | S(dst) | A(dst)));+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM(-32)));+ /* The highest bits are set, if dst < 32, zero otherwise. */+ FAIL_IF(push_inst(compiler, SRWI(27) | S(TMP_REG1) | A(TMP_REG1)));+ return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));+ case SLJIT_ADD: if (flags & ALT_FORM1) { /* Setting XER SO is not enough, CR SO is also needed. */@@ -103,12 +112,14 @@ if (flags & ALT_FORM3) return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + imm = compiler->imm;+ if (flags & ALT_FORM4) {- FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));+ FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1)))); src1 = dst; } - return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2);@@ -208,8 +219,10 @@ } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2);- FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));- return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));+ imm = compiler->imm;++ FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));+ return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16)); } return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); @@ -224,34 +237,82 @@ } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2);- FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));- return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));+ imm = compiler->imm;++ FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));+ return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16)); }+ if (flags & ALT_FORM4) {+ SLJIT_ASSERT(src1 == TMP_REG1);+ return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));+ } return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_SHL:+ case SLJIT_MSHL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2);- compiler->imm &= 0x1f;- return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));+ imm = compiler->imm & 0x1f;+ return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst)); }++ if (op == SLJIT_MSHL) {+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));+ src2 = TMP_REG2;+ }+ return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_LSHR:+ case SLJIT_MLSHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2);- compiler->imm &= 0x1f;- return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));+ imm = compiler->imm & 0x1f;+ /* Since imm can be 0, SRWI() cannot be used. */+ return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31)); }++ if (op == SLJIT_MLSHR) {+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));+ src2 = TMP_REG2;+ }+ return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR:+ case SLJIT_MASHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2);- compiler->imm &= 0x1f;- return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));+ imm = compiler->imm & 0x1f;+ return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11)); }++ if (op == SLJIT_MASHR) {+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));+ src2 = TMP_REG2;+ }+ return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ imm = compiler->imm;++ if (op == SLJIT_ROTR)+ imm = (sljit_u32)(-(sljit_s32)imm);++ imm &= 0x1f;+ return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));+ }++ if (op == SLJIT_ROTR) {+ FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));+ src2 = TMP_REG2;+ }++ return push_inst(compiler, RLWNM | S(src1) | A(dst) | B(src2) | RLWI_MBE(0, 31)); } SLJIT_UNREACHABLE();@@ -264,6 +325,151 @@ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); } +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_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 ^ (sljit_sw)0x80000000));+ src = TMP_REG1;+ invert_sign = 0;+ } else if (!FAST_IS_REG(src)) {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ /* First, a special double precision floating point value is constructed:+ (2^53 + (src xor (2^31)))+ The upper 32 bits of this number is a constant, and the lower 32 bits+ is simply the value of the source argument. The xor 2^31 operation adds+ 0x80000000 to the source argument, which moves it into the 0 - 0xffffffff+ range. Finally we substract 2^53 + 2^31 to get the converted value. */+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));+ if (invert_sign)+ FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));+ FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));+ FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));++ FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));++ if (op & SLJIT_32)+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ } else if (!FAST_IS_REG(src)) {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ /* First, a special double precision floating point value is constructed:+ (2^53 + src)+ The upper 32 bits of this number is a constant, and the lower 32 bits+ is simply the value of the source argument. Finally we substract 2^53+ to get the converted value. */+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));+ FAIL_IF(push_inst(compiler, STW | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));+ FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));++ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, STW | S(TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));++ FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));++ if (op & SLJIT_32)+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ union {+ sljit_s32 imm[2];+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ if (u.imm[0] != 0)+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));+ if (u.imm[1] != 0)+ FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));++ /* Saved in the same endianness. */+ FAIL_IF(push_inst(compiler, STW | S(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, STW | S(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | A(SLJIT_SP) | (TMP_MEM_OFFSET + sizeof(sljit_s32))));+ return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_s32 reg2 = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ if (op & SLJIT_32) {+ if (op == SLJIT_COPY32_TO_F32) {+ FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);+ }++ FAIL_IF(push_inst(compiler, STFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);+ }++ if (reg & REG_PAIR_MASK) {+ reg2 = REG_PAIR_SECOND(reg);+ reg = REG_PAIR_FIRST(reg);+ }++ if (op == SLJIT_COPY_TO_F64) {+ FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));++ if (reg2 != 0)+ FAIL_IF(push_inst(compiler, STW | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));+ else+ FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));++ return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);+ }++ FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));++ if (reg2 != 0)+ FAIL_IF(push_inst(compiler, LWZ | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));++ return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI);+}+ 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;@@ -276,9 +482,4 @@ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); 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_sw executable_offset)-{- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset); }
src/c/pcre2/src/sljit/sljitNativePPC_64.c view
@@ -35,8 +35,9 @@ #error "Must implement count leading zeroes" #endif -#define PUSH_RLDICR(reg, shift) \- push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))+/* Computes SLDI(63 - shift). */+#define PUSH_SLDI_NEG(reg, shift) \+ push_inst(compiler, RLDICR | S(reg) | A(reg) | RLDI_SH(63 - shift) | RLDI_ME(shift)) static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm) {@@ -48,7 +49,7 @@ if (imm <= SIMM_MAX && imm >= SIMM_MIN) return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm)); - if (!(imm & ~0xffff))+ if (((sljit_uw)imm >> 16) == 0) return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm)); if (imm <= 0x7fffffffl && imm >= -0x80000000l) {@@ -56,6 +57,11 @@ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; } + if (((sljit_uw)imm >> 32) == 0) {+ FAIL_IF(push_inst(compiler, ORIS | S(TMP_ZERO) | A(reg) | IMM(imm >> 16)));+ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;+ }+ /* Count leading zeroes. */ tmp = (sljit_uw)((imm >= 0) ? imm : ~imm); ASM_SLJIT_CLZ(tmp, shift);@@ -66,14 +72,14 @@ if ((tmp & ~0xffff000000000000ul) == 0) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); shift += 15;- return PUSH_RLDICR(reg, shift);+ return PUSH_SLDI_NEG(reg, shift); } if ((tmp & ~0xffffffff00000000ul) == 0) { FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32))); shift += 31;- return PUSH_RLDICR(reg, shift);+ return PUSH_SLDI_NEG(reg, shift); } /* Cut out the 16 bit from immediate. */@@ -82,13 +88,13 @@ if (tmp2 <= 0xffff) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));- FAIL_IF(PUSH_RLDICR(reg, shift));+ FAIL_IF(PUSH_SLDI_NEG(reg, shift)); return push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)tmp2); } if (tmp2 <= 0xffffffff) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));- FAIL_IF(PUSH_RLDICR(reg, shift));+ FAIL_IF(PUSH_SLDI_NEG(reg, shift)); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 16))); return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS; }@@ -100,23 +106,24 @@ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); shift2 += 15; shift += (63 - shift2);- FAIL_IF(PUSH_RLDICR(reg, shift));+ FAIL_IF(PUSH_SLDI_NEG(reg, shift)); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48)));- return PUSH_RLDICR(reg, shift2);+ return PUSH_SLDI_NEG(reg, shift2); } /* The general version. */ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)((sljit_uw)imm >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));- FAIL_IF(PUSH_RLDICR(reg, 31));+ FAIL_IF(PUSH_SLDI_NEG(reg, 31)); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16))); return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)); } -/* Simplified mnemonics: clrldi. */-#define INS_CLEAR_LEFT(dst, src, from) \- (RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5))+#undef PUSH_SLDI_NEG +#define CLRLDI(dst, src, n) \+ (RLDICL | S(src) | A(dst) | RLDI_SH(0) | RLDI_MB(n))+ /* Sign extension for integer operations. */ #define UN_EXTS() \ if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \@@ -145,6 +152,8 @@ 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_u32 imm;+ switch (op) { case SLJIT_MOV: case SLJIT_MOV_P:@@ -159,7 +168,7 @@ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S32) return push_inst(compiler, EXTSW | S(src2) | A(dst));- return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));+ return push_inst(compiler, CLRLDI(dst, src2, 32)); } else { SLJIT_ASSERT(dst == src2);@@ -172,7 +181,7 @@ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst));- return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));+ return push_inst(compiler, CLRLDI(dst, src2, 56)); } else if ((flags & REG_DEST) && op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst));@@ -187,36 +196,39 @@ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S16) return push_inst(compiler, EXTSH | S(src2) | A(dst));- return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));+ return push_inst(compiler, CLRLDI(dst, src2, 48)); } else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; - case SLJIT_NOT:+ case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1);- UN_EXTS();- return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));+ return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(src2) | A(dst)); - case SLJIT_CLZ:+ case SLJIT_CTZ: SLJIT_ASSERT(src1 == TMP_REG1);- if (flags & ALT_FORM1)- return push_inst(compiler, CNTLZW | S(src2) | A(dst));- return push_inst(compiler, CNTLZD | S(src2) | A(dst));+ FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));+ FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));+ FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(dst) | A(dst)));+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM((flags & ALT_FORM1) ? -32 : -64)));+ /* The highest bits are set, if dst < bit width, zero otherwise. */+ FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? SRWI(27) : SRDI(58)) | S(TMP_REG1) | A(TMP_REG1)));+ return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1)); case SLJIT_ADD: if (flags & ALT_FORM1) { if (flags & ALT_SIGN_EXT) {- FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));+ FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1))); src1 = TMP_REG1;- FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));+ FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2))); 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 push_inst(compiler, SRDI(32) | S(dst) | A(dst)); return SLJIT_SUCCESS; } @@ -227,12 +239,14 @@ if (flags & ALT_FORM3) return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + imm = compiler->imm;+ if (flags & ALT_FORM4) {- FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));+ FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1)))); src1 = dst; } - return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2);@@ -287,11 +301,11 @@ if (flags & ALT_FORM3) { if (flags & ALT_SIGN_EXT) { if (src1 != TMP_ZERO) {- FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));+ FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1))); src1 = TMP_REG1; } if (src2 != TMP_ZERO) {- FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));+ FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2))); src2 = TMP_REG2; } }@@ -303,7 +317,7 @@ FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2))); if (flags & ALT_SIGN_EXT)- return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));+ return push_inst(compiler, SRDI(32) | S(dst) | A(dst)); return SLJIT_SUCCESS; } @@ -362,8 +376,10 @@ } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2);- FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));- return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));+ imm = compiler->imm;++ FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));+ return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16)); } return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); @@ -378,46 +394,110 @@ } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2);- FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));- return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));+ imm = compiler->imm;++ FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));+ return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16)); }+ if (flags & ALT_FORM4) {+ SLJIT_ASSERT(src1 == TMP_REG1);+ UN_EXTS();+ return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));+ } return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_SHL:+ case SLJIT_MSHL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2);+ imm = compiler->imm;+ if (flags & ALT_FORM2) {- compiler->imm &= 0x1f;- return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));+ imm &= 0x1f;+ return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst)); }- compiler->imm &= 0x3f;- return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));++ imm &= 0x3f;+ return push_inst(compiler, SLDI(imm) | RC(flags) | S(src1) | A(dst)); }++ if (op == SLJIT_MSHL) {+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));+ src2 = TMP_REG2;+ }+ return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_LSHR:+ case SLJIT_MLSHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2);+ imm = compiler->imm;+ if (flags & ALT_FORM2) {- compiler->imm &= 0x1f;- return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));+ imm &= 0x1f;+ /* Since imm can be 0, SRWI() cannot be used. */+ return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31)); }- compiler->imm &= 0x3f;- return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));++ imm &= 0x3f;+ /* Since imm can be 0, SRDI() cannot be used. */+ return push_inst(compiler, RLDICL | RC(flags) | S(src1) | A(dst) | RLDI_SH((64 - imm) & 0x3f) | RLDI_MB(imm)); }++ if (op == SLJIT_MLSHR) {+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));+ src2 = TMP_REG2;+ }+ return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR:+ case SLJIT_MASHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2);+ imm = compiler->imm;+ if (flags & ALT_FORM2) {- compiler->imm &= 0x1f;- return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));+ imm &= 0x1f;+ return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11)); }- compiler->imm &= 0x3f;- return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));++ imm &= 0x3f;+ return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | RLDI_SH(imm)); }++ if (op == SLJIT_MASHR) {+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));+ src2 = TMP_REG2;+ }+ return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ imm = compiler->imm;++ if (op == SLJIT_ROTR)+ imm = (sljit_u32)(-(sljit_s32)imm);++ if (flags & ALT_FORM2) {+ imm &= 0x1f;+ return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));+ }++ imm &= 0x3f;+ return push_inst(compiler, RLDICL | S(src1) | A(dst) | RLDI_SH(imm));+ }++ if (op == SLJIT_ROTR) {+ FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));+ src2 = TMP_REG2;+ }++ return push_inst(compiler, ((flags & ALT_FORM2) ? (RLWNM | RLWI_MBE(0, 31)) : (RLDCL | RLDI_MB(0))) | S(src1) | A(dst) | B(src2)); } SLJIT_UNREACHABLE();@@ -483,11 +563,146 @@ { 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)));- FAIL_IF(PUSH_RLDICR(reg, 31));+ FAIL_IF(push_inst(compiler, SLDI(32) | S(reg) | A(reg))); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16))); return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); } +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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src == SLJIT_IMM) {+ 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_CONV_F64_FROM_S32) {+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));+ else+ FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ if (FAST_IS_REG(src)) {+ FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ } else+ FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));++ FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));++ if (op & SLJIT_32)+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {+ if (src == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_u32)srcw));+ src = TMP_REG1;+ } else {+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, CLRLDI(TMP_REG1, src, 32)));+ else+ FAIL_IF(emit_op_mem(compiler, INT_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));+ } else {+ if (src == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ } else if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, CMPI | CRD(0 | 1) | A(src) | 0));+ FAIL_IF(push_inst(compiler, BCx | (12 << 21) | (0 << 16) | 20));+ FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));+ FAIL_IF(push_inst(compiler, Bx | ((op & SLJIT_32) ? 36 : 32)));++ if (op & SLJIT_32)+ FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(TMP_REG2) | RLWI_SH(10) | RLWI_MBE(10, 21)));+ else+ FAIL_IF(push_inst(compiler, ANDI | S(src) | A(TMP_REG2) | 0x1));++ /* Shift right. */+ FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(63) | RLDI_MB(1)));++ if (op & SLJIT_32)+ FAIL_IF(push_inst(compiler, RLDICR | S(TMP_REG1) | A(TMP_REG1) | RLDI_SH(0) | RLDI_ME(53)));++ FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));++ FAIL_IF(push_inst(compiler, STD | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));+ FAIL_IF(push_inst(compiler, FADD | FD(dst_r) | FA(dst_r) | FB(dst_r)));+ }++ if (op & SLJIT_32)+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ union {+ sljit_sw imm;+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ if (u.imm != 0)+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));++ FAIL_IF(push_inst(compiler, STD | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STW : STD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ return push_inst(compiler, ((op & SLJIT_32) ? LFS : LFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);+ }++ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ return push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);+}+ 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;@@ -501,9 +716,4 @@ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1); 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_sw executable_offset)-{- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset); }
src/c/pcre2/src/sljit/sljitNativePPC_common.c view
@@ -98,2492 +98,3064 @@ #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) #define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5) #else-#define TMP_CALL_REG TMP_REG2-#endif--#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)-#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)--static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {- 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12-};--static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 0, 13-};--/* --------------------------------------------------------------------- */-/* Instrucion forms */-/* --------------------------------------------------------------------- */-#define D(d) ((sljit_ins)reg_map[d] << 21)-#define S(s) ((sljit_ins)reg_map[s] << 21)-#define A(a) ((sljit_ins)reg_map[a] << 16)-#define B(b) ((sljit_ins)reg_map[b] << 11)-#define C(c) ((sljit_ins)reg_map[c] << 6)-#define FD(fd) ((sljit_ins)freg_map[fd] << 21)-#define FS(fs) ((sljit_ins)freg_map[fs] << 21)-#define FA(fa) ((sljit_ins)freg_map[fa] << 16)-#define FB(fb) ((sljit_ins)freg_map[fb] << 11)-#define FC(fc) ((sljit_ins)freg_map[fc] << 6)-#define IMM(imm) ((sljit_ins)(imm) & 0xffff)-#define CRD(d) ((sljit_ins)(d) << 21)--/* Instruction bit sections.- OE and Rc flag (see 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 HI(opcode) ((sljit_ins)(opcode) << 26)-#define LO(opcode) ((sljit_ins)(opcode) << 1)--#define ADD (HI(31) | LO(266))-#define ADDC (HI(31) | LO(10))-#define ADDE (HI(31) | LO(138))-#define ADDI (HI(14))-#define ADDIC (HI(13))-#define ADDIS (HI(15))-#define ADDME (HI(31) | LO(234))-#define AND (HI(31) | LO(28))-#define ANDI (HI(28))-#define ANDIS (HI(29))-#define Bx (HI(18))-#define BCx (HI(16))-#define BCCTR (HI(19) | LO(528) | (3 << 11))-#define BLR (HI(19) | LO(16) | (0x14 << 21))-#define CNTLZD (HI(31) | LO(58))-#define CNTLZW (HI(31) | LO(26))-#define CMP (HI(31) | LO(0))-#define CMPI (HI(11))-#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))-#define DIVWU (HI(31) | LO(459))-#define EXTSB (HI(31) | LO(954))-#define EXTSH (HI(31) | LO(922))-#define EXTSW (HI(31) | LO(986))-#define FABS (HI(63) | LO(264))-#define FADD (HI(63) | LO(21))-#define FADDS (HI(59) | LO(21))-#define FCFID (HI(63) | LO(846))-#define FCMPU (HI(63) | LO(0))-#define FCTIDZ (HI(63) | LO(815))-#define FCTIWZ (HI(63) | LO(15))-#define FDIV (HI(63) | LO(18))-#define FDIVS (HI(59) | LO(18))-#define FMR (HI(63) | LO(72))-#define FMUL (HI(63) | LO(25))-#define FMULS (HI(59) | LO(25))-#define FNEG (HI(63) | LO(40))-#define FRSP (HI(63) | LO(12))-#define FSUB (HI(63) | LO(20))-#define FSUBS (HI(59) | LO(20))-#define LD (HI(58) | 0)-#define LFD (HI(50))-#define LWZ (HI(32))-#define MFCR (HI(31) | LO(19))-#define MFLR (HI(31) | LO(339) | 0x80000)-#define MFXER (HI(31) | LO(339) | 0x10000)-#define MTCTR (HI(31) | LO(467) | 0x90000)-#define MTLR (HI(31) | LO(467) | 0x80000)-#define MTXER (HI(31) | LO(467) | 0x10000)-#define MULHD (HI(31) | LO(73))-#define MULHDU (HI(31) | LO(9))-#define MULHW (HI(31) | LO(75))-#define MULHWU (HI(31) | LO(11))-#define MULLD (HI(31) | LO(233))-#define MULLI (HI(7))-#define MULLW (HI(31) | LO(235))-#define NEG (HI(31) | LO(104))-#define NOP (HI(24))-#define NOR (HI(31) | LO(124))-#define OR (HI(31) | LO(444))-#define ORI (HI(24))-#define ORIS (HI(25))-#define RLDICL (HI(30))-#define RLWINM (HI(21))-#define SLD (HI(31) | LO(27))-#define SLW (HI(31) | LO(24))-#define SRAD (HI(31) | LO(794))-#define SRADI (HI(31) | LO(413 << 1))-#define SRAW (HI(31) | LO(792))-#define SRAWI (HI(31) | LO(824))-#define SRD (HI(31) | LO(539))-#define SRW (HI(31) | LO(536))-#define STD (HI(62) | 0)-#define STDU (HI(62) | 1)-#define STDUX (HI(31) | LO(181))-#define STFD (HI(54))-#define STFIWX (HI(31) | LO(983))-#define STW (HI(36))-#define STWU (HI(37))-#define STWUX (HI(31) | LO(183))-#define SUBF (HI(31) | LO(40))-#define SUBFC (HI(31) | LO(8))-#define SUBFE (HI(31) | LO(136))-#define SUBFIC (HI(8))-#define XOR (HI(31) | LO(316))-#define XORI (HI(26))-#define XORIS (HI(27))--#define SIMM_MAX (0x7fff)-#define SIMM_MIN (-0x8000)-#define UIMM_MAX (0xffff)--#define RLDI(dst, src, sh, mb, type) \- (HI(30) | S(src) | A(dst) | ((sljit_ins)(type) << 2) | (((sljit_ins)(sh) & 0x1f) << 11) \- | (((sljit_ins)(sh) & 0x20) >> 4) | (((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20))--#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func)-{- sljit_uw* ptrs;-- if (func_ptr)- *func_ptr = (void*)context;-- ptrs = (sljit_uw*)func;- context->addr = addr ? addr : ptrs[0];- context->r2 = ptrs[1];- context->r11 = ptrs[2];-}-#endif--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);- *ptr = ins;- compiler->size++;- return SLJIT_SUCCESS;-}--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;- sljit_uw extra_jump_flags;--#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))- return 0;-#else- if (jump->flags & SLJIT_REWRITABLE_JUMP)- return 0;-#endif-- if (jump->flags & JUMP_ADDR)- target_addr = jump->u.target;- else {- SLJIT_ASSERT(jump->flags & JUMP_LABEL);- 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)- if (jump->flags & IS_CALL)- goto keep_address;-#endif-- diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;-- extra_jump_flags = 0;- if (jump->flags & IS_COND) {- if (diff <= 0x7fff && diff >= -0x8000) {- jump->flags |= PATCH_B;- return 1;- }- if (target_addr <= 0xffff) {- jump->flags |= PATCH_B | PATCH_ABS_B;- return 1;- }- extra_jump_flags = REMOVE_COND;-- diff -= SSIZE_OF(ins);- }-- if (diff <= 0x01ffffff && diff >= -0x02000000) {- 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;- }--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)-keep_address:-#endif- if (target_addr <= 0x7fffffff) {- jump->flags |= PATCH_ABS32;- return 1;- }-- if (target_addr <= 0x7fffffffffffl) {- jump->flags |= PATCH_ABS48;- return 1;- }-#endif-- return 0;-}--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)--static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)-{- if (max_label < 0x100000000l) {- put_label->flags = 0;- return 1;- }-- if (max_label < 0x1000000000000l) {- put_label->flags = 1;- return 3;- }-- put_label->flags = 2;- return 4;-}--static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)-{- sljit_uw addr = put_label->label->addr;- sljit_ins *inst = (sljit_ins *)put_label->addr;- sljit_u32 reg = *inst;-- if (put_label->flags == 0) {- SLJIT_ASSERT(addr < 0x100000000l);- inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 16);- }- else {- if (put_label->flags == 1) {- SLJIT_ASSERT(addr < 0x1000000000000l);- inst[0] = ORI | S(TMP_ZERO) | A(reg) | IMM(addr >> 32);- }- else {- inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 48);- inst[1] = ORI | S(reg) | A(reg) | IMM((addr >> 32) & 0xffff);- inst ++;- }-- inst[1] = RLDI(reg, reg, 32, 31, 1);- inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff);- inst += 2;- }-- inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff);-}--#endif--SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)-{- struct sljit_memory_fragment *buf;- sljit_ins *code;- sljit_ins *code_ptr;- sljit_ins *buf_ptr;- sljit_ins *buf_end;- sljit_uw word_count;- sljit_uw next_addr;- sljit_sw executable_offset;- sljit_uw addr;-- struct sljit_label *label;- struct sljit_jump *jump;- struct sljit_const *const_;- struct sljit_put_label *put_label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_generate_code(compiler));- reverse_buf(compiler);--#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));-#else- compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));-#endif-#endif- code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);- PTR_FAIL_WITH_EXEC_IF(code);- buf = compiler->buf;-- code_ptr = code;- word_count = 0;- next_addr = 0;- executable_offset = SLJIT_EXEC_OFFSET(code);-- label = compiler->labels;- jump = compiler->jumps;- const_ = compiler->consts;- put_label = compiler->put_labels;-- do {- buf_ptr = (sljit_ins*)buf->memory;- buf_end = buf_ptr + (buf->used_size >> 2);- do {- *code_ptr = *buf_ptr++;- if (next_addr == word_count) {- SLJIT_ASSERT(!label || label->size >= word_count);- SLJIT_ASSERT(!jump || jump->addr >= word_count);- SLJIT_ASSERT(!const_ || const_->addr >= word_count);- SLJIT_ASSERT(!put_label || put_label->addr >= word_count);-- /* These structures are ordered by their address. */- if (label && label->size == word_count) {- /* Just recording the address. */- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }- if (jump && jump->addr == word_count) {-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- jump->addr = (sljit_uw)(code_ptr - 3);-#else- jump->addr = (sljit_uw)(code_ptr - 6);-#endif- 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;-#else- if (jump->flags & PATCH_ABS32) {- code_ptr -= 3;- code_ptr[-1] = code_ptr[2];- code_ptr[0] = code_ptr[3];- }- else if (jump->flags & PATCH_ABS48) {- code_ptr--;- code_ptr[-1] = code_ptr[0];- code_ptr[0] = code_ptr[1];- /* rldicr rX,rX,32,31 -> rX,rX,16,47 */- SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);- code_ptr[-3] ^= 0x8422;- /* oris -> ori */- code_ptr[-2] ^= 0x4000000;- }- else {- code_ptr[-6] = code_ptr[0];- code_ptr -= 6;- }-#endif- if (jump->flags & REMOVE_COND) {- code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);- code_ptr++;- jump->addr += sizeof(sljit_ins);- code_ptr[0] = Bx;- jump->flags -= IS_COND;- }- }- jump = jump->next;- }- if (const_ && const_->addr == word_count) {- const_->addr = (sljit_uw)code_ptr;- const_ = const_->next;- }- if (put_label && put_label->addr == word_count) {- SLJIT_ASSERT(put_label->label);- put_label->addr = (sljit_uw)code_ptr;-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));- word_count += 4;-#endif- put_label = put_label->next;- }- next_addr = compute_next_addr(label, jump, const_, put_label);- }- code_ptr ++;- word_count ++;- } while (buf_ptr < buf_end);-- buf = buf->next;- } while (buf);-- if (label && label->size == word_count) {- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }-- SLJIT_ASSERT(!label);- SLJIT_ASSERT(!jump);- SLJIT_ASSERT(!const_);- SLJIT_ASSERT(!put_label);--#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)- SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins))));-#else- SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);-#endif-- jump = compiler->jumps;- while (jump) {- do {- addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;- buf_ptr = (sljit_ins *)jump->addr;-- if (jump->flags & PATCH_B) {- if (jump->flags & IS_COND) {- if (!(jump->flags & PATCH_ABS_B)) {- addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);- SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);- *buf_ptr = BCx | ((sljit_ins)addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);- }- else {- SLJIT_ASSERT(addr <= 0xffff);- *buf_ptr = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);- }- }- else {- if (!(jump->flags & PATCH_ABS_B)) {- addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);- SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);- *buf_ptr = Bx | ((sljit_ins)addr & 0x03fffffc) | ((*buf_ptr) & 0x1);- }- else {- SLJIT_ASSERT(addr <= 0x03ffffff);- *buf_ptr = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);- }- }- break;- }-- /* Set the fields of immediate loads. */-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);- buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;- buf_ptr[1] |= (sljit_ins)addr & 0xffff;-#else- if (jump->flags & PATCH_ABS32) {- SLJIT_ASSERT(addr <= 0x7fffffff);- SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);- buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;- buf_ptr[1] |= (sljit_ins)addr & 0xffff;- break;- }-- if (jump->flags & PATCH_ABS48) {- SLJIT_ASSERT(addr <= 0x7fffffffffff);- SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3]) & 0xffff) == 0);- buf_ptr[0] |= (sljit_ins)(addr >> 32) & 0xffff;- buf_ptr[1] |= (sljit_ins)(addr >> 16) & 0xffff;- buf_ptr[3] |= (sljit_ins)addr & 0xffff;- break;- }-- SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3] | buf_ptr[4]) & 0xffff) == 0);- buf_ptr[0] |= (sljit_ins)(addr >> 48) & 0xffff;- buf_ptr[1] |= (sljit_ins)(addr >> 32) & 0xffff;- buf_ptr[3] |= (sljit_ins)(addr >> 16) & 0xffff;- buf_ptr[4] |= (sljit_ins)addr & 0xffff;-#endif- } while (0);- jump = jump->next;- }-- put_label = compiler->put_labels;- while (put_label) {-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- addr = put_label->label->addr;- buf_ptr = (sljit_ins *)put_label->addr;-- SLJIT_ASSERT((buf_ptr[0] & 0xfc1f0000) == ADDIS && (buf_ptr[1] & 0xfc000000) == ORI);- buf_ptr[0] |= (addr >> 16) & 0xffff;- buf_ptr[1] |= addr & 0xffff;-#else- put_label_set(put_label);-#endif- put_label = put_label->next;- }-- compiler->error = SLJIT_ERR_COMPILED;- compiler->executable_offset = executable_offset;- compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);-- 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_uw)code, (void*)sljit_generate_code);-#endif-- code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);-- SLJIT_CACHE_FLUSH(code, code_ptr);- SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);--#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)- return code_ptr;-#else- 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- /* Available by default. */- return 1;-#endif-- /* A saved register is set to a zero value. */- case SLJIT_HAS_ZERO_REGISTER:- case SLJIT_HAS_CLZ:- case SLJIT_HAS_PREFETCH:- return 1;-- default:- return 0;- }-}--/* --------------------------------------------------------------------- */-/* Entry, exit */-/* --------------------------------------------------------------------- */--/* inp_flags: */--/* Creates an index in data_transfer_insts array. */-#define LOAD_DATA 0x01-#define INDEXED 0x02-#define SIGNED_DATA 0x04--#define WORD_DATA 0x00-#define BYTE_DATA 0x08-#define HALF_DATA 0x10-#define INT_DATA 0x18-/* Separates integer and floating point registers */-#define GPR_REG 0x1f-#define DOUBLE_DATA 0x20--#define MEM_MASK 0x7f--/* Other inp_flags. */--/* Integer opertion and set flags -> requires exts on 64 bit systems. */-#define ALT_SIGN_EXT 0x000100-/* This flag affects the RC() and OERC() macros. */-#define ALT_SET_FLAGS 0x000400-#define ALT_FORM1 0x001000-#define ALT_FORM2 0x002000-#define ALT_FORM3 0x004000-#define ALT_FORM4 0x008000-#define ALT_FORM5 0x010000--/* Source and destination is register. */-#define REG_DEST 0x000001-#define REG1_SOURCE 0x000002-#define REG2_SOURCE 0x000004-/*-ALT_SIGN_EXT 0x000100-ALT_SET_FLAGS 0x000200-ALT_FORM1 0x001000-...-ALT_FORM5 0x010000 */--#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)-#include "sljitNativePPC_32.c"-#else-#include "sljitNativePPC_64.c"-#endif--#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)-#define STACK_STORE STW-#define STACK_LOAD LWZ-#else-#define STACK_STORE STD-#define STACK_LOAD LD-#endif--#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)-#define LR_SAVE_OFFSET 2 * SSIZE_OF(sw)-#else-#define LR_SAVE_OFFSET SSIZE_OF(sw)-#endif--#define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET)--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 i, tmp, base, offset;- sljit_s32 word_arg_count = 0;- sljit_s32 saved_arg_count = 0;-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- sljit_s32 arg_count = 0;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1)- + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));- local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;- compiler->local_size = local_size;-- FAIL_IF(push_inst(compiler, MFLR | D(0)));-- base = SLJIT_SP;- offset = local_size;-- if (local_size <= STACK_MAX_DISTANCE) {-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));-#else- FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));-#endif- } else {- base = TMP_REG1;- FAIL_IF(push_inst(compiler, OR | S(SLJIT_SP) | A(TMP_REG1) | B(SLJIT_SP)));- FAIL_IF(load_immediate(compiler, TMP_REG2, -local_size));-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));-#else- FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));-#endif- local_size = 0;- offset = 0;- }-- tmp = SLJIT_FS0 - fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- offset -= SSIZE_OF(f64);- FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));- }-- for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- offset -= SSIZE_OF(f64);- FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));- }-- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));-- tmp = SLJIT_S0 - saveds;- for (i = SLJIT_S0; i > tmp; i--) {- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));- }-- for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));- }-- FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));- FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));-- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types > 0) {- if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- do {- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- tmp = SLJIT_S0 - saved_arg_count;- saved_arg_count++;- } else if (arg_count != word_arg_count)- tmp = SLJIT_R0 + word_arg_count;- else- break;-- FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + arg_count) | A(tmp) | B(SLJIT_R0 + arg_count)));- } while (0);-#else- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + word_arg_count) | A(SLJIT_S0 - saved_arg_count) | B(SLJIT_R0 + word_arg_count)));- saved_arg_count++;- }-#endif- word_arg_count++;- }--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- arg_count++;-#endif- arg_types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- CHECK_ERROR();- CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1)- + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));- compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;- return SLJIT_SUCCESS;-}---static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)-{- sljit_s32 i, tmp, base, offset;- sljit_s32 local_size = compiler->local_size;-- base = SLJIT_SP;- if (local_size > STACK_MAX_DISTANCE) {- base = TMP_REG1;- if (local_size > 2 * STACK_MAX_DISTANCE + LR_SAVE_OFFSET) {- FAIL_IF(push_inst(compiler, STACK_LOAD | D(base) | A(SLJIT_SP) | IMM(0)));- local_size = 0;- } else {- FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(SLJIT_SP) | IMM(local_size - STACK_MAX_DISTANCE)));- local_size = STACK_MAX_DISTANCE;- }- }-- offset = local_size;- FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET)));-- tmp = SLJIT_FS0 - compiler->fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- offset -= SSIZE_OF(f64);- FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));- }-- for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- offset -= SSIZE_OF(f64);- FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));- }-- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));-- tmp = SLJIT_S0 - compiler->saveds;- for (i = SLJIT_S0; i > tmp; i--) {- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));- }-- for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {- offset -= SSIZE_OF(sw);- FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));- }-- push_inst(compiler, MTLR | S(0));-- if (local_size > 0)- return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size));-- SLJIT_ASSERT(base == TMP_REG1);- return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)-{- CHECK_ERROR();- CHECK(check_sljit_emit_return_void(compiler));-- FAIL_IF(emit_stack_frame_release(compiler));- return push_inst(compiler, BLR);-}--#undef STACK_STORE-#undef STACK_LOAD--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--/* s/l - store/load (1 bit)- i/x - immediate/indexed form- u/s - signed/unsigned (1 bit)- w/b/h/i - word/byte/half/int allowed (2 bit)-- Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */--/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-#define INT_ALIGNED 0x10000-#endif--#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)-#define ARCH_32_64(a, b) a-#define INST_CODE_AND_DST(inst, flags, reg) \- ((sljit_ins)(inst) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))-#else-#define ARCH_32_64(a, b) b-#define INST_CODE_AND_DST(inst, flags, reg) \- (((sljit_ins)(inst) & ~(sljit_ins)INT_ALIGNED) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))-#endif--static const sljit_ins data_transfer_insts[64 + 16] = {--/* -------- Integer -------- */--/* Word. */--/* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),-/* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),-/* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),-/* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),--/* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),-/* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),-/* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),-/* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),--/* Byte. */--/* b u i s */ HI(38) /* stb */,-/* b u i l */ HI(34) /* lbz */,-/* b u x s */ HI(31) | LO(215) /* stbx */,-/* b u x l */ HI(31) | LO(87) /* lbzx */,--/* b s i s */ HI(38) /* stb */,-/* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,-/* b s x s */ HI(31) | LO(215) /* stbx */,-/* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,--/* Half. */--/* h u i s */ HI(44) /* sth */,-/* h u i l */ HI(40) /* lhz */,-/* h u x s */ HI(31) | LO(407) /* sthx */,-/* h u x l */ HI(31) | LO(279) /* lhzx */,--/* h s i s */ HI(44) /* sth */,-/* h s i l */ HI(42) /* lha */,-/* h s x s */ HI(31) | LO(407) /* sthx */,-/* h s x l */ HI(31) | LO(343) /* lhax */,--/* Int. */--/* i u i s */ HI(36) /* stw */,-/* i u i l */ HI(32) /* lwz */,-/* i u x s */ HI(31) | LO(151) /* stwx */,-/* i u x l */ HI(31) | LO(23) /* lwzx */,--/* i s i s */ HI(36) /* stw */,-/* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),-/* i s x s */ HI(31) | LO(151) /* stwx */,-/* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),--/* -------- Floating point -------- */--/* d i s */ HI(54) /* stfd */,-/* d i l */ HI(50) /* lfd */,-/* d x s */ HI(31) | LO(727) /* stfdx */,-/* d x l */ HI(31) | LO(599) /* lfdx */,--/* s i s */ HI(52) /* stfs */,-/* s i l */ HI(48) /* lfs */,-/* s x s */ HI(31) | LO(663) /* stfsx */,-/* s x l */ HI(31) | LO(535) /* lfsx */,-};--static const sljit_ins updated_data_transfer_insts[64] = {--/* -------- Integer -------- */--/* Word. */--/* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),-/* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),-/* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),-/* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),--/* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),-/* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),-/* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),-/* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),--/* Byte. */--/* b u i s */ HI(39) /* stbu */,-/* b u i l */ HI(35) /* lbzu */,-/* b u x s */ HI(31) | LO(247) /* stbux */,-/* b u x l */ HI(31) | LO(119) /* lbzux */,--/* b s i s */ HI(39) /* stbu */,-/* b s i l */ 0 /* no such instruction */,-/* b s x s */ HI(31) | LO(247) /* stbux */,-/* b s x l */ 0 /* no such instruction */,--/* Half. */--/* h u i s */ HI(45) /* sthu */,-/* h u i l */ HI(41) /* lhzu */,-/* h u x s */ HI(31) | LO(439) /* sthux */,-/* h u x l */ HI(31) | LO(311) /* lhzux */,--/* h s i s */ HI(45) /* sthu */,-/* h s i l */ HI(43) /* lhau */,-/* h s x s */ HI(31) | LO(439) /* sthux */,-/* h s x l */ HI(31) | LO(375) /* lhaux */,--/* Int. */--/* i u i s */ HI(37) /* stwu */,-/* i u i l */ HI(33) /* lwzu */,-/* i u x s */ HI(31) | LO(183) /* stwux */,-/* i u x l */ HI(31) | LO(55) /* lwzux */,--/* i s i s */ HI(37) /* stwu */,-/* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),-/* i s x s */ HI(31) | LO(183) /* stwux */,-/* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),--/* -------- Floating point -------- */--/* d i s */ HI(55) /* stfdu */,-/* d i l */ HI(51) /* lfdu */,-/* d x s */ HI(31) | LO(759) /* stfdux */,-/* d x l */ HI(31) | LO(631) /* lfdux */,--/* s i s */ HI(53) /* stfsu */,-/* s i l */ HI(49) /* lfsu */,-/* s x s */ HI(31) | LO(695) /* stfsux */,-/* s x l */ HI(31) | LO(567) /* lfsux */,-};--#undef ARCH_32_64--/* Simple cases, (no caching is required). */-static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,- sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)-{- sljit_ins inst;- sljit_s32 offs_reg;- sljit_sw high_short;-- /* Should work when (arg & REG_MASK) == 0. */- SLJIT_ASSERT(A(0) == 0);- SLJIT_ASSERT(arg & SLJIT_MEM);-- if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {- argw &= 0x3;- offs_reg = OFFS_REG(arg);-- if (argw != 0) {-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | ((sljit_ins)argw << 11) | ((31 - (sljit_ins)argw) << 1)));-#else- FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1)));-#endif- offs_reg = tmp_reg;- }-- inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- SLJIT_ASSERT(!(inst & INT_ALIGNED));-#endif-- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));- }-- inst = data_transfer_insts[inp_flags & MEM_MASK];- arg &= REG_MASK;--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {- FAIL_IF(load_immediate(compiler, tmp_reg, argw));-- inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));- }-#endif-- if (argw <= SIMM_MAX && argw >= SIMM_MIN)- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {-#endif-- high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);-#else- SLJIT_ASSERT(high_short);-#endif-- FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16)));- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- }-- /* The rest is PPC-64 only. */-- FAIL_IF(load_immediate(compiler, tmp_reg, argw));-- inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];- return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));-#endif-}--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- result goes to TMP_REG2, so put result can use TMP_REG1. */- sljit_s32 dst_r = TMP_REG2;- 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);-- /* Destination check. */- if (FAST_IS_REG(dst)) {- dst_r = dst;- /* The REG_DEST is only used by SLJIT_MOV operations, although- * it is set for op2 operations with unset destination. */- flags |= REG_DEST;-- if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)- sugg_src2_r = dst_r;- }-- /* Source 1. */- if (FAST_IS_REG(src1)) {- src1_r = src1;- flags |= REG1_SOURCE;- }- else if (src1 & SLJIT_IMM) {- src1_r = TMP_ZERO;- if (src1w != 0) {- FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));- src1_r = TMP_REG1;- }- }- else {- FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));- src1_r = TMP_REG1;- }-- /* Source 2. */- if (FAST_IS_REG(src2)) {- src2_r = src2;- flags |= REG2_SOURCE;-- if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)- dst_r = src2_r;- }- else if (src2 & SLJIT_IMM) {- src2_r = TMP_ZERO;- if (src2w != 0) {- FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));- src2_r = sugg_src2_r;- }- }- else {- FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, TMP_REG2));- src2_r = sugg_src2_r;- }-- FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));-- if (!(dst & SLJIT_MEM))- return SLJIT_SUCCESS;-- return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);-}--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_s32 int_op = op & SLJIT_32;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_op0(compiler, op));-- op = GET_OPCODE(op);- switch (op) {- case SLJIT_BREAKPOINT:- case SLJIT_NOP:- return push_inst(compiler, NOP);- 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_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_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));-#endif- 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_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_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_DIV_UW:- case SLJIT_DIV_SW:-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- 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_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));-#endif- case SLJIT_ENDBR:- case SLJIT_SKIP_FRAMES_BEFORE_RETURN:- return SLJIT_SUCCESS;- }-- 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))- 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) | ((sljit_ins)srcw << 11) | ((31 - (sljit_ins)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_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 dst, sljit_sw dstw,- sljit_s32 src, sljit_sw srcw)-{- 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);-- op = GET_OPCODE(op);-- if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)- FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));-- if (op < SLJIT_NOT && 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_flags & SLJIT_32) {- if (op < SLJIT_NOT) {- if (src & SLJIT_MEM) {- if (op == SLJIT_MOV_S32)- op = SLJIT_MOV_U32;- }- else if (src & SLJIT_IMM) {- if (op == SLJIT_MOV_U32)- op = SLJIT_MOV_S32;- }- }- else {- /* Most operations expect sign extended arguments. */- flags |= INT_DATA | SIGNED_DATA;- if (HAS_FLAGS(op_flags))- flags |= ALT_SIGN_EXT;- }- }-#endif-- switch (op) {- case SLJIT_MOV:-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:-#endif- case SLJIT_MOV_P:- 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_U32:- return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));-- case SLJIT_MOV_S32:- case SLJIT_MOV32:- return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));-#endif-- case SLJIT_MOV_U8:- return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));-- case SLJIT_MOV_S8:- return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));-- case SLJIT_MOV_U16:- return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));-- case SLJIT_MOV_S16:- return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));-- case SLJIT_NOT:- return emit_op(compiler, SLJIT_NOT, flags, 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_32) ? 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- }-- return SLJIT_SUCCESS;-}--#undef EMIT_MOV--#define TEST_SL_IMM(src, srcw) \- (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)--#define TEST_UL_IMM(src, srcw) \- (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-#define TEST_SH_IMM(src, srcw) \- (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)-#else-#define TEST_SH_IMM(src, srcw) \- (((src) & SLJIT_IMM) && !((srcw) & 0xffff))-#endif--#define TEST_UH_IMM(src, srcw) \- (((src) & SLJIT_IMM) && !((srcw) & ~(sljit_sw)0xffff0000))--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-#define TEST_ADD_IMM(src, srcw) \- (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)-#else-#define TEST_ADD_IMM(src, srcw) \- ((src) & SLJIT_IMM)-#endif--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-#define TEST_UI_IMM(src, srcw) \- (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))-#else-#define TEST_UI_IMM(src, srcw) \- ((src) & SLJIT_IMM)-#endif--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-#define TEST_ADD_FORM1(op) \- (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \- || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY))-#define TEST_SUB_FORM2(op) \- ((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \- || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z))-#define TEST_SUB_FORM3(op) \- (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \- || (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z))-#else-#define TEST_ADD_FORM1(op) \- (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)-#define TEST_SUB_FORM2(op) \- (GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)-#define TEST_SUB_FORM3(op) \- (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)-#endif--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_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;-- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- if (op & SLJIT_32) {- /* Most operations expect sign extended arguments. */- flags |= INT_DATA | SIGNED_DATA;- if (src1 & SLJIT_IMM)- src1w = (sljit_s32)(src1w);- if (src2 & SLJIT_IMM)- src2w = (sljit_s32)(src2w);- if (HAS_FLAGS(op))- flags |= ALT_SIGN_EXT;- }-#endif- if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)- FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));-- switch (GET_OPCODE(op)) {- case SLJIT_ADD:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;-- if (TEST_ADD_FORM1(op))- 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 = (sljit_ins)src2w & 0xffff;- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);- }- if (TEST_SL_IMM(src1, src1w)) {- compiler->imm = (sljit_ins)src1w & 0xffff;- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);- }- if (TEST_SH_IMM(src2, src2w)) {- compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;- 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 = (sljit_ins)(src1w >> 16) & 0xffff;- 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 = (sljit_ins)src2w & 0xffffffff;- 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 = (sljit_ins)src1w & 0xffffffff;- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);- }- }--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- if ((op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) {- if (TEST_SL_IMM(src2, src2w)) {- compiler->imm = (sljit_ins)src2w & 0xffff;- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);- }- if (TEST_SL_IMM(src1, src1w)) {- compiler->imm = (sljit_ins)src1w & 0xffff;- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);- }- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);- }-#endif- if (HAS_FLAGS(op)) {- if (TEST_SL_IMM(src2, src2w)) {- compiler->imm = (sljit_ins)src2w & 0xffff;- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);- }- if (TEST_SL_IMM(src1, src1w)) {- compiler->imm = (sljit_ins)src1w & 0xffff;- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);- }- }- return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_ADDC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_SUB:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;-- if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {- if (dst == TMP_REG2) {- if (TEST_UL_IMM(src2, src2w)) {- compiler->imm = (sljit_ins)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 = (sljit_ins)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 (dst == TMP_REG2 && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {- if (TEST_SL_IMM(src2, src2w)) {- compiler->imm = (sljit_ins)src2w & 0xffff;- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);- }- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);- }-- if (TEST_SUB_FORM2(op)) {- if ((src2 & SLJIT_IMM) && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {- compiler->imm = (sljit_ins)src2w & 0xffff;- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);- }- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);- }-- if (TEST_SUB_FORM3(op))- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);-- if (TEST_SL_IMM(src2, -src2w)) {- compiler->imm = (sljit_ins)(-src2w) & 0xffff;- return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);- }-- if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {- compiler->imm = (sljit_ins)src1w & 0xffff;- return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);- }-- if (!HAS_FLAGS(op)) {- if (TEST_SH_IMM(src2, -src2w)) {- compiler->imm = (sljit_ins)((-src2w) >> 16) & 0xffff;- 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 = (sljit_ins)-src2w;- return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);- }- }-- /* We know ALT_SIGN_EXT is set if it is an SLJIT_32 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:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- 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_32)- flags |= ALT_FORM2;-#endif- if (!HAS_FLAGS(op)) {- if (TEST_SL_IMM(src2, src2w)) {- compiler->imm = (sljit_ins)src2w & 0xffff;- return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);- }- if (TEST_SL_IMM(src1, src1w)) {- compiler->imm = (sljit_ins)src1w & 0xffff;- 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 (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {- if (TEST_UL_IMM(src2, src2w)) {- compiler->imm = (sljit_ins)src2w;- return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);- }- if (TEST_UL_IMM(src1, src1w)) {- compiler->imm = (sljit_ins)src1w;- return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);- }- if (TEST_UH_IMM(src2, src2w)) {- compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;- return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);- }- if (TEST_UH_IMM(src1, src1w)) {- compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;- return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);- }- }- if (GET_OPCODE(op) != SLJIT_AND) {- /* Unlike or and xor, the and resets unwanted bits as well. */- if (TEST_UI_IMM(src2, src2w)) {- compiler->imm = (sljit_ins)src2w;- return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);- }- if (TEST_UI_IMM(src1, src1w)) {- compiler->imm = (sljit_ins)src1w;- return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);- }- }- return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_SHL:- case SLJIT_LSHR:- case SLJIT_ASHR:-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- if (op & SLJIT_32)- flags |= ALT_FORM2;-#endif- if (src2 & SLJIT_IMM) {- compiler->imm = (sljit_ins)src2w;- return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);- }- return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 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_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);-}--#undef TEST_ADD_FORM1-#undef TEST_SUB_FORM2-#undef TEST_SUB_FORM3--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- switch (op) {- case SLJIT_FAST_RETURN:- if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, MTLR | S(src)));- else {- FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));- FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));- }-- return push_inst(compiler, BLR);- case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:- return SLJIT_SUCCESS;- case SLJIT_PREFETCH_L1:- case SLJIT_PREFETCH_L2:- case SLJIT_PREFETCH_L3:- case SLJIT_PREFETCH_ONCE:- return emit_prefetch(compiler, src, srcw);- }-- return SLJIT_SUCCESS;-}--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_s32 sljit_get_float_register_index(sljit_s32 reg)-{- CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));- return freg_map[reg];-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_custom(compiler, instruction, size));-- return push_inst(compiler, *(sljit_ins*)instruction);-}--/* --------------------------------------------------------------------- */-/* Floating point operators */-/* --------------------------------------------------------------------- */--#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6))-#define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double))--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-#define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))-#else-#define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw))--#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)-#define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw))-#define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw))-#else-#define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw))-#define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw))-#endif--#endif /* SLJIT_CONFIG_PPC_64 */--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. */- FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));- src = TMP_FREG1;- }--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- op = GET_OPCODE(op);- FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));-- if (op == SLJIT_CONV_SW_FROM_F64) {- if (FAST_IS_REG(dst)) {- FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));- return emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);- }- return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);- }-#else- FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));-#endif-- if (FAST_IS_REG(dst)) {- FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET));- FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));- return emit_op_mem(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);- }-- SLJIT_ASSERT(dst & SLJIT_MEM);-- if (dst & OFFS_REG_MASK) {- dstw &= 0x3;- if (dstw) {-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | ((sljit_ins)dstw << 11) | ((31 - (sljit_ins)dstw) << 1)));-#else- FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));-#endif- dstw = TMP_REG1;- }- else- dstw = OFFS_REG(dst);- }- else {- if ((dst & REG_MASK) && !dstw) {- dstw = dst & REG_MASK;- dst = 0;- }- else {- /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */- FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));- dstw = TMP_REG1;- }- }-- return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));-}--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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- if (src & SLJIT_IMM) {- 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_CONV_F64_FROM_S32) {- if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));- else- FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));- src = TMP_REG1;- }-- if (FAST_IS_REG(src)) {- FAIL_IF(emit_op_mem(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));- FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));- }- else- FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));-- FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));-- if (dst & SLJIT_MEM)- return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);- if (op & SLJIT_32)- return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));- return SLJIT_SUCCESS;--#else-- 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 ^ (sljit_sw)0x80000000));- src = TMP_REG1;- invert_sign = 0;- }- else if (!FAST_IS_REG(src)) {- FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));- src = TMP_REG1;- }-- /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31)))- The double precision format has exactly 53 bit precision, so the lower 32 bit represents- the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000- to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating- point value, we need to substract 2^53 + 2^31 from the constructed value. */- FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));- if (invert_sign)- FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));- FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, TMP_REG1));- FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));- FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));- FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));- FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));- FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));-- FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));-- if (dst & SLJIT_MEM)- return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);- if (op & SLJIT_32)- return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));- return SLJIT_SUCCESS;--#endif-}--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_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));- src1 = TMP_FREG1;- }-- if (src2 & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));- src2 = TMP_FREG2;- }-- return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2));-}--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_s32 dst_r;-- CHECK_ERROR();-- SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);- SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);-- if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)- op ^= SLJIT_32;-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));- src = dst_r;- }-- switch (GET_OPCODE(op)) {- case SLJIT_CONV_F64_FROM_F32:- op ^= SLJIT_32;- if (op & SLJIT_32) {- FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));- break;- }- /* Fall through. */- case SLJIT_MOV_F64:- if (src != dst_r) {- if (dst_r != TMP_FREG1)- FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));- else- dst_r = src;- }- break;- case SLJIT_NEG_F64:- FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));- break;- case SLJIT_ABS_F64:- FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));- break;- }-- if (dst & SLJIT_MEM)- FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));- return SLJIT_SUCCESS;-}--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_s32 dst_r;-- CHECK_ERROR();- CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;-- if (src1 & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));- src1 = TMP_FREG1;- }-- if (src2 & SLJIT_MEM) {- FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));- src2 = TMP_FREG2;- }-- switch (GET_OPCODE(op)) {- case SLJIT_ADD_F64:- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));- break;-- case SLJIT_SUB_F64:- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));- break;-- 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_DIV_F64:- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));- break;- }-- if (dst & SLJIT_MEM)- FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));-- return SLJIT_SUCCESS;-}--#undef SELECT_FOP--/* --------------------------------------------------------------------- */-/* Other instructions */-/* --------------------------------------------------------------------- */--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);-- if (FAST_IS_REG(dst))- return push_inst(compiler, MFLR | D(dst));-- /* Memory. */- FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));- return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);-}--/* --------------------------------------------------------------------- */-/* Conditional instructions */-/* --------------------------------------------------------------------- */--SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)-{- struct sljit_label *label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_label(compiler));-- if (compiler->last_label && compiler->last_label->size == compiler->size)- return compiler->last_label;-- label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));- PTR_FAIL_IF(!label);- set_label(label, compiler);- return label;-}--static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)-{- switch (type) {- case SLJIT_NOT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)- return (4 << 21) | (2 << 16);- /* fallthrough */-- case SLJIT_EQUAL:- return (12 << 21) | (2 << 16);-- case SLJIT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)- return (12 << 21) | (2 << 16);- /* fallthrough */-- case SLJIT_NOT_EQUAL:- return (4 << 21) | (2 << 16);-- case SLJIT_LESS:- 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:- return (12 << 21) | (3 << 16);-- case SLJIT_NOT_OVERFLOW:- return (4 << 21) | (3 << 16);-- case SLJIT_EQUAL_F64:- return (12 << 21) | ((4 + 2) << 16);-- case SLJIT_NOT_EQUAL_F64:- return (4 << 21) | ((4 + 2) << 16);-- case SLJIT_UNORDERED_F64:- return (12 << 21) | ((4 + 3) << 16);-- case SLJIT_ORDERED_F64:- return (4 << 21) | ((4 + 3) << 16);-- default:- SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);- return (20 << 21);- }-}--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;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_jump(compiler, type));-- bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);- if (!bo_bi_flags)- return NULL;-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP);- type &= 0xff;-- if (type == SLJIT_CARRY || type == SLJIT_NOT_CARRY)- PTR_FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));-- /* In PPC, we don't need to touch the arguments. */- if (type < SLJIT_JUMP)- jump->flags |= IS_COND;-#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)- if (type >= SLJIT_CALL)- jump->flags |= IS_CALL;-#endif-- PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));- PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG)));- jump->addr = compiler->size;- PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));- return jump;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types)-{- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));-#endif-- if (type & SLJIT_CALL_RETURN) {- PTR_FAIL_IF(emit_stack_frame_release(compiler));- type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);- }--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_jump(compiler, type);-}--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_s32 src_r;-- CHECK_ERROR();- CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- if (FAST_IS_REG(src)) {-#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)- if (type >= SLJIT_CALL && src != TMP_CALL_REG) {- FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));- src_r = TMP_CALL_REG;- }- else- src_r = src;-#else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */- src_r = src;-#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */- } else if (src & SLJIT_IMM) {- /* These jumps are converted to jump/call instructions when possible. */- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- FAIL_IF(!jump);- set_jump(jump, compiler, JUMP_ADDR);- jump->u.target = (sljit_uw)srcw;--#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)- if (type >= SLJIT_CALL)- jump->flags |= IS_CALL;-#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */-- FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));- src_r = TMP_CALL_REG;- }- else {- FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));- src_r = TMP_CALL_REG;- }-- FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));- if (jump)- jump->addr = compiler->size;- return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));-- if (src & SLJIT_MEM) {- ADJUST_LOCAL_OFFSET(src, srcw);- FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));- src = TMP_CALL_REG;- }-- if (type & SLJIT_CALL_RETURN) {- if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {- FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));- src = TMP_CALL_REG;- }-- FAIL_IF(emit_stack_frame_release(compiler));- type = SLJIT_JUMP;- }--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- FAIL_IF(call_with_args(compiler, arg_types, &src));-#endif--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_ijump(compiler, type, src, srcw);-}--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_s32 reg, invert;- sljit_u32 bit, from_xer;- sljit_s32 saved_op = op;- sljit_sw saved_dstw = dstw;-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- sljit_s32 input_flags = ((op & SLJIT_32) || op == SLJIT_MOV32) ? INT_DATA : WORD_DATA;-#else- sljit_s32 input_flags = WORD_DATA;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));- ADJUST_LOCAL_OFFSET(dst, dstw);-- op = GET_OPCODE(op);- reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;-- if (op >= SLJIT_ADD && (dst & SLJIT_MEM))- FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));-- invert = 0;- bit = 0;- from_xer = 0;-- switch (type & 0xff) {- case SLJIT_LESS:- case SLJIT_SIG_LESS:- break;-- case SLJIT_GREATER_EQUAL:- case SLJIT_SIG_GREATER_EQUAL:- invert = 1;- break;-- case SLJIT_GREATER:- case SLJIT_SIG_GREATER:- bit = 1;- break;-- case SLJIT_LESS_EQUAL:- case SLJIT_SIG_LESS_EQUAL:- bit = 1;- invert = 1;- break;-- case SLJIT_EQUAL:- bit = 2;- break;-- case SLJIT_NOT_EQUAL:- bit = 2;- invert = 1;- break;-- case SLJIT_OVERFLOW:- from_xer = 1;- bit = 1;- break;-- case SLJIT_NOT_OVERFLOW:- from_xer = 1;- bit = 1;- invert = 1;- break;-- case SLJIT_CARRY:- from_xer = 1;- bit = 2;- invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB) != 0;- break;-- case SLJIT_NOT_CARRY:- from_xer = 1;- bit = 2;- invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0;- break;-- case SLJIT_LESS_F64:- bit = 4 + 0;- break;-- case SLJIT_GREATER_EQUAL_F64:- bit = 4 + 0;- invert = 1;- break;-- case SLJIT_GREATER_F64:- bit = 4 + 1;- break;-- case SLJIT_LESS_EQUAL_F64:- bit = 4 + 1;- invert = 1;- break;-- case SLJIT_EQUAL_F64:- bit = 4 + 2;- break;-- case SLJIT_NOT_EQUAL_F64:- bit = 4 + 2;- invert = 1;- break;-- case SLJIT_UNORDERED_F64:- bit = 4 + 3;- break;-- case SLJIT_ORDERED_F64:- bit = 4 + 3;- invert = 1;- break;-- default:- SLJIT_UNREACHABLE();- break;- }-- FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg)));- FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + bit) << 11) | (31 << 6) | (31 << 1)));-- if (invert)- FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));-- if (op < SLJIT_ADD) {- if (!(dst & SLJIT_MEM))- return SLJIT_SUCCESS;- return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);- }--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif- 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 sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 reg,- sljit_s32 mem, sljit_sw memw)-{- sljit_s32 mem_flags;- sljit_ins inst;-- CHECK_ERROR();- CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));-- if (type & SLJIT_MEM_POST)- return SLJIT_ERR_UNSUPPORTED;-- switch (type & 0xff) {- case SLJIT_MOV:- case SLJIT_MOV_P:-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:-#endif- mem_flags = WORD_DATA;- break;--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- case SLJIT_MOV_U32:- case SLJIT_MOV32:- mem_flags = INT_DATA;- break;-- case SLJIT_MOV_S32:- mem_flags = INT_DATA;-- if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_32)) {- if (mem & OFFS_REG_MASK)- mem_flags |= SIGNED_DATA;- else- return SLJIT_ERR_UNSUPPORTED;- }- break;-#endif-- case SLJIT_MOV_U8:- case SLJIT_MOV_S8:- mem_flags = BYTE_DATA;- break;-- case SLJIT_MOV_U16:- mem_flags = HALF_DATA;- break;-- case SLJIT_MOV_S16:- mem_flags = HALF_DATA | SIGNED_DATA;- break;-- default:- SLJIT_UNREACHABLE();- mem_flags = WORD_DATA;- break;- }-- if (!(type & SLJIT_MEM_STORE))- mem_flags |= LOAD_DATA;-- if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {- if (memw != 0)- return SLJIT_ERR_UNSUPPORTED;-- if (type & SLJIT_MEM_SUPP)- return SLJIT_SUCCESS;-- inst = updated_data_transfer_insts[mem_flags | INDEXED];- FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));- }- else {- if (memw > SIMM_MAX || memw < SIMM_MIN)- return SLJIT_ERR_UNSUPPORTED;-- inst = updated_data_transfer_insts[mem_flags];--#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)- if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)- return SLJIT_ERR_UNSUPPORTED;-#endif-- if (type & SLJIT_MEM_SUPP)- return SLJIT_SUCCESS;-- FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));- }-- if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)- return push_inst(compiler, EXTSB | S(reg) | A(reg));- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 freg,- sljit_s32 mem, sljit_sw memw)-{- sljit_s32 mem_flags;- sljit_ins inst;-- CHECK_ERROR();- CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));-- if (type & SLJIT_MEM_POST)- return SLJIT_ERR_UNSUPPORTED;-- if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {- if (memw != 0)- return SLJIT_ERR_UNSUPPORTED;- }- else {- if (memw > SIMM_MAX || memw < SIMM_MIN)- return SLJIT_ERR_UNSUPPORTED;- }-- if (type & SLJIT_MEM_SUPP)- return SLJIT_SUCCESS;-- mem_flags = FLOAT_DATA(type);-- if (!(type & SLJIT_MEM_STORE))- mem_flags |= LOAD_DATA;-- if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {- inst = updated_data_transfer_insts[mem_flags | INDEXED];- return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));- }-- inst = updated_data_transfer_insts[mem_flags];- return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)-{- struct sljit_const *const_;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));- ADJUST_LOCAL_OFFSET(dst, dstw);-- const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));- PTR_FAIL_IF(!const_);- set_const(const_, compiler);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;- PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));-- return const_;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- struct sljit_put_label *put_label;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);-- put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));- PTR_FAIL_IF(!put_label);- set_put_label(put_label, compiler, 0);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)- PTR_FAIL_IF(emit_const(compiler, dst_r, 0));-#else- PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));- compiler->size += 4;-#endif-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));-- return put_label;+#define TMP_CALL_REG TMP_REG1+#endif++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {+ 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 0, 13+};++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */+#define D(d) ((sljit_ins)reg_map[d] << 21)+#define S(s) ((sljit_ins)reg_map[s] << 21)+#define A(a) ((sljit_ins)reg_map[a] << 16)+#define B(b) ((sljit_ins)reg_map[b] << 11)+#define C(c) ((sljit_ins)reg_map[c] << 6)+#define FD(fd) ((sljit_ins)freg_map[fd] << 21)+#define FS(fs) ((sljit_ins)freg_map[fs] << 21)+#define FA(fa) ((sljit_ins)freg_map[fa] << 16)+#define FB(fb) ((sljit_ins)freg_map[fb] << 11)+#define FC(fc) ((sljit_ins)freg_map[fc] << 6)+#define IMM(imm) ((sljit_ins)(imm) & 0xffff)+#define CRD(d) ((sljit_ins)(d) << 21)++/* Instruction bit sections.+ OE and Rc flag (see ALT_SET_FLAGS). */+#define OE(flags) ((flags) & ALT_SET_FLAGS)+/* Rc flag (see ALT_SET_FLAGS). */+#define RC(flags) ((sljit_ins)((flags) & ALT_SET_FLAGS) >> 10)+#define HI(opcode) ((sljit_ins)(opcode) << 26)+#define LO(opcode) ((sljit_ins)(opcode) << 1)++#define ADD (HI(31) | LO(266))+#define ADDC (HI(31) | LO(10))+#define ADDE (HI(31) | LO(138))+#define ADDI (HI(14))+#define ADDIC (HI(13))+#define ADDIS (HI(15))+#define ADDME (HI(31) | LO(234))+#define AND (HI(31) | LO(28))+#define ANDI (HI(28))+#define ANDIS (HI(29))+#define Bx (HI(18))+#define BCx (HI(16))+#define BCCTR (HI(19) | LO(528) | (3 << 11))+#define BLR (HI(19) | LO(16) | (0x14 << 21))+#if defined(_ARCH_PWR10) && _ARCH_PWR10+#define BRD (HI(31) | LO(187))+#endif /* POWER10 */+#define CNTLZD (HI(31) | LO(58))+#define CNTLZW (HI(31) | LO(26))+#define CMP (HI(31) | LO(0))+#define CMPI (HI(11))+#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))+#define DIVWU (HI(31) | LO(459))+#define EXTSB (HI(31) | LO(954))+#define EXTSH (HI(31) | LO(922))+#define EXTSW (HI(31) | LO(986))+#define FABS (HI(63) | LO(264))+#define FADD (HI(63) | LO(21))+#define FADDS (HI(59) | LO(21))+#define FCFID (HI(63) | LO(846))+#define FCMPU (HI(63) | LO(0))+#define FCTIDZ (HI(63) | LO(815))+#define FCTIWZ (HI(63) | LO(15))+#define FDIV (HI(63) | LO(18))+#define FDIVS (HI(59) | LO(18))+#define FMR (HI(63) | LO(72))+#define FMUL (HI(63) | LO(25))+#define FMULS (HI(59) | LO(25))+#define FNEG (HI(63) | LO(40))+#define FRSP (HI(63) | LO(12))+#define FSUB (HI(63) | LO(20))+#define FSUBS (HI(59) | LO(20))+#define LD (HI(58) | 0)+#define LFD (HI(50))+#define LFS (HI(48))+#if defined(_ARCH_PWR7) && _ARCH_PWR7+#define LDBRX (HI(31) | LO(532))+#endif /* POWER7 */+#define LHBRX (HI(31) | LO(790))+#define LWBRX (HI(31) | LO(534))+#define LWZ (HI(32))+#define MFCR (HI(31) | LO(19))+#define MFLR (HI(31) | LO(339) | 0x80000)+#define MFXER (HI(31) | LO(339) | 0x10000)+#define MTCTR (HI(31) | LO(467) | 0x90000)+#define MTLR (HI(31) | LO(467) | 0x80000)+#define MTXER (HI(31) | LO(467) | 0x10000)+#define MULHD (HI(31) | LO(73))+#define MULHDU (HI(31) | LO(9))+#define MULHW (HI(31) | LO(75))+#define MULHWU (HI(31) | LO(11))+#define MULLD (HI(31) | LO(233))+#define MULLI (HI(7))+#define MULLW (HI(31) | LO(235))+#define NEG (HI(31) | LO(104))+#define NOP (HI(24))+#define NOR (HI(31) | LO(124))+#define OR (HI(31) | LO(444))+#define ORI (HI(24))+#define ORIS (HI(25))+#define RLDCL (HI(30) | LO(8))+#define RLDICL (HI(30) | LO(0 << 1))+#define RLDICR (HI(30) | LO(1 << 1))+#define RLDIMI (HI(30) | LO(3 << 1))+#define RLWIMI (HI(20))+#define RLWINM (HI(21))+#define RLWNM (HI(23))+#define SLD (HI(31) | LO(27))+#define SLW (HI(31) | LO(24))+#define SRAD (HI(31) | LO(794))+#define SRADI (HI(31) | LO(413 << 1))+#define SRAW (HI(31) | LO(792))+#define SRAWI (HI(31) | LO(824))+#define SRD (HI(31) | LO(539))+#define SRW (HI(31) | LO(536))+#define STD (HI(62) | 0)+#if defined(_ARCH_PWR7) && _ARCH_PWR7+#define STDBRX (HI(31) | LO(660))+#endif /* POWER7 */+#define STDU (HI(62) | 1)+#define STDUX (HI(31) | LO(181))+#define STFD (HI(54))+#define STFIWX (HI(31) | LO(983))+#define STFS (HI(52))+#define STHBRX (HI(31) | LO(918))+#define STW (HI(36))+#define STWBRX (HI(31) | LO(662))+#define STWU (HI(37))+#define STWUX (HI(31) | LO(183))+#define SUBF (HI(31) | LO(40))+#define SUBFC (HI(31) | LO(8))+#define SUBFE (HI(31) | LO(136))+#define SUBFIC (HI(8))+#define XOR (HI(31) | LO(316))+#define XORI (HI(26))+#define XORIS (HI(27))++#define SIMM_MAX (0x7fff)+#define SIMM_MIN (-0x8000)+#define UIMM_MAX (0xffff)++/* Shift helpers. */+#define RLWI_SH(sh) ((sljit_ins)(sh) << 11)+#define RLWI_MBE(mb, me) (((sljit_ins)(mb) << 6) | ((sljit_ins)(me) << 1))+#define RLDI_SH(sh) ((((sljit_ins)(sh) & 0x1f) << 11) | (((sljit_ins)(sh) & 0x20) >> 4))+#define RLDI_MB(mb) ((((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20))+#define RLDI_ME(me) RLDI_MB(me)++#define SLWI(shift) (RLWINM | RLWI_SH(shift) | RLWI_MBE(0, 31 - (shift)))+#define SLDI(shift) (RLDICR | RLDI_SH(shift) | RLDI_ME(63 - (shift)))+/* shift > 0 */+#define SRWI(shift) (RLWINM | RLWI_SH(32 - (shift)) | RLWI_MBE((shift), 31))+#define SRDI(shift) (RLDICL | RLDI_SH(64 - (shift)) | RLDI_MB(shift))++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+#define SLWI_W(shift) SLWI(shift)+#define TMP_MEM_OFFSET (2 * sizeof(sljit_sw))+#else /* !SLJIT_CONFIG_PPC_32 */+#define SLWI_W(shift) SLDI(shift)+#define TMP_MEM_OFFSET (6 * sizeof(sljit_sw))+#endif /* SLJIT_CONFIG_PPC_32 */++#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET)+#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET + sizeof(sljit_s32))+#define LWBRX_FIRST_REG S(TMP_REG1)+#define LWBRX_SECOND_REG S(dst)+#else /* !SLJIT_LITTLE_ENDIAN */+#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET + sizeof(sljit_s32))+#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET)+#define LWBRX_FIRST_REG S(dst)+#define LWBRX_SECOND_REG S(TMP_REG1)+#endif /* SLJIT_LITTLE_ENDIAN */++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func)+{+ sljit_uw* ptrs;++ if (func_ptr)+ *func_ptr = (void*)context;++ ptrs = (sljit_uw*)func;+ context->addr = addr ? addr : ptrs[0];+ context->r2 = ptrs[1];+ context->r11 = ptrs[2];+}+#endif++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);+ *ptr = ins;+ compiler->size++;+ return SLJIT_SUCCESS;+}++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;++#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))+ goto exit;+#else+ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ goto exit;+#endif++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->u.label != NULL);+ 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)+ if (jump->flags & IS_CALL)+ goto keep_address;+#endif++ diff = (sljit_sw)target_addr - (sljit_sw)code_ptr - executable_offset;++ if (jump->flags & IS_COND) {+ if (diff <= 0x7fff && diff >= -0x8000) {+ jump->flags |= PATCH_B;+ return code_ptr;+ }+ if (target_addr <= 0xffff) {+ jump->flags |= PATCH_B | PATCH_ABS_B;+ return code_ptr;+ }++ diff -= SSIZE_OF(ins);+ }++ if (diff <= 0x01ffffff && diff >= -0x02000000) {+ jump->flags |= PATCH_B;+ } else if (target_addr <= 0x01ffffff) {+ jump->flags |= PATCH_B | PATCH_ABS_B;+ }++ if (jump->flags & PATCH_B) {+ if (!(jump->flags & IS_COND))+ return code_ptr;++ code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);+ code_ptr[1] = Bx;+ jump->addr += sizeof(sljit_ins);+ jump->flags -= IS_COND;+ return code_ptr + 1;+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)+keep_address:+#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */+ if (target_addr < 0x80000000l) {+ jump->flags |= PATCH_ABS32;+ code_ptr[2] = MTCTR | S(TMP_CALL_REG);+ code_ptr[3] = code_ptr[0];+ return code_ptr + 3;+ }++ if (target_addr < 0x800000000000l) {+ jump->flags |= PATCH_ABS48;+ code_ptr[4] = MTCTR | S(TMP_CALL_REG);+ code_ptr[5] = code_ptr[0];+ return code_ptr + 5;+ }+#endif /* SLJIT_CONFIG_PPC_64 */++exit:+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ code_ptr[2] = MTCTR | S(TMP_CALL_REG);+ code_ptr[3] = code_ptr[0];+#else /* !SLJIT_CONFIG_PPC_32 */+ code_ptr[5] = MTCTR | S(TMP_CALL_REG);+ code_ptr[6] = code_ptr[0];+#endif /* SLJIT_CONFIG_PPC_32 */+ return code_ptr + JUMP_MAX_SIZE - 1;+}++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)++static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_uw addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_ASSERT(jump->flags < ((sljit_uw)5 << JUMP_SIZE_SHIFT));+ if (jump->flags & JUMP_ADDR)+ addr = jump->u.target;+ else+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ if (addr < 0x80000000l) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS32;+ return 1;+ }++ if (addr < 0x800000000000l) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS48;+ return 3;+ }++ SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));+ return 4;+}++#endif /* SLJIT_CONFIG_PPC_64 */++static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)+{+ sljit_uw flags = jump->flags;+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;+ sljit_ins *ins = (sljit_ins*)jump->addr;+ sljit_s32 reg;+ SLJIT_UNUSED_ARG(executable_offset);++ if (flags & PATCH_B) {+ if (flags & IS_COND) {+ if (!(flags & PATCH_ABS_B)) {+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);+ SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);+ ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | (ins[0] & 0x03ff0001);+ } else {+ SLJIT_ASSERT(addr <= 0xffff);+ ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*ins) & 0x03ff0001);+ }+ return;+ }++ if (!(flags & PATCH_ABS_B)) {+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);+ SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);+ ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | (ins[0] & 0x1);+ } else {+ SLJIT_ASSERT(addr <= 0x03ffffff);+ ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | (ins[0] & 0x1);+ }+ return;+ }++ reg = (flags & JUMP_MOV_ADDR) ? (sljit_s32)ins[0] : TMP_CALL_REG;++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);+ ins[1] = ORI | S(reg) | A(reg) | IMM(addr);+#else /* !SLJIT_CONFIG_PPC_32 */++ /* The TMP_ZERO cannot be used because it is restored for tail calls. */+ if (flags & PATCH_ABS32) {+ SLJIT_ASSERT(addr < 0x80000000l);+ ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);+ ins[1] = ORI | S(reg) | A(reg) | IMM(addr);+ return;+ }++ if (flags & PATCH_ABS48) {+ SLJIT_ASSERT(addr < 0x800000000000l);+ ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 32);+ ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 16);+ ins[2] = SLDI(16) | S(reg) | A(reg);+ ins[3] = ORI | S(reg) | A(reg) | IMM(addr);+ return;+ }++ ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 48);+ ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 32);+ ins[2] = SLDI(32) | S(reg) | A(reg);+ ins[3] = ORIS | S(reg) | A(reg) | IMM(addr >> 16);+ ins[4] = ORI | S(reg) | A(reg) | IMM(addr);+#endif /* SLJIT_CONFIG_PPC_32 */+}++static void reduce_code_size(struct sljit_compiler *compiler)+{+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_uw total_size;+ sljit_uw size_reduce = 0;+ sljit_sw diff;++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();++ while (1) {+ SLJIT_GET_NEXT_MIN();++ if (next_min_addr == SLJIT_MAX_ADDRESS)+ break;++ if (next_min_addr == next_label_size) {+ label->size -= size_reduce;++ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_const_addr) {+ const_->addr -= size_reduce;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ continue;+ }++ if (next_min_addr != next_jump_addr)+ continue;++ jump->addr -= size_reduce;+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ total_size = JUMP_MAX_SIZE - 1;++ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {+ if (jump->flags & JUMP_ADDR) {+ if (jump->u.target <= 0x01ffffff)+ total_size = 1 - 1;+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ else if (jump->u.target < 0x80000000l)+ total_size = 4 - 1;+ else if (jump->u.target < 0x800000000000l)+ total_size = 6 - 1;+#endif /* SLJIT_CONFIG_PPC_64 */+ } else {+ /* Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;++ if (jump->flags & IS_COND) {+ if (diff <= (0x7fff / SSIZE_OF(ins)) && diff >= (-0x8000 / SSIZE_OF(ins)))+ total_size = 1 - 1;+ else if ((diff - 1) <= (0x01ffffff / SSIZE_OF(ins)) && (diff - 1) >= (-0x02000000 / SSIZE_OF(ins)))+ total_size = 2 - 1;+ } else if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins)))+ total_size = 1 - 1;+ }+ }++ size_reduce += (JUMP_MAX_SIZE - 1) - total_size;+ jump->flags |= total_size << JUMP_SIZE_SHIFT;+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ } else {+ total_size = (sljit_uw)4 << JUMP_SIZE_SHIFT;++ if (jump->flags & JUMP_ADDR) {+ if (jump->u.target < 0x80000000l) {+ total_size = (sljit_uw)1 << JUMP_SIZE_SHIFT;+ size_reduce += 3;+ } else if (jump->u.target < 0x800000000000l) {+ total_size = (sljit_uw)3 << JUMP_SIZE_SHIFT;+ size_reduce += 1;+ }+ }+ jump->flags |= total_size;+#endif /* SLJIT_CONFIG_PPC_64 */+ }++ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ }++ compiler->size -= size_reduce;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_sw executable_offset;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));++ reduce_code_size(compiler);++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+ /* add to compiler->size additional instruction space to hold the trampoline and padding */+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));+#else+ compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));+#endif+#endif+ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);+ PTR_FAIL_WITH_EXEC_IF(code);++ reverse_buf(compiler);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();+ SLJIT_GET_NEXT_MIN();++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ *code_ptr = *buf_ptr++;+ if (next_min_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);++ /* These structures are ordered by their address. */+ if (next_min_addr == next_label_size) {+ /* Just recording the address. */+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_jump_addr) {+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ word_count += jump->flags >> JUMP_SIZE_SHIFT;+ jump->addr = (sljit_uw)code_ptr;+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);+ SLJIT_ASSERT(((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));+ } else {+ jump->addr = (sljit_uw)code_ptr;+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ word_count += jump->flags >> JUMP_SIZE_SHIFT;+ code_ptr += mov_addr_get_length(jump, code, executable_offset);+#else /* !SLJIT_CONFIG_PPC_64 */+ word_count++;+ code_ptr++;+#endif /* SLJIT_CONFIG_PPC_64 */+ }+ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ } else if (next_min_addr == next_const_addr) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ }++ SLJIT_GET_NEXT_MIN();+ }+ code_ptr++;+ word_count++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins))));+#else+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);+#endif++ jump = compiler->jumps;+ while (jump) {+ generate_jump_or_mov_addr(jump, executable_offset);+ jump = jump->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;++ 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_uw)code, (void*)sljit_generate_code);+#endif++ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ SLJIT_CACHE_FLUSH(code, code_ptr);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins) + sizeof(struct sljit_function_context);+ return code_ptr;+#else+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);+ 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) != 0;+#else+ /* Available by default. */+ return 1;+#endif+ case SLJIT_HAS_REV:+#if defined(_ARCH_PWR10) && _ARCH_PWR10+ return 1;+#else /* !POWER10 */+ return 2;+#endif /* POWER10 */+ /* A saved register is set to a zero value. */+ case SLJIT_HAS_ZERO_REGISTER:+ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_ROT:+ case SLJIT_HAS_PREFETCH:+ return 1;++ case SLJIT_HAS_CTZ:+ return 2;++ default:+ return 0;+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)+{+ switch (type) {+ case SLJIT_UNORDERED_OR_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_LESS:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER:+ case SLJIT_ORDERED_LESS_EQUAL:+ return 1;+ }++ return 0;+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++/* inp_flags: */++/* Creates an index in data_transfer_insts array. */+#define LOAD_DATA 0x01+#define INDEXED 0x02+#define SIGNED_DATA 0x04++#define WORD_DATA 0x00+#define BYTE_DATA 0x08+#define HALF_DATA 0x10+#define INT_DATA 0x18+/* Separates integer and floating point registers */+#define GPR_REG 0x1f+#define DOUBLE_DATA 0x20++#define MEM_MASK 0x7f++#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6))++/* Other inp_flags. */++/* Integer opertion and set flags -> requires exts on 64 bit systems. */+#define ALT_SIGN_EXT 0x000100+/* This flag affects the RC() and OERC() macros. */+#define ALT_SET_FLAGS 0x000400+#define ALT_FORM1 0x001000+#define ALT_FORM2 0x002000+#define ALT_FORM3 0x004000+#define ALT_FORM4 0x008000+#define ALT_FORM5 0x010000++/* Source and destination is register. */+#define REG_DEST 0x000001+#define REG1_SOURCE 0x000002+#define REG2_SOURCE 0x000004+/*+ALT_SIGN_EXT 0x000100+ALT_SET_FLAGS 0x000200+ALT_FORM1 0x001000+...+ALT_FORM5 0x010000 */++static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg);++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+#include "sljitNativePPC_32.c"+#else+#include "sljitNativePPC_64.c"+#endif++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+#define STACK_STORE STW+#define STACK_LOAD LWZ+#else+#define STACK_STORE STD+#define STACK_LOAD LD+#endif++#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)+#define LR_SAVE_OFFSET (2 * SSIZE_OF(sw))+#else+#define LR_SAVE_OFFSET SSIZE_OF(sw)+#endif++#define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 i, tmp, base, offset;+ sljit_s32 word_arg_count = 0;+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ sljit_s32 arg_count = 0;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0)+ + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);++ if (!(options & SLJIT_ENTER_REG_ARG))+ local_size += SSIZE_OF(sw);++ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;+ compiler->local_size = local_size;++ FAIL_IF(push_inst(compiler, MFLR | D(0)));++ base = SLJIT_SP;+ offset = local_size;++ if (local_size <= STACK_MAX_DISTANCE) {+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));+#else+ FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));+#endif+ } else {+ base = TMP_REG1;+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_SP) | A(TMP_REG1) | B(SLJIT_SP)));+ FAIL_IF(load_immediate(compiler, TMP_REG2, -local_size));+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));+#else+ FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));+#endif+ local_size = 0;+ offset = 0;+ }++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));+ }++ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));+ }++ if (!(options & SLJIT_ENTER_REG_ARG)) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));+ }++ tmp = SLJIT_S0 - saveds;+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));+ }++ FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));++ if (options & SLJIT_ENTER_REG_ARG)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));++ arg_types >>= SLJIT_ARG_SHIFT;+ saved_arg_count = 0;++ while (arg_types > 0) {+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ do {+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ tmp = SLJIT_S0 - saved_arg_count;+ saved_arg_count++;+ } else if (arg_count != word_arg_count)+ tmp = SLJIT_R0 + word_arg_count;+ else+ break;++ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + arg_count) | A(tmp) | B(SLJIT_R0 + arg_count)));+ } while (0);+#else+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + word_arg_count) | A(SLJIT_S0 - saved_arg_count) | B(SLJIT_R0 + word_arg_count)));+ saved_arg_count++;+ }+#endif+ word_arg_count++;+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ arg_count++;+#endif+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0)+ + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);++ if (!(options & SLJIT_ENTER_REG_ARG))+ local_size += SSIZE_OF(sw);++ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)+{+ sljit_s32 i, tmp, base, offset;+ sljit_s32 local_size = compiler->local_size;++ SLJIT_ASSERT(TMP_CALL_REG != TMP_REG2);++ base = SLJIT_SP;+ if (local_size > STACK_MAX_DISTANCE) {+ base = TMP_REG2;+ if (local_size > 2 * STACK_MAX_DISTANCE + LR_SAVE_OFFSET) {+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(base) | A(SLJIT_SP) | IMM(0)));+ local_size = 0;+ } else {+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(SLJIT_SP) | IMM(local_size - STACK_MAX_DISTANCE)));+ local_size = STACK_MAX_DISTANCE;+ }+ }++ offset = local_size;+ if (!is_return_to)+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET)));++ tmp = SLJIT_FS0 - compiler->fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));+ }++ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));+ }++ if (!(compiler->options & SLJIT_ENTER_REG_ARG)) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));+ }++ tmp = SLJIT_S0 - compiler->saveds;+ for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));+ }++ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));+ }++ if (!is_return_to)+ push_inst(compiler, MTLR | S(0));++ if (local_size > 0)+ return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size));++ SLJIT_ASSERT(base == TMP_REG2);+ return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base));+}++#undef STACK_STORE+#undef STACK_LOAD++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ FAIL_IF(emit_stack_frame_release(compiler, 0));+ return push_inst(compiler, BLR);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));+ src = TMP_CALL_REG;+ srcw = 0;+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));+ src = TMP_CALL_REG;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 1));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++/* s/l - store/load (1 bit)+ i/x - immediate/indexed form+ u/s - signed/unsigned (1 bit)+ w/b/h/i - word/byte/half/int allowed (2 bit)++ Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */++/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define INT_ALIGNED 0x10000+#endif++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+#define ARCH_32_64(a, b) a+#define INST_CODE_AND_DST(inst, flags, reg) \+ ((sljit_ins)(inst) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))+#else+#define ARCH_32_64(a, b) b+#define INST_CODE_AND_DST(inst, flags, reg) \+ (((sljit_ins)(inst) & ~(sljit_ins)INT_ALIGNED) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))+#endif++static const sljit_ins data_transfer_insts[64 + 16] = {++/* -------- Integer -------- */++/* Word. */++/* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),+/* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),+/* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),+/* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),++/* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),+/* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),+/* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),+/* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),++/* Byte. */++/* b u i s */ HI(38) /* stb */,+/* b u i l */ HI(34) /* lbz */,+/* b u x s */ HI(31) | LO(215) /* stbx */,+/* b u x l */ HI(31) | LO(87) /* lbzx */,++/* b s i s */ HI(38) /* stb */,+/* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,+/* b s x s */ HI(31) | LO(215) /* stbx */,+/* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,++/* Half. */++/* h u i s */ HI(44) /* sth */,+/* h u i l */ HI(40) /* lhz */,+/* h u x s */ HI(31) | LO(407) /* sthx */,+/* h u x l */ HI(31) | LO(279) /* lhzx */,++/* h s i s */ HI(44) /* sth */,+/* h s i l */ HI(42) /* lha */,+/* h s x s */ HI(31) | LO(407) /* sthx */,+/* h s x l */ HI(31) | LO(343) /* lhax */,++/* Int. */++/* i u i s */ HI(36) /* stw */,+/* i u i l */ HI(32) /* lwz */,+/* i u x s */ HI(31) | LO(151) /* stwx */,+/* i u x l */ HI(31) | LO(23) /* lwzx */,++/* i s i s */ HI(36) /* stw */,+/* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),+/* i s x s */ HI(31) | LO(151) /* stwx */,+/* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),++/* -------- Floating point -------- */++/* d i s */ HI(54) /* stfd */,+/* d i l */ HI(50) /* lfd */,+/* d x s */ HI(31) | LO(727) /* stfdx */,+/* d x l */ HI(31) | LO(599) /* lfdx */,++/* s i s */ HI(52) /* stfs */,+/* s i l */ HI(48) /* lfs */,+/* s x s */ HI(31) | LO(663) /* stfsx */,+/* s x l */ HI(31) | LO(535) /* lfsx */,+};++static const sljit_ins updated_data_transfer_insts[64] = {++/* -------- Integer -------- */++/* Word. */++/* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),+/* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),+/* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),+/* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),++/* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),+/* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),+/* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),+/* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),++/* Byte. */++/* b u i s */ HI(39) /* stbu */,+/* b u i l */ HI(35) /* lbzu */,+/* b u x s */ HI(31) | LO(247) /* stbux */,+/* b u x l */ HI(31) | LO(119) /* lbzux */,++/* b s i s */ HI(39) /* stbu */,+/* b s i l */ 0 /* no such instruction */,+/* b s x s */ HI(31) | LO(247) /* stbux */,+/* b s x l */ 0 /* no such instruction */,++/* Half. */++/* h u i s */ HI(45) /* sthu */,+/* h u i l */ HI(41) /* lhzu */,+/* h u x s */ HI(31) | LO(439) /* sthux */,+/* h u x l */ HI(31) | LO(311) /* lhzux */,++/* h s i s */ HI(45) /* sthu */,+/* h s i l */ HI(43) /* lhau */,+/* h s x s */ HI(31) | LO(439) /* sthux */,+/* h s x l */ HI(31) | LO(375) /* lhaux */,++/* Int. */++/* i u i s */ HI(37) /* stwu */,+/* i u i l */ HI(33) /* lwzu */,+/* i u x s */ HI(31) | LO(183) /* stwux */,+/* i u x l */ HI(31) | LO(55) /* lwzux */,++/* i s i s */ HI(37) /* stwu */,+/* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),+/* i s x s */ HI(31) | LO(183) /* stwux */,+/* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),++/* -------- Floating point -------- */++/* d i s */ HI(55) /* stfdu */,+/* d i l */ HI(51) /* lfdu */,+/* d x s */ HI(31) | LO(759) /* stfdux */,+/* d x l */ HI(31) | LO(631) /* lfdux */,++/* s i s */ HI(53) /* stfsu */,+/* s i l */ HI(49) /* lfsu */,+/* s x s */ HI(31) | LO(695) /* stfsux */,+/* s x l */ HI(31) | LO(567) /* lfsux */,+};++#undef ARCH_32_64++/* Simple cases, (no caching is required). */+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)+{+ sljit_ins inst;+ sljit_s32 offs_reg;++ /* Should work when (arg & REG_MASK) == 0. */+ SLJIT_ASSERT(A(0) == 0);+ SLJIT_ASSERT(arg & SLJIT_MEM);++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;+ offs_reg = OFFS_REG(arg);++ if (argw != 0) {+ FAIL_IF(push_inst(compiler, SLWI_W(argw) | S(OFFS_REG(arg)) | A(tmp_reg)));+ offs_reg = tmp_reg;+ }++ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ SLJIT_ASSERT(!(inst & INT_ALIGNED));+#endif /* SLJIT_CONFIG_PPC_64 */++ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));+ }++ inst = data_transfer_insts[inp_flags & MEM_MASK];+ arg &= REG_MASK;++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {+ FAIL_IF(load_immediate(compiler, tmp_reg, argw));++ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));+ }+#endif /* SLJIT_CONFIG_PPC_64 */++ if (argw <= SIMM_MAX && argw >= SIMM_MIN)+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {+#endif /* SLJIT_CONFIG_PPC_64 */+ FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM((argw + 0x8000) >> 16)));+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ }++ FAIL_IF(load_immediate(compiler, tmp_reg, argw));++ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));+#endif /* SLJIT_CONFIG_PPC_64 */+}++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+ result goes to TMP_REG2, so put result can use TMP_REG1. */+ sljit_s32 dst_r = TMP_REG2;+ sljit_s32 src1_r;+ sljit_s32 src2_r;+ sljit_s32 src2_tmp_reg = (!(input_flags & ALT_SIGN_EXT) && GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;+ sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);++ /* Destination check. */+ if (FAST_IS_REG(dst)) {+ dst_r = dst;+ /* The REG_DEST is only used by SLJIT_MOV operations, although+ * it is set for op2 operations with unset destination. */+ flags |= REG_DEST;++ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)+ src2_tmp_reg = dst_r;+ }++ /* Source 2. */+ if (FAST_IS_REG(src2)) {+ src2_r = src2;+ flags |= REG2_SOURCE;++ if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)+ dst_r = src2_r;+ } else if (src2 == SLJIT_IMM) {+ src2_r = TMP_ZERO;+ if (src2w != 0) {+ FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w));+ src2_r = src2_tmp_reg;+ }+ } else {+ FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, src2_tmp_reg, src2, src2w, TMP_REG1));+ src2_r = src2_tmp_reg;+ }++ /* Source 1. */+ if (FAST_IS_REG(src1)) {+ src1_r = src1;+ flags |= REG1_SOURCE;+ } else if (src1 == SLJIT_IMM) {+ src1_r = TMP_ZERO;+ if (src1w != 0) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));+ src1_r = TMP_REG1;+ }+ } else {+ FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));+ src1_r = TMP_REG1;+ }++ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;++ return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);+}++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_s32 int_op = op & SLJIT_32;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ case SLJIT_NOP:+ return push_inst(compiler, NOP);+ 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_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_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));+#endif+ 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_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_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_DIV_UW:+ case SLJIT_DIV_SW:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ 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_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));+#endif+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 mem, offs_reg, inp_flags;+ sljit_sw memw;+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ sljit_s32 is_32 = op & SLJIT_32;++ op = GET_OPCODE(op);+#endif /* SLJIT_CONFIG_PPC_64 */++ if (!((dst | src) & SLJIT_MEM)) {+ /* Both are registers. */+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {+ if (src == dst) {+ FAIL_IF(push_inst(compiler, RLWIMI | S(dst) | A(dst) | RLWI_SH(16) | RLWI_MBE(8, 15)));+ FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | RLWI_SH(24) | RLWI_MBE(16, 31)));+ } else {+ FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(dst) | RLWI_SH(8) | RLWI_MBE(16, 23)));+ FAIL_IF(push_inst(compiler, RLWIMI | S(src) | A(dst) | RLWI_SH(24) | RLWI_MBE(24, 31)));+ }++ if (op == SLJIT_REV_U16)+ return SLJIT_SUCCESS;+ return push_inst(compiler, EXTSH | S(dst) | A(dst));+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (!is_32) {+#if defined(_ARCH_PWR10) && _ARCH_PWR10+ return push_inst(compiler, BRD | S(src) | A(dst));+#else /* !POWER10 */+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_HI)));+ FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));+ FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_LO)));+ FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(SLJIT_SP) | B(TMP_REG2)));+ return push_inst(compiler, LD | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);+#endif /* POWER10 */+ }+#endif /* SLJIT_CONFIG_PPC_64 */++ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET)));+ FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));+ FAIL_IF(push_inst(compiler, LWZ | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET));++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (op == SLJIT_REV_S32)+ return push_inst(compiler, EXTSW | S(dst) | A(dst));+#endif /* SLJIT_CONFIG_PPC_64 */+ return SLJIT_SUCCESS;+ }++ mem = src;+ memw = srcw;++ if (dst & SLJIT_MEM) {+ mem = dst;+ memw = dstw;++ if (src & SLJIT_MEM) {+ inp_flags = HALF_DATA | LOAD_DATA;++ if (op != SLJIT_REV_U16 && op != SLJIT_REV_S16) {+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ inp_flags = (is_32 ? INT_DATA : WORD_DATA) | LOAD_DATA;+#else /* !SLJIT_CONFIG_PPC_64 */+ inp_flags = WORD_DATA | LOAD_DATA;+#endif /* SLJIT_CONFIG_PPC_64 */+ }++ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src, srcw, TMP_REG2));+ src = TMP_REG1;+ }+ }++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ offs_reg = OFFS_REG(mem);+ mem &= REG_MASK;+ memw &= 0x3;++ if (memw != 0) {+ FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(offs_reg) | A(TMP_REG2)));+ offs_reg = TMP_REG2;+ }+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ } else if (memw > 0x7fff7fffl || memw < -0x80000000l) {+ FAIL_IF(load_immediate(compiler, TMP_REG2, memw));+ offs_reg = TMP_REG2;+ mem &= REG_MASK;+#endif /* SLJIT_CONFIG_PPC_64 */+ } else {+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(mem & REG_MASK) | IMM(memw)));+ if (memw > SIMM_MAX || memw < SIMM_MIN)+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(TMP_REG2) | IMM((memw + 0x8000) >> 16)));++ mem = 0;+ offs_reg = TMP_REG2;+ }++ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {+ if (dst & SLJIT_MEM)+ return push_inst(compiler, STHBRX | S(src) | A(mem) | B(offs_reg));++ FAIL_IF(push_inst(compiler, LHBRX | S(dst) | A(mem) | B(offs_reg)));++ if (op == SLJIT_REV_U16)+ return SLJIT_SUCCESS;+ return push_inst(compiler, EXTSH | S(dst) | A(dst));+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (!is_32) {+ if (dst & SLJIT_MEM) {+#if defined(_ARCH_PWR7) && _ARCH_PWR7+ return push_inst(compiler, STDBRX | S(src) | A(mem) | B(offs_reg));+#else /* !POWER7 */+#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN+ FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));+ FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(offs_reg)));+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));+ return push_inst(compiler, STWBRX | S(src) | A(mem) | B(TMP_REG2));+#else /* !SLJIT_LITTLE_ENDIAN */+ FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg)));+ FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));+ return push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(TMP_REG2));+#endif /* SLJIT_LITTLE_ENDIAN */+#endif /* POWER7 */+ }+#if defined(_ARCH_PWR7) && _ARCH_PWR7+ return push_inst(compiler, LDBRX | S(dst) | A(mem) | B(offs_reg));+#else /* !POWER7 */+ FAIL_IF(push_inst(compiler, LWBRX | LWBRX_FIRST_REG | A(mem) | B(offs_reg)));+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));+ FAIL_IF(push_inst(compiler, LWBRX | LWBRX_SECOND_REG | A(mem) | B(TMP_REG2)));+ return push_inst(compiler, RLDIMI | S(TMP_REG1) | A(dst) | RLDI_SH(32) | RLDI_MB(0));+#endif /* POWER7 */+ }+#endif /* SLJIT_CONFIG_PPC_64 */++ if (dst & SLJIT_MEM)+ return push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg));++ FAIL_IF(push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg)));+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (op == SLJIT_REV_S32)+ return push_inst(compiler, EXTSW | S(dst) | A(dst));+#endif /* SLJIT_CONFIG_PPC_64 */+ return SLJIT_SUCCESS;+}++#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_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ 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);++ op = GET_OPCODE(op);++ if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));++ if (op <= SLJIT_MOV_P && 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_flags & SLJIT_32) {+ if (op <= SLJIT_MOV_P) {+ if (src & SLJIT_MEM) {+ if (op == SLJIT_MOV_S32)+ op = SLJIT_MOV_U32;+ }+ else if (src == SLJIT_IMM) {+ if (op == SLJIT_MOV_U32)+ op = SLJIT_MOV_S32;+ }+ }+ else {+ /* Most operations expect sign extended arguments. */+ flags |= INT_DATA | SIGNED_DATA;+ if (HAS_FLAGS(op_flags))+ flags |= ALT_SIGN_EXT;+ }+ }+#endif++ switch (op) {+ case SLJIT_MOV:+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+#endif+ case SLJIT_MOV_P:+ 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_U32:+ return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));++ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));+#endif++ case SLJIT_MOV_U8:+ return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));++ case SLJIT_MOV_S8:+ return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));++ case SLJIT_MOV_U16:+ return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));++ case SLJIT_MOV_S16:+ return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));++ case SLJIT_CLZ:+ case SLJIT_CTZ:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (op_flags & SLJIT_32)+ flags |= ALT_FORM1;+#endif /* SLJIT_CONFIG_PPC_64 */+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ op |= SLJIT_32;+#endif /* SLJIT_CONFIG_PPC_64 */+ /* fallthrough */+ case SLJIT_REV:+ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ op |= (op_flags & SLJIT_32);+#endif /* SLJIT_CONFIG_PPC_64 */+ return emit_rev(compiler, op, dst, dstw, src, srcw);+ }++ return SLJIT_SUCCESS;+}++#undef EMIT_MOV++/* Macros for checking different operand types / values. */+#define TEST_SL_IMM(src, srcw) \+ ((src) == SLJIT_IMM && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)+#define TEST_UL_IMM(src, srcw) \+ ((src) == SLJIT_IMM && !((srcw) & ~0xffff))+#define TEST_UH_IMM(src, srcw) \+ ((src) == SLJIT_IMM && !((srcw) & ~(sljit_sw)0xffff0000))++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define TEST_SH_IMM(src, srcw) \+ ((src) == SLJIT_IMM && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)+#define TEST_ADD_IMM(src, srcw) \+ ((src) == SLJIT_IMM && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)+#define TEST_UI_IMM(src, srcw) \+ ((src) == SLJIT_IMM && !((srcw) & ~0xffffffff))++#define TEST_ADD_FORM1(op) \+ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \+ || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY))+#define TEST_SUB_FORM2(op) \+ ((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \+ || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z))+#define TEST_SUB_FORM3(op) \+ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \+ || (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z))++#else /* !SLJIT_CONFIG_PPC_64 */+#define TEST_SH_IMM(src, srcw) \+ ((src) == SLJIT_IMM && !((srcw) & 0xffff))+#define TEST_ADD_IMM(src, srcw) \+ ((src) == SLJIT_IMM)+#define TEST_UI_IMM(src, srcw) \+ ((src) == SLJIT_IMM)++#define TEST_ADD_FORM1(op) \+ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)+#define TEST_SUB_FORM2(op) \+ (GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)+#define TEST_SUB_FORM3(op) \+ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)+#endif /* SLJIT_CONFIG_PPC_64 */++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_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (op & SLJIT_32) {+ /* Most operations expect sign extended arguments. */+ flags |= INT_DATA | SIGNED_DATA;+ if (src1 == SLJIT_IMM)+ src1w = (sljit_s32)(src1w);+ if (src2 == SLJIT_IMM)+ src2w = (sljit_s32)(src2w);+ if (HAS_FLAGS(op))+ flags |= ALT_SIGN_EXT;+ }+#endif+ if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;++ if (TEST_ADD_FORM1(op))+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);++ if (!HAS_FLAGS(op) && (src1 == SLJIT_IMM || src2 == SLJIT_IMM)) {+ if (TEST_SL_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)src2w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_SL_IMM(src1, src1w)) {+ compiler->imm = (sljit_ins)src1w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ if (TEST_SH_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;+ 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 = (sljit_ins)(src1w >> 16) & 0xffff;+ 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 = (sljit_ins)src2w & 0xffffffff;+ 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 = (sljit_ins)src1w & 0xffffffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if ((op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) {+ if (TEST_SL_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)src2w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_SL_IMM(src1, src1w)) {+ compiler->imm = (sljit_ins)src1w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);+ }+#endif+ if (HAS_FLAGS(op)) {+ if (TEST_SL_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)src2w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_SL_IMM(src1, src1w)) {+ compiler->imm = (sljit_ins)src1w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ }+ return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_ADDC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUB:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;++ if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {+ if (dst == TMP_REG1) {+ if (TEST_UL_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)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 = (sljit_ins)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 (dst == TMP_REG1 && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {+ if (TEST_SL_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)src2w & 0xffff;+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);+ }++ if (TEST_SUB_FORM2(op)) {+ if (src2 == SLJIT_IMM && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {+ compiler->imm = (sljit_ins)src2w & 0xffff;+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);+ }++ if (TEST_SUB_FORM3(op))+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);++ if (TEST_SL_IMM(src2, -src2w)) {+ compiler->imm = (sljit_ins)(-src2w) & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);+ }++ if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {+ compiler->imm = (sljit_ins)src1w & 0xffff;+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);+ }++ if (!HAS_FLAGS(op)) {+ if (TEST_SH_IMM(src2, -src2w)) {+ compiler->imm = (sljit_ins)((-src2w) >> 16) & 0xffff;+ 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 = (sljit_ins)-src2w;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ }++ /* We know ALT_SIGN_EXT is set if it is an SLJIT_32 on 64 bit systems. */+ return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUBC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ 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_32)+ flags |= ALT_FORM2;+#endif+ if (!HAS_FLAGS(op)) {+ if (TEST_SL_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)src2w & 0xffff;+ return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_SL_IMM(src1, src1w)) {+ compiler->imm = (sljit_ins)src1w & 0xffff;+ 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_XOR:+ if (src2 == SLJIT_IMM && src2w == -1) {+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src1, src1w);+ }+ if (src1 == SLJIT_IMM && src1w == -1) {+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src2, src2w);+ }+ /* fallthrough */+ case SLJIT_AND:+ case SLJIT_OR:+ /* Commutative unsigned operations. */+ if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {+ if (TEST_UL_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)src2w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_UL_IMM(src1, src1w)) {+ compiler->imm = (sljit_ins)src1w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ if (TEST_UH_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_UH_IMM(src1, src1w)) {+ compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ }+ if (!HAS_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {+ /* Unlike or and xor, the and resets unwanted bits as well. */+ if (TEST_UI_IMM(src2, src2w)) {+ compiler->imm = (sljit_ins)src2w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_UI_IMM(src1, src1w)) {+ compiler->imm = (sljit_ins)src1w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ }+ return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_MSHL:+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ case SLJIT_ROTL:+ case SLJIT_ROTR:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (op & SLJIT_32)+ flags |= ALT_FORM2;+#endif+ if (src2 == SLJIT_IMM) {+ compiler->imm = (sljit_ins)src2w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);+}++#undef TEST_ADD_FORM1+#undef TEST_SUB_FORM2+#undef TEST_SUB_FORM3++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));++ switch (GET_OPCODE(op)) {+ case SLJIT_MULADD:+ SLJIT_SKIP_CHECKS(compiler);+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));+ return push_inst(compiler, ADD | D(dst_reg) | A(dst_reg) | B(TMP_REG2));+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+ sljit_s32 is_right;+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;+#else /* !SLJIT_CONFIG_PPC_64 */+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;+ sljit_sw bit_length = 32;+#endif /* SLJIT_CONFIG_PPC_64 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));++ is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR);++ if (src1_reg == src2_reg) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);+ }++ ADJUST_LOCAL_OFFSET(src3, src3w);++ if (src3 == SLJIT_IMM) {+ src3w &= bit_length - 1;++ if (src3w == 0)+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (!(op & SLJIT_32)) {+ if (is_right) {+ FAIL_IF(push_inst(compiler, SRDI(src3w) | S(src1_reg) | A(dst_reg)));+ return push_inst(compiler, RLDIMI | S(src2_reg) | A(dst_reg) | RLDI_SH(64 - src3w) | RLDI_MB(0));+ }++ FAIL_IF(push_inst(compiler, SLDI(src3w) | S(src1_reg) | A(dst_reg)));+ /* Computes SRDI(64 - src2w). */+ FAIL_IF(push_inst(compiler, RLDICL | S(src2_reg) | A(TMP_REG1) | RLDI_SH(src3w) | RLDI_MB(64 - src3w)));+ return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));+ }+#endif /* SLJIT_CONFIG_PPC_64 */++ if (is_right) {+ FAIL_IF(push_inst(compiler, SRWI(src3w) | S(src1_reg) | A(dst_reg)));+ return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(32 - src3w) | RLWI_MBE(0, src3w - 1));+ }++ FAIL_IF(push_inst(compiler, SLWI(src3w) | S(src1_reg) | A(dst_reg)));+ return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(src3w) | RLWI_MBE(32 - src3w, 31));+ }++ if (src3 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w, TMP_REG2));+ src3 = TMP_REG2;+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (!(op & SLJIT_32)) {+ if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {+ FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x3f));+ src3 = TMP_REG2;+ }++ FAIL_IF(push_inst(compiler, (is_right ? SRD : SLD) | S(src1_reg) | A(dst_reg) | B(src3)));+ FAIL_IF(push_inst(compiler, (is_right ? SLDI(1) : SRDI(1)) | S(src2_reg) | A(TMP_REG1)));+ FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x3f));+ FAIL_IF(push_inst(compiler, (is_right ? SLD : SRD) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));+ return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));+ }+#endif /* SLJIT_CONFIG_PPC_64 */++ if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {+ FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x1f));+ src3 = TMP_REG2;+ }++ FAIL_IF(push_inst(compiler, (is_right ? SRW : SLW) | S(src1_reg) | A(dst_reg) | B(src3)));+ FAIL_IF(push_inst(compiler, (is_right ? SLWI(1) : SRWI(1)) | S(src2_reg) | A(TMP_REG1)));+ FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x1f));+ FAIL_IF(push_inst(compiler, (is_right ? SLW : SRW) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));+ return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));+}++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))+ 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)));++ FAIL_IF(push_inst(compiler, SLWI_W(srcw) | S(OFFS_REG(src)) | A(TMP_REG1)));+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, MTLR | S(src)));+ else {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG2));+ FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));+ }++ return push_inst(compiler, BLR);+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ return emit_prefetch(compiler, src, srcw);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ switch (op) {+ case SLJIT_FAST_ENTER:+ if (FAST_IS_REG(dst))+ return push_inst(compiler, MFLR | D(dst));++ FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG1)));+ break;+ case SLJIT_GET_RETURN_ADDRESS:+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + LR_SAVE_OFFSET, TMP_REG2));+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));++ if (type == SLJIT_GP_REGISTER)+ return reg_map[reg];++ if (type != SLJIT_FLOAT_REGISTER)+ return -1;++ return freg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+ SLJIT_UNUSED_ARG(size);++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double))++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. */+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));+ src = TMP_FREG1;+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ op = GET_OPCODE(op);+ FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));++ if (op == SLJIT_CONV_SW_FROM_F64) {+ if (FAST_IS_REG(dst)) {+ FAIL_IF(push_inst(compiler, STFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ return push_inst(compiler, LD | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);+ }+ return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);+ }+#else /* !SLJIT_CONFIG_PPC_64 */+ FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));+#endif /* SLJIT_CONFIG_PPC_64 */++ if (FAST_IS_REG(dst)) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));+ return push_inst(compiler, LWZ | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);+ }++ SLJIT_ASSERT(dst & SLJIT_MEM);++ if (dst & OFFS_REG_MASK) {+ dstw &= 0x3;+ if (dstw) {+ FAIL_IF(push_inst(compiler, SLWI_W(dstw) | S(OFFS_REG(dst)) | A(TMP_REG1)));+ dstw = TMP_REG1;+ } else+ dstw = OFFS_REG(dst);+ }+ else {+ if ((dst & REG_MASK) && !dstw) {+ dstw = dst & REG_MASK;+ dst = 0;+ } else {+ /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */+ FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));+ dstw = TMP_REG1;+ }+ }++ return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));+}++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_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));+ src2 = TMP_FREG2;+ }++ FAIL_IF(push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2)));++ switch (GET_FLAG_TYPE(op)) {+ case SLJIT_UNORDERED_OR_EQUAL:+ return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11));+ case SLJIT_UNORDERED_OR_LESS:+ return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11));+ case SLJIT_UNORDERED_OR_GREATER:+ return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11));+ }++ return SLJIT_SUCCESS;+}++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_s32 dst_r;++ CHECK_ERROR();++ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)+ op ^= SLJIT_32;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_CONV_F64_FROM_F32:+ op ^= SLJIT_32;+ if (op & SLJIT_32) {+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));+ break;+ }+ /* Fall through. */+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (!(dst & SLJIT_MEM))+ FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));+ break;+ }++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));+ return SLJIT_SUCCESS;+}++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_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG1));+ src2 = TMP_FREG2;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));+ break;+ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));+ break;+ 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_DIV_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));+ break;+ case SLJIT_COPYSIGN_F64:+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(src2) | A(SLJIT_SP) | TMP_MEM_OFFSET));+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ FAIL_IF(push_inst(compiler, LWZ | S(TMP_REG1) | A(SLJIT_SP) | ((op & SLJIT_32) ? TMP_MEM_OFFSET : TMP_MEM_OFFSET_HI)));+#else /* !SLJIT_CONFIG_PPC_32 */+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));+#endif /* SLJIT_CONFIG_PPC_32 */+ FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src1)));+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(TMP_REG1) | 0));+#else /* !SLJIT_CONFIG_PPC_32 */+ FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((op & SLJIT_32) ? 0 : 1)) | A(TMP_REG1) | 0));+#endif /* SLJIT_CONFIG_PPC_32 */+ FAIL_IF(push_inst(compiler, BCx | (4 << 21) | (0 << 16) | 8));+ return push_inst(compiler, FNEG | FD(dst_r) | FB(dst_r));+ }++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));++ return SLJIT_SUCCESS;+}++#undef SELECT_FOP++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+ union {+ sljit_s32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++ if (u.imm != 0)+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));++ FAIL_IF(push_inst(compiler, STW | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));+ return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)+{+ switch (type) {+ case SLJIT_NOT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)+ return (4 << 21) | (2 << 16);+ /* fallthrough */++ case SLJIT_EQUAL:+ return (12 << 21) | (2 << 16);++ case SLJIT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)+ return (12 << 21) | (2 << 16);+ /* fallthrough */++ case SLJIT_NOT_EQUAL:+ return (4 << 21) | (2 << 16);++ case SLJIT_LESS:+ 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_OVERFLOW:+ return (12 << 21) | (3 << 16);++ case SLJIT_NOT_OVERFLOW:+ return (4 << 21) | (3 << 16);++ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ case SLJIT_UNORDERED_OR_LESS:+ return (12 << 21) | ((4 + 0) << 16);++ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ return (4 << 21) | ((4 + 0) << 16);++ case SLJIT_F_GREATER:+ case SLJIT_ORDERED_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ return (12 << 21) | ((4 + 1) << 16);++ case SLJIT_F_LESS_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ return (4 << 21) | ((4 + 1) << 16);++ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ return (12 << 21) | ((4 + 2) << 16);++ case SLJIT_F_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ return (4 << 21) | ((4 + 2) << 16);++ case SLJIT_UNORDERED:+ return (12 << 21) | ((4 + 3) << 16);++ case SLJIT_ORDERED:+ return (4 << 21) | ((4 + 3) << 16);++ default:+ SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);+ return (20 << 21);+ }+}++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;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);+ if (!bo_bi_flags)+ return NULL;++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ if ((type | 0x1) == SLJIT_NOT_CARRY)+ PTR_FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG2) | A(TMP_ZERO) | B(TMP_ZERO)));++ /* In PPC, we don't need to touch the arguments. */+ if (type < SLJIT_JUMP)+ jump->flags |= IS_COND;+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)+ if (type >= SLJIT_CALL)+ jump->flags |= IS_CALL;+#endif++ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ SLJIT_UNUSED_ARG(arg_types);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));+#endif++ if (type & SLJIT_CALL_RETURN) {+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, type);+}++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_s32 src_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));++ if (src == SLJIT_IMM) {+ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR);+ jump->u.target = (sljit_uw)srcw;++#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)+ if (type >= SLJIT_CALL)+ jump->flags |= IS_CALL;+#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */++ jump->addr = compiler->size;+ FAIL_IF(push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0)));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return SLJIT_SUCCESS;+ }++ if (FAST_IS_REG(src)) {+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)+ if (type >= SLJIT_CALL && src != TMP_CALL_REG) {+ FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));+ src_r = TMP_CALL_REG;+ } else+ src_r = src;+#else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */+ src_r = src;+#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */+ } else {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));+ src_r = TMP_CALL_REG;+ }++ FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));+ return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(arg_types);++ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));+ src = TMP_CALL_REG;+ }++ if (type & SLJIT_CALL_RETURN) {+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));+ src = TMP_CALL_REG;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 0));+ type = SLJIT_JUMP;+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ FAIL_IF(call_with_args(compiler, arg_types, &src));+#endif++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+}++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_s32 reg, invert;+ sljit_u32 bit, from_xer;+ sljit_s32 saved_op = op;+ sljit_sw saved_dstw = dstw;+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ sljit_s32 input_flags = ((op & SLJIT_32) || op == SLJIT_MOV32) ? INT_DATA : WORD_DATA;+#else+ sljit_s32 input_flags = WORD_DATA;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+ reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;++ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))+ FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));++ invert = 0;+ bit = 0;+ from_xer = 0;++ switch (type) {+ case SLJIT_LESS:+ case SLJIT_SIG_LESS:+ break;++ case SLJIT_GREATER_EQUAL:+ case SLJIT_SIG_GREATER_EQUAL:+ invert = 1;+ break;++ case SLJIT_GREATER:+ case SLJIT_SIG_GREATER:+ bit = 1;+ break;++ case SLJIT_LESS_EQUAL:+ case SLJIT_SIG_LESS_EQUAL:+ bit = 1;+ invert = 1;+ break;++ case SLJIT_EQUAL:+ bit = 2;+ break;++ case SLJIT_NOT_EQUAL:+ bit = 2;+ invert = 1;+ break;++ case SLJIT_OVERFLOW:+ from_xer = 1;+ bit = 1;+ break;++ case SLJIT_NOT_OVERFLOW:+ from_xer = 1;+ bit = 1;+ invert = 1;+ break;++ case SLJIT_CARRY:+ from_xer = 1;+ bit = 2;+ invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB) != 0;+ break;++ case SLJIT_NOT_CARRY:+ from_xer = 1;+ bit = 2;+ invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0;+ break;++ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ case SLJIT_UNORDERED_OR_LESS:+ bit = 4 + 0;+ break;++ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ bit = 4 + 0;+ invert = 1;+ break;++ case SLJIT_F_GREATER:+ case SLJIT_ORDERED_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ bit = 4 + 1;+ break;++ case SLJIT_F_LESS_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ bit = 4 + 1;+ invert = 1;+ break;++ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ bit = 4 + 2;+ break;++ case SLJIT_F_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ bit = 4 + 2;+ invert = 1;+ break;++ case SLJIT_UNORDERED:+ bit = 4 + 3;+ break;++ case SLJIT_ORDERED:+ bit = 4 + 3;+ invert = 1;+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++ FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg)));+ /* Simplified mnemonics: extrwi. */+ FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | RLWI_SH(1 + bit) | RLWI_MBE(31, 31)));++ if (invert)+ FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));++ if (op < SLJIT_ADD) {+ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);+ }++ SLJIT_SKIP_CHECKS(compiler);++ 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_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+ sljit_ins *ptr;+ sljit_uw size;+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;+#else /* !SLJIT_CONFIG_PPC_64 */+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;+#endif /* SLJIT_CONFIG_PPC_64 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (dst_reg != src2_reg) {+ if (dst_reg == src1) {+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else {+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ FAIL_IF(push_inst(compiler, OR | S(dst_reg) | A(TMP_REG1) | B(dst_reg)));++ if ((src1 & REG_MASK) == dst_reg)+ src1 = (src1 & ~REG_MASK) | TMP_REG1;++ if (OFFS_REG(src1) == dst_reg)+ src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);+ }++ FAIL_IF(push_inst(compiler, OR | S(src2_reg) | A(dst_reg) | B(src2_reg)));+ }+ }++ if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)+ FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));++ size = compiler->size;++ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size++;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w, TMP_REG1));+ } else if (src1 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (type & SLJIT_32)+ src1w = (sljit_s32)src1w;+#endif /* SLJIT_CONFIG_RISCV_64 */+ FAIL_IF(load_immediate(compiler, dst_reg, src1w));+ } else+ FAIL_IF(push_inst(compiler, OR | S(src1) | A(dst_reg) | B(src1)));++ *ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+ sljit_ins *ptr;+ sljit_uw size;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (dst_freg != src2_freg) {+ if (dst_freg == src1) {+ src1 = src2_freg;+ src1w = 0;+ type ^= 0x1;+ } else+ FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src2_freg)));+ }++ if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)+ FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));++ size = compiler->size;++ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size++;++ if (src1 & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w, TMP_REG1));+ else+ FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src1)));++ *ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);+ return SLJIT_SUCCESS;+}++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)++#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \+ ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw))++#else /* !SLJIT_CONFIG_PPC_32 */++#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \+ ((((inst) & INT_ALIGNED) && ((memw) & 0x3) != 0) \+ || ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw)) \+ || ((memw) > 0x7fff7fffl || (memw) < -0x80000000l)) \++#endif /* SLJIT_CONFIG_PPC_32 */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (!(reg & REG_PAIR_MASK))+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);++ ADJUST_LOCAL_OFFSET(mem, memw);++ inst = data_transfer_insts[WORD_DATA | ((type & SLJIT_MEM_STORE) ? 0 : LOAD_DATA)];++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ memw &= 0x3;++ if (memw != 0) {+ FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(OFFS_REG(mem)) | A(TMP_REG1)));+ FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(TMP_REG1) | B(mem & REG_MASK)));+ } else+ FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(mem & REG_MASK) | B(OFFS_REG(mem))));++ mem = TMP_REG1;+ memw = 0;+ } else {+ if (EMIT_MEM_LOAD_IMM(inst, mem, memw)) {+ if ((mem & REG_MASK) != 0) {+ SLJIT_SKIP_CHECKS(compiler);+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_ADD, TMP_REG1, 0, mem & REG_MASK, 0, SLJIT_IMM, memw));+ } else+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw));++ memw = 0;+ mem = TMP_REG1;+ } else if (memw > SIMM_MAX || memw < SIMM_MIN) {+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(mem & REG_MASK) | IMM((memw + 0x8000) >> 16)));++ memw &= 0xffff;+ mem = TMP_REG1;+ } else {+ memw &= 0xffff;+ mem &= REG_MASK;+ }+ }++ SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw >= 0x8000 && memw <= 0xffff));++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ inst &= (sljit_ins)~INT_ALIGNED;+#endif /* SLJIT_CONFIG_PPC_64 */++ if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {+ FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw))));+ return push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw));+ }++ FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw)));+ return push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw)));+}++#undef EMIT_MEM_LOAD_IMM++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 mem_flags;+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));++ if (type & SLJIT_MEM_POST)+ return SLJIT_ERR_UNSUPPORTED;++ switch (type & 0xff) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+#endif+ mem_flags = WORD_DATA;+ break;++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ case SLJIT_MOV_U32:+ case SLJIT_MOV32:+ mem_flags = INT_DATA;+ break;++ case SLJIT_MOV_S32:+ mem_flags = INT_DATA;++ if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_32)) {+ if (mem & OFFS_REG_MASK)+ mem_flags |= SIGNED_DATA;+ else+ return SLJIT_ERR_UNSUPPORTED;+ }+ break;+#endif++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ mem_flags = BYTE_DATA;+ break;++ case SLJIT_MOV_U16:+ mem_flags = HALF_DATA;+ break;++ case SLJIT_MOV_S16:+ mem_flags = HALF_DATA | SIGNED_DATA;+ break;++ default:+ SLJIT_UNREACHABLE();+ mem_flags = WORD_DATA;+ break;+ }++ if (!(type & SLJIT_MEM_STORE))+ mem_flags |= LOAD_DATA;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ if (memw != 0)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ inst = updated_data_transfer_insts[mem_flags | INDEXED];+ FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));+ }+ else {+ if (memw > SIMM_MAX || memw < SIMM_MIN)+ return SLJIT_ERR_UNSUPPORTED;++ inst = updated_data_transfer_insts[mem_flags];++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)+ return SLJIT_ERR_UNSUPPORTED;+#endif++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));+ }++ if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)+ return push_inst(compiler, EXTSB | S(reg) | A(reg));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 mem_flags;+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));++ if (type & SLJIT_MEM_POST)+ return SLJIT_ERR_UNSUPPORTED;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ if (memw != 0)+ return SLJIT_ERR_UNSUPPORTED;+ }+ else {+ if (memw > SIMM_MAX || memw < SIMM_MIN)+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ mem_flags = FLOAT_DATA(type);++ if (!(type & SLJIT_MEM_STORE))+ mem_flags |= LOAD_DATA;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ inst = updated_data_transfer_insts[mem_flags | INDEXED];+ return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));+ }++ inst = updated_data_transfer_insts[mem_flags];+ return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ compiler->size++;+#else+ compiler->size += 4;+#endif++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset); }
+ src/c/pcre2/src/sljit/sljitNativeRISCV_32.c view
@@ -0,0 +1,142 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)+{+ SLJIT_UNUSED_ARG(tmp_r);++ if (imm <= SIMM_MAX && imm >= SIMM_MIN)+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));++ if (imm & 0x800)+ imm += 0x1000;++ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));++ if ((imm & 0xfff) == 0)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ union {+ sljit_s32 imm[2];+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ if (u.imm[0] != 0)+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0], TMP_REG3));+ if (u.imm[1] != 0)+ FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1], TMP_REG3));++ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16)));+ FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | (8 << 7)));+ FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | (12 << 7)));+ FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8)));+ return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_ins inst;+ sljit_s32 reg2 = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ if (op & SLJIT_32) {+ if (op == SLJIT_COPY32_TO_F32)+ inst = FMV_W_X | RS1(reg) | FRD(freg);+ else+ inst = FMV_X_W | FRS1(freg) | RD(reg);++ return push_inst(compiler, inst);+ }++ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16)));++ if (reg & REG_PAIR_MASK) {+ reg2 = REG_PAIR_SECOND(reg);+ reg = REG_PAIR_FIRST(reg);+ }++ if (op == SLJIT_COPY_TO_F64) {+ if (reg2 != 0)+ FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg2) | (8 << 7)));+ else+ FAIL_IF(push_inst(compiler, FSW | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7)));++ FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg) | (12 << 7)));+ FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8)));+ } else {+ FAIL_IF(push_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7)));++ if (reg2 != 0)+ FAIL_IF(push_inst(compiler, FMV_X_W | FRS1(freg) | RD(reg2)));++ FAIL_IF(push_inst(compiler, LW | RD(reg) | RS1(SLJIT_SP) | IMM_I(12)));+ }++ return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16));+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)+{+ if ((init_value & 0x800) != 0)+ init_value += 0x1000;++ FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff)));+ return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value));+}++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_UNUSED_ARG(executable_offset);++ if ((new_target & 0x800) != 0)+ new_target += 0x1000;++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);++ SLJIT_ASSERT((inst[0] & 0x7f) == LUI);+ inst[0] = (inst[0] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff);+ SLJIT_ASSERT((inst[1] & 0x707f) == ADDI || (inst[1] & 0x707f) == JALR);+ inst[1] = (inst[1] & 0xfffff) | IMM_I(new_target);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 5);+}
+ src/c/pcre2/src/sljit/sljitNativeRISCV_64.c view
@@ -0,0 +1,222 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)+{+ sljit_sw high;++ if (imm <= SIMM_MAX && imm >= SIMM_MIN)+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));++ if (imm <= 0x7fffffffl && imm >= S32_MIN) {+ if (imm > S32_MAX) {+ SLJIT_ASSERT((imm & 0x800) != 0);+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));+ return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));+ }++ if ((imm & 0x800) != 0)+ imm += 0x1000;++ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));++ if ((imm & 0xfff) == 0)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));+ }++ /* Trailing zeroes could be used to produce shifted immediates. */++ if (imm <= 0x7ffffffffffl && imm >= -0x80000000000l) {+ high = imm >> 12;++ if (imm & 0x800)+ high = ~high;++ if (high > S32_MAX) {+ SLJIT_ASSERT((high & 0x800) != 0);+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));+ FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(high)));+ } else {+ if ((high & 0x800) != 0)+ high += 0x1000;++ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(high & ~0xfff)));++ if ((high & 0xfff) != 0)+ FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(high)));+ }++ FAIL_IF(push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(12)));++ if ((imm & 0xfff) != 0)+ return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));++ return SLJIT_SUCCESS;+ }++ SLJIT_ASSERT(dst_r != tmp_r);++ high = imm >> 32;+ imm = (sljit_s32)imm;++ if ((imm & 0x80000000l) != 0)+ high = ~high;++ if (high <= 0x7ffff && high >= -0x80000) {+ FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high << 12)));+ high = 0x1000;+ } else {+ if ((high & 0x800) != 0)+ high += 0x1000;++ FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high & ~0xfff)));+ high &= 0xfff;+ }++ if (imm <= SIMM_MAX && imm >= SIMM_MIN) {+ FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)));+ imm = 0;+ } else if (imm > S32_MAX) {+ SLJIT_ASSERT((imm & 0x800) != 0);++ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));+ imm = 0x1000 | (imm & 0xfff);+ } else {+ if ((imm & 0x800) != 0)+ imm += 0x1000;++ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));+ imm &= 0xfff;+ }++ if ((high & 0xfff) != 0)+ FAIL_IF(push_inst(compiler, ADDI | RD(tmp_r) | RS1(tmp_r) | IMM_I(high)));++ if (imm & 0x1000)+ FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));+ else if (imm != 0)+ FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));++ FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(tmp_r) | IMM_I((high & 0x1000) ? 20 : 32)));+ return push_inst(compiler, XOR | RD(dst_r) | RS1(dst_r) | RS2(tmp_r));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ union {+ sljit_sw imm;+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ if (u.imm == 0)+ return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_ZERO) | FRD(freg));++ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3));+ return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_REG1) | FRD(freg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)+ inst = FMV_W_X | RS1(reg) | FRD(freg);+ else+ inst = FMV_X_W | FRS1(freg) | RD(reg);++ if (!(op & SLJIT_32))+ inst |= (sljit_ins)1 << 25;++ return push_inst(compiler, inst);+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)+{+ sljit_sw high;++ if ((init_value & 0x800) != 0)+ init_value += 0x1000;++ high = init_value >> 32;++ if ((init_value & 0x80000000l) != 0)+ high = ~high;++ if ((high & 0x800) != 0)+ high += 0x1000;++ FAIL_IF(push_inst(compiler, LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff)));+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high)));+ FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff)));+ FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(32)));+ FAIL_IF(push_inst(compiler, XOR | RD(dst) | RS1(dst) | RS2(TMP_REG3)));+ return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value));+}++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_sw high;+ SLJIT_UNUSED_ARG(executable_offset);++ if ((new_target & 0x800) != 0)+ new_target += 0x1000;++ high = (sljit_sw)new_target >> 32;++ if ((new_target & 0x80000000l) != 0)+ high = ~high;++ if ((high & 0x800) != 0)+ high += 0x1000;++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);++ SLJIT_ASSERT((inst[0] & 0x7f) == LUI);+ inst[0] = (inst[0] & 0xfff) | (sljit_ins)(high & ~0xfff);+ SLJIT_ASSERT((inst[1] & 0x707f) == ADDI);+ inst[1] = (inst[1] & 0xfffff) | IMM_I(high);+ SLJIT_ASSERT((inst[2] & 0x7f) == LUI);+ inst[2] = (inst[2] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff);+ SLJIT_ASSERT((inst[5] & 0x707f) == ADDI || (inst[5] & 0x707f) == JALR);+ inst[5] = (inst[5] & 0xfffff) | IMM_I(new_target);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);++ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 5);+}
+ src/c/pcre2/src/sljit/sljitNativeRISCV_common.c view
@@ -0,0 +1,3121 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ return "RISC-V-32" SLJIT_CPUINFO;+#else /* !SLJIT_CONFIG_RISCV_32 */+ return "RISC-V-64" SLJIT_CPUINFO;+#endif /* SLJIT_CONFIG_RISCV_32 */+}++/* Length of an instruction word+ Both for riscv-32 and riscv-64 */+typedef sljit_u32 sljit_ins;++#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_ZERO 0++/* Flags are kept in volatile registers. */+#define EQUAL_FLAG (SLJIT_NUMBER_OF_REGISTERS + 5)+#define RETURN_ADDR_REG TMP_REG2+#define OTHER_FLAG (SLJIT_NUMBER_OF_REGISTERS + 6)++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {+ 0, 10, 11, 12, 13, 14, 15, 16, 17, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 2, 6, 1, 7, 5, 28+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {+ 0, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 28, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 0, 1,+};++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++#define RD(rd) ((sljit_ins)reg_map[rd] << 7)+#define RS1(rs1) ((sljit_ins)reg_map[rs1] << 15)+#define RS2(rs2) ((sljit_ins)reg_map[rs2] << 20)+#define FRD(rd) ((sljit_ins)freg_map[rd] << 7)+#define FRS1(rs1) ((sljit_ins)freg_map[rs1] << 15)+#define FRS2(rs2) ((sljit_ins)freg_map[rs2] << 20)+#define IMM_I(imm) ((sljit_ins)(imm) << 20)+#define IMM_S(imm) ((((sljit_ins)(imm) & 0xfe0) << 20) | (((sljit_ins)(imm) & 0x1f) << 7))++/* Represents funct(i) parts of the instructions. */+#define OPC(o) ((sljit_ins)(o))+#define F3(f) ((sljit_ins)(f) << 12)+#define F12(f) ((sljit_ins)(f) << 20)+#define F7(f) ((sljit_ins)(f) << 25)++#define ADD (F7(0x0) | F3(0x0) | OPC(0x33))+#define ADDI (F3(0x0) | OPC(0x13))+#define AND (F7(0x0) | F3(0x7) | OPC(0x33))+#define ANDI (F3(0x7) | OPC(0x13))+#define AUIPC (OPC(0x17))+#define BEQ (F3(0x0) | OPC(0x63))+#define BNE (F3(0x1) | OPC(0x63))+#define BLT (F3(0x4) | OPC(0x63))+#define BGE (F3(0x5) | OPC(0x63))+#define BLTU (F3(0x6) | OPC(0x63))+#define BGEU (F3(0x7) | OPC(0x63))+#define DIV (F7(0x1) | F3(0x4) | OPC(0x33))+#define DIVU (F7(0x1) | F3(0x5) | OPC(0x33))+#define EBREAK (F12(0x1) | F3(0x0) | OPC(0x73))+#define FADD_S (F7(0x0) | F3(0x7) | OPC(0x53))+#define FDIV_S (F7(0xc) | F3(0x7) | OPC(0x53))+#define FEQ_S (F7(0x50) | F3(0x2) | OPC(0x53))+#define FLD (F3(0x3) | OPC(0x7))+#define FLE_S (F7(0x50) | F3(0x0) | OPC(0x53))+#define FLT_S (F7(0x50) | F3(0x1) | OPC(0x53))+/* These conversion opcodes are partly defined. */+#define FCVT_S_D (F7(0x20) | OPC(0x53))+#define FCVT_S_W (F7(0x68) | OPC(0x53))+#define FCVT_S_WU (F7(0x68) | F12(0x1) | OPC(0x53))+#define FCVT_W_S (F7(0x60) | F3(0x1) | OPC(0x53))+#define FMUL_S (F7(0x8) | F3(0x7) | OPC(0x53))+#define FMV_X_W (F7(0x70) | F3(0x0) | OPC(0x53))+#define FMV_W_X (F7(0x78) | F3(0x0) | OPC(0x53))+#define FSD (F3(0x3) | OPC(0x27))+#define FSGNJ_S (F7(0x10) | F3(0x0) | OPC(0x53))+#define FSGNJN_S (F7(0x10) | F3(0x1) | OPC(0x53))+#define FSGNJX_S (F7(0x10) | F3(0x2) | OPC(0x53))+#define FSUB_S (F7(0x4) | F3(0x7) | OPC(0x53))+#define FSW (F3(0x2) | OPC(0x27))+#define JAL (OPC(0x6f))+#define JALR (F3(0x0) | OPC(0x67))+#define LD (F3(0x3) | OPC(0x3))+#define LUI (OPC(0x37))+#define LW (F3(0x2) | OPC(0x3))+#define MUL (F7(0x1) | F3(0x0) | OPC(0x33))+#define MULH (F7(0x1) | F3(0x1) | OPC(0x33))+#define MULHU (F7(0x1) | F3(0x3) | OPC(0x33))+#define OR (F7(0x0) | F3(0x6) | OPC(0x33))+#define ORI (F3(0x6) | OPC(0x13))+#define REM (F7(0x1) | F3(0x6) | OPC(0x33))+#define REMU (F7(0x1) | F3(0x7) | OPC(0x33))+#define SD (F3(0x3) | OPC(0x23))+#define SLL (F7(0x0) | F3(0x1) | OPC(0x33))+#define SLLI (IMM_I(0x0) | F3(0x1) | OPC(0x13))+#define SLT (F7(0x0) | F3(0x2) | OPC(0x33))+#define SLTI (F3(0x2) | OPC(0x13))+#define SLTU (F7(0x0) | F3(0x3) | OPC(0x33))+#define SLTUI (F3(0x3) | OPC(0x13))+#define SRL (F7(0x0) | F3(0x5) | OPC(0x33))+#define SRLI (IMM_I(0x0) | F3(0x5) | OPC(0x13))+#define SRA (F7(0x20) | F3(0x5) | OPC(0x33))+#define SRAI (IMM_I(0x400) | F3(0x5) | OPC(0x13))+#define SUB (F7(0x20) | F3(0x0) | OPC(0x33))+#define SW (F3(0x2) | OPC(0x23))+#define XOR (F7(0x0) | F3(0x4) | OPC(0x33))+#define XORI (F3(0x4) | OPC(0x13))++#define SIMM_MAX (0x7ff)+#define SIMM_MIN (-0x800)+#define BRANCH_MAX (0xfff)+#define BRANCH_MIN (-0x1000)+#define JUMP_MAX (0xfffff)+#define JUMP_MIN (-0x100000)++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+#define S32_MAX (0x7ffff7ffl)+#define S32_MIN (-0x80000000l)+#define S44_MAX (0x7fffffff7ffl)+#define S52_MAX (0x7ffffffffffffl)+#endif++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);+ *ptr = ins;+ compiler->size++;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_imm_s_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_sw imm)+{+ return push_inst(compiler, ins | IMM_S(imm));+}++static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_sw diff;+ sljit_uw target_addr;+ sljit_ins *inst;++ inst = (sljit_ins *)jump->addr;++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ goto exit;++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->u.label != NULL);+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;+ }++ diff = (sljit_sw)target_addr - (sljit_sw)inst - executable_offset;++ if (jump->flags & IS_COND) {+ diff += SSIZE_OF(ins);++ if (diff >= BRANCH_MIN && diff <= BRANCH_MAX) {+ inst--;+ inst[0] = (inst[0] & 0x1fff07f) ^ 0x1000;+ jump->flags |= PATCH_B;+ jump->addr = (sljit_uw)inst;+ return inst;+ }++ diff -= SSIZE_OF(ins);+ }++ if (diff >= JUMP_MIN && diff <= JUMP_MAX) {+ if (jump->flags & IS_COND) {+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;+#else+ inst[-1] -= (sljit_ins)(5 * sizeof(sljit_ins)) << 7;+#endif+ }++ jump->flags |= PATCH_J;+ return inst;+ }++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (diff >= S32_MIN && diff <= S32_MAX) {+ if (jump->flags & IS_COND)+ inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;++ jump->flags |= PATCH_REL32;+ inst[1] = inst[0];+ return inst + 1;+ }++ if (target_addr <= (sljit_uw)S32_MAX) {+ if (jump->flags & IS_COND)+ inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;++ jump->flags |= PATCH_ABS32;+ inst[1] = inst[0];+ return inst + 1;+ }++ if (target_addr <= S44_MAX) {+ if (jump->flags & IS_COND)+ inst[-1] -= (sljit_ins)(2 * sizeof(sljit_ins)) << 7;++ jump->flags |= PATCH_ABS44;+ inst[3] = inst[0];+ return inst + 3;+ }++ if (target_addr <= S52_MAX) {+ if (jump->flags & IS_COND)+ inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;++ jump->flags |= PATCH_ABS52;+ inst[4] = inst[0];+ return inst + 4;+ }+#endif++exit:+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ inst[1] = inst[0];+ return inst + 1;+#else+ inst[5] = inst[0];+ return inst + 5;+#endif+}++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)++static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_uw addr;+ sljit_sw diff;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT));+ if (jump->flags & JUMP_ADDR)+ addr = jump->u.target;+ else+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ if (diff >= S32_MIN && diff <= S32_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_REL32;+ return 1;+ }++ if (addr <= S32_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS32;+ return 1;+ }++ if (addr <= S44_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS44;+ return 3;+ }++ if (addr <= S52_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS52;+ return 4;+ }++ SLJIT_ASSERT(jump->flags >= ((sljit_uw)5 << JUMP_SIZE_SHIFT));+ return 5;+}++#endif /* SLJIT_CONFIG_RISCV_64 */++static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw executable_offset)+{+ sljit_uw flags = jump->flags;+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;+ sljit_ins *ins = (sljit_ins*)jump->addr;+ sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : TMP_REG1;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_sw high;+#endif+ SLJIT_UNUSED_ARG(executable_offset);++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (flags & PATCH_REL32) {+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);++ SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX);++ if ((addr & 0x800) != 0)+ addr += 0x1000;++ ins[0] = AUIPC | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);++ if (!(flags & JUMP_MOV_ADDR)) {+ SLJIT_ASSERT((ins[1] & 0x707f) == JALR);+ ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);+ } else+ ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);+ return;+ }+#endif++ if ((addr & 0x800) != 0)+ addr += 0x1000;++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);+#else /* !SLJIT_CONFIG_RISCV_32 */++ if (flags & PATCH_ABS32) {+ SLJIT_ASSERT(addr <= S32_MAX);+ ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);+ } else if (flags & PATCH_ABS44) {+ high = (sljit_sw)addr >> 12;+ SLJIT_ASSERT((sljit_uw)high <= 0x7fffffff);++ if (high > S32_MAX) {+ SLJIT_ASSERT((high & 0x800) != 0);+ ins[0] = LUI | RD(reg) | (sljit_ins)0x80000000u;+ ins[1] = XORI | RD(reg) | RS1(reg) | IMM_I(high);+ } else {+ if ((high & 0x800) != 0)+ high += 0x1000;++ ins[0] = LUI | RD(reg) | (sljit_ins)(high & ~0xfff);+ ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(high);+ }++ ins[2] = SLLI | RD(reg) | RS1(reg) | IMM_I(12);+ ins += 2;+ } else {+ high = (sljit_sw)addr >> 32;++ if ((addr & 0x80000000l) != 0)+ high = ~high;++ if (flags & PATCH_ABS52) {+ SLJIT_ASSERT(addr <= S52_MAX);+ ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12);+ } else {+ if ((high & 0x800) != 0)+ high += 0x1000;+ ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff);+ ins[1] = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high);+ ins++;+ }++ ins[1] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);+ ins[2] = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32);+ ins[3] = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3);+ ins += 3;+ }+#endif /* !SLJIT_CONFIG_RISCV_32 */++ if (!(flags & JUMP_MOV_ADDR)) {+ SLJIT_ASSERT((ins[1] & 0x707f) == JALR);+ ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);+ } else+ ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);+}++static void reduce_code_size(struct sljit_compiler *compiler)+{+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_uw total_size;+ sljit_uw size_reduce = 0;+ sljit_sw diff;++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();++ while (1) {+ SLJIT_GET_NEXT_MIN();++ if (next_min_addr == SLJIT_MAX_ADDRESS)+ break;++ if (next_min_addr == next_label_size) {+ label->size -= size_reduce;++ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_const_addr) {+ const_->addr -= size_reduce;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ continue;+ }++ if (next_min_addr != next_jump_addr)+ continue;++ jump->addr -= size_reduce;+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ total_size = JUMP_MAX_SIZE;++ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {+ if (jump->flags & JUMP_ADDR) {+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (jump->u.target <= S32_MAX)+ total_size = 2;+ else if (jump->u.target <= S44_MAX)+ total_size = 4;+ else if (jump->u.target <= S52_MAX)+ total_size = 5;+#endif /* SLJIT_CONFIG_RISCV_64 */+ } else {+ /* Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;++ if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH_MIN / SSIZE_OF(ins)))+ total_size = 0;+ else if (diff >= (JUMP_MIN / SSIZE_OF(ins)) && diff <= (JUMP_MAX / SSIZE_OF(ins)))+ total_size = 1;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ else if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))+ total_size = 2;+#endif /* SLJIT_CONFIG_RISCV_64 */+ }+ }++ size_reduce += JUMP_MAX_SIZE - total_size;+ jump->flags |= total_size << JUMP_SIZE_SHIFT;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ } else {+ total_size = 5;++ if (!(jump->flags & JUMP_ADDR)) {+ /* Real size minus 1. Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;++ if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))+ total_size = 1;+ } else if (jump->u.target < S32_MAX)+ total_size = 1;+ else if (jump->u.target < S44_MAX)+ total_size = 3;+ else if (jump->u.target <= S52_MAX)+ total_size = 4;++ size_reduce += 5 - total_size;+ jump->flags |= total_size << JUMP_SIZE_SHIFT;+#endif /* !SLJIT_CONFIG_RISCV_64 */+ }++ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ }++ compiler->size -= size_reduce;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_sw executable_offset;+ sljit_uw addr;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));++ reduce_code_size(compiler);++ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);+ PTR_FAIL_WITH_EXEC_IF(code);++ reverse_buf(compiler);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();+ SLJIT_GET_NEXT_MIN();++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ *code_ptr = *buf_ptr++;+ if (next_min_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);++ /* These structures are ordered by their address. */+ if (next_min_addr == next_label_size) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_jump_addr) {+ if (!(jump->flags & JUMP_MOV_ADDR)) {+ word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);+ jump->addr = (sljit_uw)code_ptr;+ code_ptr = detect_jump_type(jump, code, executable_offset);+ SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));+ } else {+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ word_count += 1;+ jump->addr = (sljit_uw)code_ptr;+ code_ptr += 1;+#else /* !SLJIT_CONFIG_RISCV_32 */+ word_count += jump->flags >> JUMP_SIZE_SHIFT;+ addr = (sljit_uw)code_ptr;+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);+ jump->addr = addr;+#endif /* SLJIT_CONFIG_RISCV_32 */+ }+ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ } else if (next_min_addr == next_const_addr) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ }++ SLJIT_GET_NEXT_MIN();+ }+ code_ptr++;+ word_count++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->u.addr = (sljit_uw)code_ptr;+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ do {+ if (!(jump->flags & (PATCH_B | PATCH_J)) || (jump->flags & JUMP_MOV_ADDR)) {+ load_addr_to_reg(jump, executable_offset);+ break;+ }++ addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;+ buf_ptr = (sljit_ins *)jump->addr;+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);++ if (jump->flags & PATCH_B) {+ SLJIT_ASSERT((sljit_sw)addr >= BRANCH_MIN && (sljit_sw)addr <= BRANCH_MAX);+ addr = ((addr & 0x800) >> 4) | ((addr & 0x1e) << 7) | ((addr & 0x7e0) << 20) | ((addr & 0x1000) << 19);+ buf_ptr[0] |= (sljit_ins)addr;+ break;+ }++ SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX);+ addr = (addr & 0xff000) | ((addr & 0x800) << 9) | ((addr & 0x7fe) << 20) | ((addr & 0x100000) << 11);+ buf_ptr[0] = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr;+ } while (0);++ jump = jump->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (sljit_uw)(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);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ 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) != 0;+#elif defined(__riscv_float_abi_soft)+ return 0;+#else+ return 1;+#endif /* SLJIT_IS_FPU_AVAILABLE */+ case SLJIT_HAS_ZERO_REGISTER:+ case SLJIT_HAS_COPY_F32:+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ case SLJIT_HAS_COPY_F64:+#endif /* !SLJIT_CONFIG_RISCV_64 */+ return 1;+ default:+ return 0;+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)+{+ switch (type) {+ case SLJIT_UNORDERED_OR_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ return 2;++ case SLJIT_UNORDERED:+ case SLJIT_ORDERED:+ return 1;+ }++ return 0;+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++/* Creates an index in data_transfer_insts array. */+#define LOAD_DATA 0x01+#define WORD_DATA 0x00+#define BYTE_DATA 0x02+#define HALF_DATA 0x04+#define INT_DATA 0x06+#define SIGNED_DATA 0x08+/* Separates integer and floating point registers */+#define GPR_REG 0x0f+#define DOUBLE_DATA 0x10+#define SINGLE_DATA 0x12++#define MEM_MASK 0x1f++#define ARG_TEST 0x00020+#define ALT_KEEP_CACHE 0x00040+#define CUMULATIVE_OP 0x00080+#define IMM_OP 0x00100+#define MOVE_OP 0x00200+#define SRC2_IMM 0x00400++#define UNUSED_DEST 0x00800+#define REG_DEST 0x01000+#define REG1_SOURCE 0x02000+#define REG2_SOURCE 0x04000+#define SLOW_SRC1 0x08000+#define SLOW_SRC2 0x10000+#define SLOW_DEST 0x20000+#define MEM_USE_TMP2 0x40000++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#define STACK_STORE SW+#define STACK_LOAD LW+#else+#define STACK_STORE SD+#define STACK_LOAD LD+#endif++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#include "sljitNativeRISCV_32.c"+#else+#include "sljitNativeRISCV_64.c"+#endif++#define STACK_MAX_DISTANCE (-SIMM_MIN)++static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw);++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 i, tmp, offset;+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ if ((local_size & SSIZE_OF(sw)) != 0)+ local_size += SSIZE_OF(sw);+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+ }+#else+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+#endif+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;+ compiler->local_size = local_size;++ if (local_size <= STACK_MAX_DISTANCE) {+ /* Frequent case. */+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));+ offset = local_size - SSIZE_OF(sw);+ local_size = 0;+ } else {+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(STACK_MAX_DISTANCE)));+ local_size -= STACK_MAX_DISTANCE;++ if (local_size > STACK_MAX_DISTANCE)+ FAIL_IF(load_immediate(compiler, TMP_REG1, local_size, TMP_REG3));+ offset = STACK_MAX_DISTANCE - SSIZE_OF(sw);+ }++ FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(RETURN_ADDR_REG), offset));++ tmp = SLJIT_S0 - saveds;+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));+ }++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ /* This alignment is valid because offset is not used after storing FPU regs. */+ if ((offset & SSIZE_OF(sw)) != 0)+ offset -= SSIZE_OF(sw);+#endif++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));+ }++ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));+ }++ if (local_size > STACK_MAX_DISTANCE)+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG1)));+ else if (local_size > 0)+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));++ if (options & SLJIT_ENTER_REG_ARG)+ return SLJIT_SUCCESS;++ arg_types >>= SLJIT_ARG_SHIFT;+ saved_arg_count = 0;+ tmp = SLJIT_R0;++ while (arg_types > 0) {+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_S0 - saved_arg_count) | RS1(tmp) | IMM_I(0)));+ saved_arg_count++;+ }+ tmp++;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++#undef STACK_MAX_DISTANCE++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {+ if ((local_size & SSIZE_OF(sw)) != 0)+ local_size += SSIZE_OF(sw);+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+ }+#else+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+#endif+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;++ return SLJIT_SUCCESS;+}++#define STACK_MAX_DISTANCE (-SIMM_MIN - 16)++static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)+{+ sljit_s32 i, tmp, offset;+ sljit_s32 local_size = compiler->local_size;++ if (local_size > STACK_MAX_DISTANCE) {+ local_size -= STACK_MAX_DISTANCE;++ if (local_size > STACK_MAX_DISTANCE) {+ FAIL_IF(load_immediate(compiler, TMP_REG2, local_size, TMP_REG3));+ FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG2)));+ } else+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size)));++ local_size = STACK_MAX_DISTANCE;+ }++ SLJIT_ASSERT(local_size > 0);++ offset = local_size - SSIZE_OF(sw);+ if (!is_return_to)+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset)));++ tmp = SLJIT_S0 - compiler->saveds;+ for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));+ }++ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offset -= SSIZE_OF(sw);+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));+ }++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ /* This alignment is valid because offset is not used after storing FPU regs. */+ if ((offset & SSIZE_OF(sw)) != 0)+ offset -= SSIZE_OF(sw);+#endif++ tmp = SLJIT_FS0 - compiler->fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));+ }++ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ offset -= SSIZE_OF(f64);+ FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));+ }++ return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size));+}++#undef STACK_MAX_DISTANCE++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ FAIL_IF(emit_stack_frame_release(compiler, 0));+ return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));+ src = TMP_REG1;+ srcw = 0;+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));+ src = TMP_REG1;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 1));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#define ARCH_32_64(a, b) a+#else+#define ARCH_32_64(a, b) b+#endif++static const sljit_ins data_transfer_insts[16 + 4] = {+/* u w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),+/* u w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),+/* u b s */ F3(0x0) | OPC(0x23) /* sb */,+/* u b l */ F3(0x4) | OPC(0x3) /* lbu */,+/* u h s */ F3(0x1) | OPC(0x23) /* sh */,+/* u h l */ F3(0x5) | OPC(0x3) /* lhu */,+/* u i s */ F3(0x2) | OPC(0x23) /* sw */,+/* u i l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x6) | OPC(0x3) /* lwu */),++/* s w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),+/* s w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),+/* s b s */ F3(0x0) | OPC(0x23) /* sb */,+/* s b l */ F3(0x0) | OPC(0x3) /* lb */,+/* s h s */ F3(0x1) | OPC(0x23) /* sh */,+/* s h l */ F3(0x1) | OPC(0x3) /* lh */,+/* s i s */ F3(0x2) | OPC(0x23) /* sw */,+/* s i l */ F3(0x2) | OPC(0x3) /* lw */,++/* d s */ F3(0x3) | OPC(0x27) /* fsd */,+/* d l */ F3(0x3) | OPC(0x7) /* fld */,+/* s s */ F3(0x2) | OPC(0x27) /* fsw */,+/* s l */ F3(0x2) | OPC(0x7) /* flw */,+};++#undef ARCH_32_64++static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 base, sljit_sw offset)+{+ sljit_ins ins;++ SLJIT_ASSERT(FAST_IS_REG(base) && offset <= 0xfff && offset >= SIMM_MIN);++ ins = data_transfer_insts[flags & MEM_MASK] | RS1(base);+ if (flags & LOAD_DATA)+ ins |= ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) | IMM_I(offset);+ else+ ins |= ((flags & MEM_MASK) <= GPR_REG ? RS2(reg) : FRS2(reg)) | IMM_S(offset);++ return push_inst(compiler, ins);+}++/* Can perform an operation using at most 1 instruction. */+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);++ if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {+ /* Works for both absoulte and relative addresses. */+ if (SLJIT_UNLIKELY(flags & ARG_TEST))+ return 1;++ FAIL_IF(push_mem_inst(compiler, flags, reg, arg & REG_MASK, argw));+ return -1;+ }+ return 0;+}++#define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0))++/* See getput_arg below.+ Note: can_cache is called only for binary operators. */+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));++ /* Simple operation except for updates. */+ if (arg & OFFS_REG_MASK) {+ argw &= 0x3;+ next_argw &= 0x3;+ if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))+ return 1;+ return 0;+ }++ if (arg == next_arg) {+ if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)+ || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))+ return 1;+ return 0;+ }++ return 0;+}++/* Emit the necessary instructions. See can_cache above. */+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_s32 base = arg & REG_MASK;+ sljit_s32 tmp_r = (flags & MEM_USE_TMP2) ? TMP_REG2 : TMP_REG1;+ sljit_sw offset, argw_hi;++ SLJIT_ASSERT(arg & SLJIT_MEM);+ if (!(next_arg & SLJIT_MEM)) {+ next_arg = 0;+ next_argw = 0;+ }++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ /* Using the cache. */+ if (argw == compiler->cache_argw) {+ if (arg == compiler->cache_arg)+ return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);++ 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, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));+ return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);+ }+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(TMP_REG3)));+ return push_mem_inst(compiler, flags, reg, tmp_r, 0);+ }+ }++ if (SLJIT_UNLIKELY(argw)) {+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);+ compiler->cache_argw = argw;+ FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(OFFS_REG(arg)) | IMM_I(argw)));+ }++ if (arg == next_arg && argw == (next_argw & 0x3)) {+ compiler->cache_arg = arg;+ compiler->cache_argw = argw;+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));+ tmp_r = TMP_REG3;+ }+ else+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));+ return push_mem_inst(compiler, flags, reg, tmp_r, 0);+ }++ if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)+ return push_mem_inst(compiler, flags, reg, TMP_REG3, argw - compiler->cache_argw);++ if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw <= SIMM_MAX) && (argw - compiler->cache_argw >= SIMM_MIN)) {+ offset = argw - compiler->cache_argw;+ } else {+ compiler->cache_arg = SLJIT_MEM;++ argw_hi = TO_ARGW_HI(argw);++ if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw, tmp_r));+ compiler->cache_argw = argw;+ offset = 0;+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi, tmp_r));+ compiler->cache_argw = argw_hi;+ offset = argw & 0xfff;+ argw = argw_hi;+ }+ }++ if (!base)+ return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);++ if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {+ compiler->cache_arg = arg;+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));+ return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);+ }++ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(TMP_REG3) | RS2(base)));+ return push_mem_inst(compiler, flags, reg, tmp_r, offset);+}++static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ sljit_s32 base = arg & REG_MASK;+ sljit_s32 tmp_r = TMP_REG1;++ if (getput_arg_fast(compiler, flags, reg, arg, argw))+ return compiler->error;++ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))+ tmp_r = reg;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ if (SLJIT_UNLIKELY(argw)) {+ FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(OFFS_REG(arg)) | IMM_I(argw)));+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));+ }+ else+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(OFFS_REG(arg))));++ argw = 0;+ } else {+ FAIL_IF(load_immediate(compiler, tmp_r, TO_ARGW_HI(argw), TMP_REG3));++ if (base != 0)+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));+ }++ return push_mem_inst(compiler, flags, reg, tmp_r, argw & 0xfff);+}++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);+}++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#define WORD 0+#define WORD_32 0+#define IMM_EXTEND(v) (IMM_I(v))+#else /* !SLJIT_CONFIG_RISCV_32 */+#define WORD word+#define WORD_32 0x08+#define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v))))+#endif /* SLJIT_CONFIG_RISCV_32 */++static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)+{+ sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;+ sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;+#else /* !SLJIT_CONFIG_RISCV_64 */+ sljit_ins word_size = 32;+#endif /* SLJIT_CONFIG_RISCV_64 */++ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);++ /* The OTHER_FLAG is the counter. */+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(word_size)));++ /* The TMP_REG2 is the next value. */+ if (src != TMP_REG2)+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src) | IMM_I(0)));++ FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)((is_clz ? 4 : 5) * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20)));++ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(0)));+ if (!is_clz) {+ FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG2) | IMM_I(1)));+ FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG1) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20)));+ } else+ FAIL_IF(push_inst(compiler, BLT | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20)));++ /* The TMP_REG1 is the next shift. */+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(word_size)));++ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(TMP_REG2) | IMM_I(0)));+ FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(1)));++ FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG1)));+ FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((2 * SSIZE_OF(ins)) << 7))));+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(TMP_REG1) | IMM_I(-1)));+ FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG2)));+ FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1)));+ FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((5 * SSIZE_OF(ins)) << 7))));++ return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(OTHER_FLAG) | IMM_I(0));+}++static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)+{+ SLJIT_UNUSED_ARG(op);++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (!(op & SLJIT_32)) {+ FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0x10000));+ FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(src) | IMM_I(32)));+ FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xfff)));+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src) | IMM_I(32)));+ FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(32)));+ FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));+ FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));++ FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(16)));+ FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));+ FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(8)));+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(16)));+ FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));+ FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));++ FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));+ FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(8)));+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));+ }+#endif /* SLJIT_CONFIG_RISCV_64 */++ FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(src) | IMM_I(16)));+ FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0xff0000));+ FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(src) | IMM_I(16)));+ FAIL_IF(push_inst(compiler, ORI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xff)));+ FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));++ FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));+ FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));+ FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(dst) | IMM_I(8)));+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));+}++static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)+{+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;+ sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;+#else /* !SLJIT_CONFIG_RISCV_64 */+ sljit_ins word_size = 32;+#endif /* SLJIT_CONFIG_RISCV_64 */++ FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(src) | IMM_I(8)));+ FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src) | IMM_I(word_size - 8)));+ FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(0xff)));+ FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | WORD | RD(dst) | RS1(dst) | IMM_I(word_size - 16)));+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));+}++#define EMIT_LOGICAL(op_imm, op_reg) \+ if (flags & SRC2_IMM) { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \+ } \+ else { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \+ }++#define EMIT_SHIFT(imm, reg) \+ op_imm = (imm); \+ op_reg = (reg);++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, carry_src_r, is_handled, reg;+ sljit_ins op_imm, op_reg;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;+#endif /* SLJIT_CONFIG_RISCV_64 */++ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if (dst != src2)+ return push_inst(compiler, ADDI | RD(dst) | RS1(src2) | IMM_I(0));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, ANDI | RD(dst) | RS1(src2) | IMM_I(0xff));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(24)));+ return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(24));+ }+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));+ return push_inst(compiler, SRLI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));+ }+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));+ return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));+ }+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ case SLJIT_MOV_U32:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src2) | IMM_I(32)));+ return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));+ }+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_S32:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))+ return push_inst(compiler, ADDI | 0x8 | RD(dst) | RS1(src2) | IMM_I(0));+ SLJIT_ASSERT(dst == src2);+ return SLJIT_SUCCESS;+#endif /* SLJIT_CONFIG_RISCV_64 */++ case SLJIT_CLZ:+ case SLJIT_CTZ:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ return emit_clz_ctz(compiler, op, dst, src2);++ case SLJIT_REV:+ case SLJIT_REV_S32:+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ case SLJIT_REV_U32:+#endif /* SLJIT_CONFIG_RISCV_32 */+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ return emit_rev(compiler, op, dst, src2);++ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ return emit_rev16(compiler, op, dst, src2);++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ case SLJIT_REV_U32:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1);+ FAIL_IF(emit_rev(compiler, op, dst, src2));+ if (dst == TMP_REG2)+ return SLJIT_SUCCESS;+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(32)));+ return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));+#endif /* SLJIT_CONFIG_RISCV_32 */++ case SLJIT_ADD:+ /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));+ else+ FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));+ }+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));++ /* Only the zero flag is needed. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));+ }+ else {+ if (is_overflow)+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADD | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));++ if (is_overflow || carry_src_r != 0) {+ if (src1 != dst)+ carry_src_r = (sljit_s32)src1;+ else if (src2 != dst)+ carry_src_r = (sljit_s32)src2;+ else {+ FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(0)));+ carry_src_r = OTHER_FLAG;+ }+ }++ /* Only the zero flag is needed. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));+ }++ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */+ if (is_overflow || carry_src_r != 0) {+ if (flags & SRC2_IMM)+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(src2)));+ else+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(carry_src_r)));+ }++ if (!is_overflow)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));+ FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));+ return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));++ case SLJIT_ADDC:+ carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));+ } else {+ if (carry_src_r != 0) {+ if (src1 != dst)+ carry_src_r = (sljit_s32)src1;+ else if (src2 != dst)+ carry_src_r = (sljit_s32)src2;+ else {+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));+ carry_src_r = EQUAL_FLAG;+ }+ }++ FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));+ }++ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */+ if (carry_src_r != 0) {+ if (flags & SRC2_IMM)+ FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(src2)));+ else+ FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(dst) | RS2(carry_src_r)));+ }++ FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));++ if (carry_src_r == 0)+ return SLJIT_SUCCESS;++ /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG)));+ /* Set carry flag. */+ return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG));++ case SLJIT_SUB:+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ is_handled = 0;++ if (flags & SRC2_IMM) {+ if (GET_FLAG_TYPE(op) == SLJIT_LESS) {+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));+ is_handled = 1;+ }+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {+ FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));+ 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) {+ reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(push_inst(compiler, ADDI | RD(reg) | RS1(TMP_ZERO) | IMM_I(src2)));+ src2 = reg;+ flags &= ~SRC2_IMM;+ }++ switch (GET_FLAG_TYPE(op)) {+ case SLJIT_LESS:+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));+ break;+ case SLJIT_GREATER:+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));+ break;+ case SLJIT_SIG_LESS:+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));+ break;+ case SLJIT_SIG_GREATER:+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));+ break;+ }+ }++ if (is_handled) {+ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));+ if (!(flags & UNUSED_DEST))+ return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2));+ }+ else {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));+ if (!(flags & UNUSED_DEST))+ return push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2));+ }+ return SLJIT_SUCCESS;+ }++ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));+ else+ FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));+ }+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));++ /* Only the zero flag is needed. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));+ }+ else {+ if (is_overflow)+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));++ /* Only the zero flag is needed. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));+ }++ if (!is_overflow)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));+ FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));+ return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));++ case SLJIT_SUBC:+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));++ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));+ }+ else {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));++ FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));+ }++ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | RD(TMP_REG1) | RS1(dst) | RS2(OTHER_FLAG)));++ FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));++ if (!is_carry)+ return SLJIT_SUCCESS;++ return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(TMP_REG1));++ case SLJIT_MUL:+ SLJIT_ASSERT(!(flags & SRC2_IMM));++ if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW)+ return push_inst(compiler, MUL | WORD | RD(dst) | RS1(src1) | RS2(src2));++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (word) {+ FAIL_IF(push_inst(compiler, MUL | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));+ FAIL_IF(push_inst(compiler, MUL | 0x8 | RD(dst) | RS1(src1) | RS2(src2)));+ return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG));+ }+#endif /* SLJIT_CONFIG_RISCV_64 */++ FAIL_IF(push_inst(compiler, MULH | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));+ FAIL_IF(push_inst(compiler, MUL | RD(dst) | RS1(src1) | RS2(src2)));+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(31)));+#else /* !SLJIT_CONFIG_RISCV_32 */+ FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(63)));+#endif /* SLJIT_CONFIG_RISCV_32 */+ return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(OTHER_FLAG));++ case SLJIT_AND:+ EMIT_LOGICAL(ANDI, AND);+ return SLJIT_SUCCESS;++ case SLJIT_OR:+ EMIT_LOGICAL(ORI, OR);+ return SLJIT_SUCCESS;++ case SLJIT_XOR:+ EMIT_LOGICAL(XORI, XOR);+ return SLJIT_SUCCESS;++ case SLJIT_SHL:+ case SLJIT_MSHL:+ EMIT_SHIFT(SLLI, SLL);+ break;++ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ EMIT_SHIFT(SRLI, SRL);+ break;++ case SLJIT_ASHR:+ case SLJIT_MASHR:+ EMIT_SHIFT(SRAI, SRA);+ break;++ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (flags & SRC2_IMM) {+ SLJIT_ASSERT(src2 != 0);++ op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLI : SRLI;+ FAIL_IF(push_inst(compiler, op_imm | WORD | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ src2 = ((op & SLJIT_32) ? 32 : 64) - src2;+#else /* !SLJIT_CONFIG_RISCV_64 */+ src2 = 32 - src2;+#endif /* SLJIT_CONFIG_RISCV_64 */+ op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLI : SLLI;+ FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));+ }++ if (src2 == TMP_ZERO) {+ if (dst != src1)+ return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(0));+ return SLJIT_SUCCESS;+ }++ FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(TMP_ZERO) | RS2(src2)));+ op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;+ FAIL_IF(push_inst(compiler, op_reg | WORD | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));+ op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;+ FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(EQUAL_FLAG)));+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));++ default:+ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+ }++ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, op_imm | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));++ if (flags & UNUSED_DEST)+ return SLJIT_SUCCESS;+ return push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2));+ }++ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, op_reg | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));++ if (flags & UNUSED_DEST)+ return SLJIT_SUCCESS;+ return push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(src2));+}++#undef IMM_EXTEND++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_s32 dst_r = TMP_REG2;+ sljit_s32 src1_r;+ sljit_sw src2_r = 0;+ sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;++ if (!(flags & ALT_KEEP_CACHE)) {+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ }++ if (dst == 0) {+ SLJIT_ASSERT(HAS_FLAGS(op));+ flags |= UNUSED_DEST;+ dst = TMP_REG2;+ }+ else if (FAST_IS_REG(dst)) {+ dst_r = dst;+ flags |= REG_DEST;+ if (flags & MOVE_OP)+ src2_tmp_reg = dst_r;+ }+ 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 != 0 && src2w <= SIMM_MAX && src2w >= SIMM_MIN) {+ flags |= SRC2_IMM;+ src2_r = src2w;+ }+ else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && src1w <= SIMM_MAX && src1w >= SIMM_MIN) {+ flags |= SRC2_IMM;+ src2_r = src1w;++ /* And swap arguments. */+ src1 = src2;+ src1w = src2w;+ src2 = SLJIT_IMM;+ /* src2w = src2_r unneeded. */+ }+ }++ /* Source 1. */+ if (FAST_IS_REG(src1)) {+ src1_r = src1;+ flags |= REG1_SOURCE;+ } else if (src1 == SLJIT_IMM) {+ if (src1w) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));+ src1_r = TMP_REG1;+ }+ else+ src1_r = TMP_ZERO;+ } else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC1;+ src1_r = TMP_REG1;+ }++ /* Source 2. */+ if (FAST_IS_REG(src2)) {+ src2_r = src2;+ flags |= REG2_SOURCE;+ if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)+ dst_r = (sljit_s32)src2_r;+ } else if (src2 == SLJIT_IMM) {+ if (!(flags & SRC2_IMM)) {+ if (src2w) {+ FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));+ src2_r = src2_tmp_reg;+ } else {+ src2_r = TMP_ZERO;+ if (flags & MOVE_OP) {+ if (dst & SLJIT_MEM)+ dst_r = 0;+ else+ op = SLJIT_MOV;+ }+ }+ }+ } else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, src2_tmp_reg, src2, src2w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC2;+ src2_r = src2_tmp_reg;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ SLJIT_ASSERT(src2_r == TMP_REG2);+ if ((flags & SLOW_DEST) && !can_cache(src2, src2w, src1, src1w) && can_cache(src2, src2w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | MEM_USE_TMP2, TMP_REG2, src2, src2w, dst, dstw));+ } else {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | ((src1_r == TMP_REG1) ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, dst, dstw));++ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));++ if (dst & SLJIT_MEM) {+ if (!(flags & SLOW_DEST)) {+ getput_arg_fast(compiler, flags, dst_r, dst, dstw);+ return compiler->error;+ }+ return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;++ SLJIT_ASSERT(word == 0 || word == 0x8);+#endif /* SLJIT_CONFIG_RISCV_64 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ switch (GET_OPCODE(op)) {+ case SLJIT_BREAKPOINT:+ return push_inst(compiler, EBREAK);+ case SLJIT_NOP:+ return push_inst(compiler, ADDI | RD(TMP_ZERO) | RS1(TMP_ZERO) | IMM_I(0));+ case SLJIT_LMUL_UW:+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));+ FAIL_IF(push_inst(compiler, MULHU | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));+ return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));+ case SLJIT_LMUL_SW:+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));+ FAIL_IF(push_inst(compiler, MULH | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));+ return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));+ case SLJIT_DIVMOD_UW:+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));+ FAIL_IF(push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));+ return push_inst(compiler, REMU | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));+ case SLJIT_DIVMOD_SW:+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));+ FAIL_IF(push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));+ return push_inst(compiler, REM | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));+ case SLJIT_DIV_UW:+ return push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));+ case SLJIT_DIV_SW:+ return push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++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_s32 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 (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (op & SLJIT_32)+ flags = INT_DATA | SIGNED_DATA;+#endif++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+#endif+ case SLJIT_MOV_P:+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, srcw);++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ case SLJIT_MOV_U32:+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);++ case SLJIT_MOV_S32:+ /* Logical operators have no W variant, so sign extended input is necessary for them. */+ case SLJIT_MOV32:+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);+#endif++ case SLJIT_MOV_U8:+ return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);++ case SLJIT_MOV_S8:+ return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);++ case SLJIT_MOV_U16:+ return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);++ case SLJIT_MOV_S16:+ return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);++ case SLJIT_CLZ:+ case SLJIT_CTZ:+ case SLJIT_REV:+ return emit_op(compiler, op, flags, dst, dstw, TMP_ZERO, 0, src, srcw);++ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);++ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++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_s32 flags = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (op & SLJIT_32) {+ flags |= INT_DATA | SIGNED_DATA;+ if (src1 == SLJIT_IMM)+ src1w = (sljit_s32)src1w;+ if (src2 == SLJIT_IMM)+ src2w = (sljit_s32)src2w;+ }+#endif++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ case SLJIT_ADDC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUB:+ case SLJIT_SUBC:+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_MUL:+ compiler->status_flags_state = 0;+ return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_MSHL:+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (src2 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ src2w &= 0x1f;+#else /* !SLJIT_CONFIG_RISCV_32 */+ if (op & SLJIT_32)+ src2w &= 0x1f;+ else+ src2w &= 0x3f;+#endif /* SLJIT_CONFIG_RISCV_32 */+ }++ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;+#endif /* SLJIT_CONFIG_RISCV_64 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));++ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);++ switch (GET_OPCODE(op)) {+ case SLJIT_MULADD:+ SLJIT_SKIP_CHECKS(compiler);+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));+ return push_inst(compiler, ADD | WORD | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG2));+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+ sljit_s32 is_left;+ sljit_ins ins1, ins2, ins3;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;+ sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;+#else /* !SLJIT_CONFIG_RISCV_64 */+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;+ sljit_sw bit_length = 32;+#endif /* SLJIT_CONFIG_RISCV_64 */++ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);++ CHECK_ERROR();+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));++ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);++ if (src1_reg == src2_reg) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);+ }++ ADJUST_LOCAL_OFFSET(src3, src3w);++ if (src3 == SLJIT_IMM) {+ src3w &= bit_length - 1;++ if (src3w == 0)+ return SLJIT_SUCCESS;++ if (is_left) {+ ins1 = SLLI | WORD | IMM_I(src3w);+ src3w = bit_length - src3w;+ ins2 = SRLI | WORD | IMM_I(src3w);+ } else {+ ins1 = SRLI | WORD | IMM_I(src3w);+ src3w = bit_length - src3w;+ ins2 = SLLI | WORD | IMM_I(src3w);+ }++ FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RS1(src1_reg)));+ FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RS1(src2_reg)));+ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));+ }++ if (src3 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w));+ src3 = TMP_REG2;+ } else if (dst_reg == src3) {+ push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src3) | IMM_I(0));+ src3 = TMP_REG2;+ }++ if (is_left) {+ ins1 = SLL;+ ins2 = SRLI;+ ins3 = SRL;+ } else {+ ins1 = SRL;+ ins2 = SLLI;+ ins3 = SLL;+ }++ FAIL_IF(push_inst(compiler, ins1 | WORD | RD(dst_reg) | RS1(src1_reg) | RS2(src3)));++ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {+ FAIL_IF(push_inst(compiler, ins2 | WORD | RD(TMP_REG1) | RS1(src2_reg) | IMM_I(1)));+ FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RS1(src3) | IMM_I((sljit_ins)bit_length - 1)));+ src2_reg = TMP_REG1;+ } else+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(TMP_REG2) | RS1(TMP_ZERO) | RS2(src3)));++ FAIL_IF(push_inst(compiler, ins3 | WORD | RD(TMP_REG1) | RS1(src2_reg) | RS2(TMP_REG2)));+ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, ADDI | RD(RETURN_ADDR_REG) | RS1(src) | IMM_I(0)));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));++ return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ switch (op) {+ case SLJIT_FAST_ENTER:+ if (FAST_IS_REG(dst))+ return push_inst(compiler, ADDI | RD(dst) | RS1(RETURN_ADDR_REG) | IMM_I(0));++ SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2);+ break;+ case SLJIT_GET_RETURN_ADDRESS:+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));++ if (type == SLJIT_GP_REGISTER)+ return reg_map[reg];++ if (type != SLJIT_FLOAT_REGISTER)+ return -1;++ return freg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+ SLJIT_UNUSED_ARG(size);++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))+#define FMT(op) ((sljit_ins)((op & SLJIT_32) ^ SLJIT_32) << 17)++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_RISCV_32 && SLJIT_CONFIG_RISCV_32)+# define flags (sljit_u32)0+#else+ sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;+#endif+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst(compiler, FCVT_W_S | FMT(op) | flags | RD(dst_r) | FRS1(src)));++ /* Store the integer value from a VFP register. */+ if (dst & SLJIT_MEM) {+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ return emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);+#else+ return emit_op_mem2(compiler, flags ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0);+#endif+ }+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+# undef flags+#endif+}++static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));+#else /* SLJIT_CONFIG_RISCV_32 */+ FAIL_IF(emit_op_mem2(compiler, ((ins & (1 << 21)) ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));+#endif /* !SLJIT_CONFIG_RISCV_32 */+ src = TMP_REG1;+ } else if (src == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3));+ src = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, ins | FRD(dst_r) | RS1(src)));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, DOUBLE_DATA | ((sljit_s32)(~ins >> 24) & 0x2), TMP_FREG1, dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++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_ins ins = FCVT_S_W | FMT(op);++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if (op & SLJIT_32)+ ins |= F3(0x7);+#else /* !SLJIT_CONFIG_RISCV_32 */+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)+ ins |= (1 << 21);+ else if (src == SLJIT_IMM)+ srcw = (sljit_s32)srcw;++ if (op != SLJIT_CONV_F64_FROM_S32)+ ins |= F3(0x7);+#endif /* SLJIT_CONFIG_RISCV_32 */++ return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_ins ins = FCVT_S_WU | FMT(op);++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if (op & SLJIT_32)+ ins |= F3(0x7);+#else /* !SLJIT_CONFIG_RISCV_32 */+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW)+ ins |= (1 << 21);+ else if (src == SLJIT_IMM)+ srcw = (sljit_u32)srcw;++ if (op != SLJIT_CONV_F64_FROM_S32)+ ins |= F3(0x7);+#endif /* SLJIT_CONFIG_RISCV_32 */++ return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);+}++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;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));+ src2 = TMP_FREG2;+ }++ switch (GET_FLAG_TYPE(op)) {+ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);+ break;+ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);+ break;+ case SLJIT_ORDERED_GREATER:+ inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);+ break;+ case SLJIT_F_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);+ break;+ case SLJIT_UNORDERED_OR_LESS:+ inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);+ break;+ case SLJIT_UNORDERED_OR_EQUAL:+ FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2)));+ FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src1)));+ inst = OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);+ break;+ default: /* SLJIT_UNORDERED */+ if (src1 == src2) {+ inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1);+ break;+ }+ FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1)));+ FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src2)));+ inst = AND | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);+ break;+ }++ return push_inst(compiler, inst);+}++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_s32 dst_r;++ CHECK_ERROR();+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)+ op ^= SLJIT_32;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (!(dst & SLJIT_MEM))+ FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, FSGNJN_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, FSGNJX_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */+ FAIL_IF(push_inst(compiler, FCVT_S_D | ((op & SLJIT_32) ? (1 << 25) : ((1 << 20) | F3(7))) | FRD(dst_r) | FRS1(src)));+ op ^= SLJIT_32;+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++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_s32 dst_r, flags = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;++ if (src1 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {+ FAIL_IF(compiler->error);+ src1 = TMP_FREG1;+ } else+ flags |= SLOW_SRC1;+ }++ if (src2 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {+ FAIL_IF(compiler->error);+ src2 = TMP_FREG2;+ } else+ flags |= SLOW_SRC2;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));+ } else {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));++ if (flags & SLOW_SRC1)+ src1 = TMP_FREG1;+ if (flags & SLOW_SRC2)+ src2 = TMP_FREG2;++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));+ break;++ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, FSUB_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));+ break;++ case SLJIT_MUL_F64:+ FAIL_IF(push_inst(compiler, FMUL_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));+ break;++ case SLJIT_DIV_F64:+ FAIL_IF(push_inst(compiler, FDIV_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));+ break;++ case SLJIT_COPYSIGN_F64:+ return push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2));+ }++ if (dst_r != dst)+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+ union {+ sljit_s32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++ if (u.imm == 0)+ return push_inst(compiler, FMV_W_X | RS1(TMP_ZERO) | FRD(freg));++ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3));+ return push_inst(compiler, FMV_W_X | RS1(TMP_REG1) | FRD(freg));+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7)+#else+#define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7)+#endif++static sljit_ins get_jump_instruction(sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ return BNE | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);+ case SLJIT_NOT_EQUAL:+ return BEQ | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);+ case SLJIT_LESS:+ case SLJIT_GREATER:+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_GREATER:+ case SLJIT_OVERFLOW:+ case SLJIT_CARRY:+ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ case SLJIT_ORDERED_GREATER:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_ORDERED:+ return BEQ | RS1(OTHER_FLAG) | RS2(TMP_ZERO);+ 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_NOT_CARRY:+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ case SLJIT_F_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ case SLJIT_UNORDERED_OR_LESS:+ case SLJIT_UNORDERED:+ return BNE | RS1(OTHER_FLAG) | RS2(TMP_ZERO);+ default:+ /* Not conditional branch. */+ return 0;+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;+ sljit_ins inst;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ inst = get_jump_instruction(type);++ if (inst != 0) {+ PTR_FAIL_IF(push_inst(compiler, inst | BRANCH_LENGTH));+ jump->flags |= IS_COND;+ }++ jump->addr = compiler->size;+ inst = JALR | RS1(TMP_REG1) | IMM_I(0);++ if (type >= SLJIT_FAST_CALL) {+ jump->flags |= IS_CALL;+ inst |= RD(RETURN_ADDR_REG);+ }++ PTR_FAIL_IF(push_inst(compiler, inst));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ SLJIT_UNUSED_ARG(arg_types);+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ if (type & SLJIT_CALL_RETURN) {+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, type);+}++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_s32 flags;+ sljit_ins inst;+ sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ flags = WORD_DATA | LOAD_DATA;+#else /* !SLJIT_CONFIG_RISCV_32 */+ flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;+#endif /* SLJIT_CONFIG_RISCV_32 */++ if (src1 & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG1, src1, src1w, src2, src2w));+ src1 = TMP_REG1;+ }++ if (src2 & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, src2_tmp_reg, src2, src2w, 0, 0));+ src2 = src2_tmp_reg;+ }++ if (src1 == SLJIT_IMM) {+ if (src1w != 0) {+ PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));+ src1 = TMP_REG1;+ }+ else+ src1 = TMP_ZERO;+ }++ if (src2 == SLJIT_IMM) {+ if (src2w != 0) {+ PTR_FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));+ src2 = src2_tmp_reg;+ }+ else+ src2 = TMP_ZERO;+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND));+ type &= 0xff;++ switch (type) {+ case SLJIT_EQUAL:+ inst = BNE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;+ break;+ case SLJIT_NOT_EQUAL:+ inst = BEQ | RS1(src1) | RS2(src2) | BRANCH_LENGTH;+ break;+ case SLJIT_LESS:+ inst = BGEU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;+ break;+ case SLJIT_GREATER_EQUAL:+ inst = BLTU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;+ break;+ case SLJIT_GREATER:+ inst = BGEU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;+ break;+ case SLJIT_LESS_EQUAL:+ inst = BLTU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;+ break;+ case SLJIT_SIG_LESS:+ inst = BGE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;+ break;+ case SLJIT_SIG_GREATER_EQUAL:+ inst = BLT | RS1(src1) | RS2(src2) | BRANCH_LENGTH;+ break;+ case SLJIT_SIG_GREATER:+ inst = BGE | RS1(src2) | RS2(src1) | BRANCH_LENGTH;+ break;+ case SLJIT_SIG_LESS_EQUAL:+ inst = BLT | RS1(src2) | RS2(src1) | BRANCH_LENGTH;+ break;+ }++ PTR_FAIL_IF(push_inst(compiler, inst));++ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return jump;+}++#undef BRANCH_LENGTH++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;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));++ if (src != SLJIT_IMM) {+ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));+ src = TMP_REG1;+ }+ return push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(src) | IMM_I(0));+ }++ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_CALL : 0));+ jump->u.target = (sljit_uw)srcw;++ jump->addr = compiler->size;+ FAIL_IF(push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));++ /* Maximum number of instructions required for generating a constant. */+ compiler->size += JUMP_MAX_SIZE - 1;+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(arg_types);+ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));+ src = TMP_REG1;+ }++ if (type & SLJIT_CALL_RETURN) {+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));+ src = TMP_REG1;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 0));+ type = SLJIT_JUMP;+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+}++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_s32 src_r, dst_r, invert;+ sljit_s32 saved_op = op;+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ sljit_s32 mem_type = WORD_DATA;+#else+ sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+ dst_r = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));++ if (type < SLJIT_F_EQUAL) {+ src_r = OTHER_FLAG;+ invert = type & 0x1;++ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_NOT_EQUAL:+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(EQUAL_FLAG) | IMM_I(1)));+ src_r = dst_r;+ break;+ case SLJIT_OVERFLOW:+ case SLJIT_NOT_OVERFLOW:+ if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {+ src_r = OTHER_FLAG;+ break;+ }+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(OTHER_FLAG) | IMM_I(1)));+ src_r = dst_r;+ invert ^= 0x1;+ break;+ }+ } else {+ invert = 0;+ src_r = OTHER_FLAG;++ switch (type) {+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ case SLJIT_F_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ case SLJIT_UNORDERED_OR_LESS:+ case SLJIT_UNORDERED:+ invert = 1;+ break;+ }+ }++ if (invert) {+ FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(src_r) | IMM_I(1)));+ src_r = dst_r;+ }++ if (op < SLJIT_ADD) {+ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, mem_type, src_r, dst, dstw);++ if (src_r != dst_r)+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(src_r) | IMM_I(0));+ return SLJIT_SUCCESS;+ }++ mem_type |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;++ if (dst & SLJIT_MEM)+ return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, src_r, 0);+ return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+ sljit_ins *ptr;+ sljit_uw size;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_ins word = (sljit_ins)(type & SLJIT_32) >> 5;+ sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;+#else /* !SLJIT_CONFIG_RISCV_64 */+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;+#endif /* SLJIT_CONFIG_RISCV_64 */++ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (dst_reg != src2_reg) {+ if (dst_reg == src1) {+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else {+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(dst_reg) | IMM_I(0)));++ if ((src1 & REG_MASK) == dst_reg)+ src1 = (src1 & ~REG_MASK) | TMP_REG1;++ if (OFFS_REG(src1) == dst_reg)+ src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);+ }++ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src2_reg) | IMM_I(0)));+ }+ }++ size = compiler->size;++ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size++;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));+ } else if (src1 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (word)+ src1w = (sljit_s32)src1w;+#endif /* SLJIT_CONFIG_RISCV_64 */+ FAIL_IF(load_immediate(compiler, dst_reg, src1w, TMP_REG1));+ } else+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src1) | IMM_I(0)));++ size = compiler->size - size;+ *ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);+ return SLJIT_SUCCESS;+}++#undef WORD++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+ sljit_ins *ptr;+ sljit_uw size;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (dst_freg != src2_freg) {+ if (dst_freg == src1) {+ src1 = src2_freg;+ src1w = 0;+ type ^= 0x1;+ } else+ FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src2_freg) | FRS2(src2_freg)));+ }++ size = compiler->size;++ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size++;++ if (src1 & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w));+ else+ FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src1) | FRS2(src1)));++ size = compiler->size - size;+ *ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);+ return SLJIT_SUCCESS;+}++#undef FLOAT_DATA+#undef FMT++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (!(reg & REG_PAIR_MASK))+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ memw &= 0x3;++ if (SLJIT_UNLIKELY(memw != 0)) {+ FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw)));+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));+ } else+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(mem & REG_MASK) | RS2(OFFS_REG(mem))));++ mem = TMP_REG1;+ memw = 0;+ } else if (memw > SIMM_MAX - SSIZE_OF(sw) || memw < SIMM_MIN) {+ if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw), TMP_REG3));+ memw &= 0xfff;+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3));+ memw = 0;+ }++ if (mem & REG_MASK)+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));++ mem = TMP_REG1;+ } else {+ mem &= REG_MASK;+ memw &= 0xfff;+ }++ SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw > SIMM_MAX && memw <= 0xfff));++ if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {+ FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff));+ return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), mem, memw);+ }++ flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0);++ FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), mem, memw));+ return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff);+}++#undef TO_ARGW_HI++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, ADDI | RD(dst_r)));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ compiler->size += 1;+#else /* !SLJIT_CONFIG_RISCV_32 */+ compiler->size += 5;+#endif /* SLJIT_CONFIG_RISCV_32 */++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);+}
src/c/pcre2/src/sljit/sljitNativeS390X.c view
@@ -38,3341 +38,4482 @@ return "s390x" SLJIT_CPUINFO; } -/* Instructions. */-typedef sljit_uw sljit_ins;--/* Instruction tags (most significant halfword). */-static const sljit_ins sljit_ins_const = (sljit_ins)1 << 48;--#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)-#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)--static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {- 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 0, 1-};--/* there are also a[2-15] available, but they are slower to access and- * their use is limited as mundaym explained:- * https://github.com/zherczeg/sljit/pull/91#discussion_r486895689- */--/* General Purpose Registers [0-15]. */-typedef sljit_uw sljit_gpr;--/*- * WARNING- * the following code is non standard and should be improved for- * consistency, but doesn't use SLJIT_NUMBER_OF_REGISTERS based- * registers because r0 and r1 are the ABI recommended volatiles.- * there is a gpr() function that maps sljit to physical register numbers- * that should be used instead of the usual index into reg_map[] and- * will be retired ASAP (TODO: carenas)- */--static const sljit_gpr r0 = 0; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 2]: 0 in address calculations; reserved */-static const sljit_gpr r1 = 1; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 3]: reserved */-static const sljit_gpr r2 = 2; /* reg_map[1]: 1st argument */-static const sljit_gpr r3 = 3; /* reg_map[2]: 2nd argument */-static const sljit_gpr r4 = 4; /* reg_map[3]: 3rd argument */-static const sljit_gpr r5 = 5; /* reg_map[4]: 4th argument */-static const sljit_gpr r6 = 6; /* reg_map[5]: 5th argument; 1st saved register */-static const sljit_gpr r7 = 7; /* reg_map[6] */-static const sljit_gpr r8 = 8; /* reg_map[7] */-static const sljit_gpr r9 = 9; /* reg_map[8] */-static const sljit_gpr r10 = 10; /* reg_map[9] */-static const sljit_gpr r11 = 11; /* reg_map[10] */-static const sljit_gpr r12 = 12; /* reg_map[11]: GOT */-static const sljit_gpr r13 = 13; /* reg_map[12]: Literal Pool pointer */-static const sljit_gpr r14 = 14; /* reg_map[0]: return address and flag register */-static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stack pointer */--/* WARNING: r12 and r13 shouldn't be used as per ABI recommendation */-/* TODO(carenas): r12 might conflict in PIC code, reserve? */-/* TODO(carenas): r13 is usually pointed to "pool" per ABI, using a tmp- * like we do know might be faster though, reserve?- */--/* TODO(carenas): should be named TMP_REG[1-2] for consistency */-#define tmp0 r0-#define tmp1 r1--/* TODO(carenas): flags should move to a different register so that- * link register doesn't need to change- */--/* When reg cannot be unused. */-#define IS_GPR_REG(reg) ((reg > 0) && (reg) <= SLJIT_SP)--/* Link registers. The normal link register is r14, but since- we use that for flags we need to use r0 instead to do fast- calls so that flags are preserved. */-static const sljit_gpr link_r = 14; /* r14 */-static const sljit_gpr fast_link_r = 0; /* r0 */--#define TMP_FREG1 (0)--static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {- 1, 0, 2, 4, 6, 3, 5, 7, 15, 14, 13, 12, 11, 10, 9, 8,-};--#define R0A(r) (r)-#define R4A(r) ((r) << 4)-#define R8A(r) ((r) << 8)-#define R12A(r) ((r) << 12)-#define R16A(r) ((r) << 16)-#define R20A(r) ((r) << 20)-#define R28A(r) ((r) << 28)-#define R32A(r) ((r) << 32)-#define R36A(r) ((r) << 36)--#define R0(r) ((sljit_ins)reg_map[r])--#define F0(r) ((sljit_ins)freg_map[r])-#define F4(r) (R4A((sljit_ins)freg_map[r]))-#define F20(r) (R20A((sljit_ins)freg_map[r]))-#define F36(r) (R36A((sljit_ins)freg_map[r]))--struct sljit_s390x_const {- struct sljit_const const_; /* must be first */- sljit_sw init_value; /* required to build literal pool */-};--/* Convert SLJIT register to hardware register. */-static SLJIT_INLINE sljit_gpr gpr(sljit_s32 r)-{- SLJIT_ASSERT(r >= 0 && r < (sljit_s32)(sizeof(reg_map) / sizeof(reg_map[0])));- return reg_map[r];-}--static SLJIT_INLINE sljit_gpr fgpr(sljit_s32 r)-{- SLJIT_ASSERT(r >= 0 && r < (sljit_s32)(sizeof(freg_map) / sizeof(freg_map[0])));- return freg_map[r];-}--/* Size of instruction in bytes. Tags must already be cleared. */-static SLJIT_INLINE sljit_uw sizeof_ins(sljit_ins ins)-{- /* keep faulting instructions */- if (ins == 0)- return 2;-- if ((ins & 0x00000000ffffL) == ins)- return 2;- if ((ins & 0x0000ffffffffL) == ins)- return 4;- if ((ins & 0xffffffffffffL) == ins)- return 6;-- SLJIT_UNREACHABLE();- return (sljit_uw)-1;-}--static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)-{- sljit_ins *ibuf = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));- FAIL_IF(!ibuf);- *ibuf = ins;- compiler->size++;- return SLJIT_SUCCESS;-}--static sljit_s32 encode_inst(void **ptr, sljit_ins ins)-{- sljit_u16 *ibuf = (sljit_u16 *)*ptr;- sljit_uw size = sizeof_ins(ins);-- SLJIT_ASSERT((size & 6) == size);- switch (size) {- case 6:- *ibuf++ = (sljit_u16)(ins >> 32);- /* fallthrough */- case 4:- *ibuf++ = (sljit_u16)(ins >> 16);- /* fallthrough */- case 2:- *ibuf++ = (sljit_u16)(ins);- }- *ptr = (void*)ibuf;- return SLJIT_SUCCESS;-}--#define SLJIT_ADD_SUB_NO_COMPARE(status_flags_state) \- (((status_flags_state) & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) \- && !((status_flags_state) & SLJIT_CURRENT_FLAGS_COMPARE))--/* Map the given type to a 4-bit condition code mask. */-static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 type) {- const sljit_u8 cc0 = 1 << 3; /* equal {,to zero} */- const sljit_u8 cc1 = 1 << 2; /* less than {,zero} */- const sljit_u8 cc2 = 1 << 1; /* greater than {,zero} */- const sljit_u8 cc3 = 1 << 0; /* {overflow,NaN} */-- switch (type) {- case SLJIT_EQUAL:- if (SLJIT_ADD_SUB_NO_COMPARE(compiler->status_flags_state)) {- sljit_s32 type = GET_FLAG_TYPE(compiler->status_flags_state);- if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL)- return cc0;- if (type == SLJIT_OVERFLOW)- return (cc0 | cc3);- return (cc0 | cc2);- }- /* fallthrough */-- case SLJIT_EQUAL_F64:- return cc0;-- case SLJIT_NOT_EQUAL:- if (SLJIT_ADD_SUB_NO_COMPARE(compiler->status_flags_state)) {- sljit_s32 type = GET_FLAG_TYPE(compiler->status_flags_state);- if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL)- return (cc1 | cc2 | cc3);- if (type == SLJIT_OVERFLOW)- return (cc1 | cc2);- return (cc1 | cc3);- }- /* fallthrough */-- case SLJIT_NOT_EQUAL_F64:- return (cc1 | cc2 | cc3);-- case SLJIT_LESS:- return cc1;-- case SLJIT_GREATER_EQUAL:- return (cc0 | cc2 | cc3);-- case SLJIT_GREATER:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_COMPARE)- return cc2;- return cc3;-- case SLJIT_LESS_EQUAL:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_COMPARE)- return (cc0 | cc1);- return (cc0 | cc1 | cc2);-- case SLJIT_SIG_LESS:- case SLJIT_LESS_F64:- return cc1;-- case SLJIT_NOT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)- return (cc2 | cc3);- /* fallthrough */-- case SLJIT_SIG_LESS_EQUAL:- case SLJIT_LESS_EQUAL_F64:- return (cc0 | cc1);-- case SLJIT_CARRY:- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)- return (cc0 | cc1);- /* fallthrough */-- case SLJIT_SIG_GREATER:- /* Overflow is considered greater, see SLJIT_SUB. */- return cc2 | cc3;-- case SLJIT_SIG_GREATER_EQUAL:- return (cc0 | cc2 | cc3);-- case SLJIT_OVERFLOW:- if (compiler->status_flags_state & SLJIT_SET_Z)- return (cc2 | cc3);- /* fallthrough */-- case SLJIT_UNORDERED_F64:- return cc3;-- case SLJIT_NOT_OVERFLOW:- if (compiler->status_flags_state & SLJIT_SET_Z)- return (cc0 | cc1);- /* fallthrough */-- case SLJIT_ORDERED_F64:- return (cc0 | cc1 | cc2);-- case SLJIT_GREATER_F64:- return cc2;-- case SLJIT_GREATER_EQUAL_F64:- return (cc0 | cc2);- }-- SLJIT_UNREACHABLE();- return (sljit_u8)-1;-}--/* Facility to bit index mappings.- Note: some facilities share the same bit index. */-typedef sljit_uw facility_bit;-#define STORE_FACILITY_LIST_EXTENDED_FACILITY 7-#define FAST_LONG_DISPLACEMENT_FACILITY 19-#define EXTENDED_IMMEDIATE_FACILITY 21-#define GENERAL_INSTRUCTION_EXTENSION_FACILITY 34-#define DISTINCT_OPERAND_FACILITY 45-#define HIGH_WORD_FACILITY 45-#define POPULATION_COUNT_FACILITY 45-#define LOAD_STORE_ON_CONDITION_1_FACILITY 45-#define MISCELLANEOUS_INSTRUCTION_EXTENSIONS_1_FACILITY 49-#define LOAD_STORE_ON_CONDITION_2_FACILITY 53-#define MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY 58-#define VECTOR_FACILITY 129-#define VECTOR_ENHANCEMENTS_1_FACILITY 135--/* Report whether a facility is known to be present due to the compiler- settings. This function should always be compiled to a constant- value given a constant argument. */-static SLJIT_INLINE int have_facility_static(facility_bit x)-{-#if ENABLE_STATIC_FACILITY_DETECTION- switch (x) {- case FAST_LONG_DISPLACEMENT_FACILITY:- return (__ARCH__ >= 6 /* z990 */);- case EXTENDED_IMMEDIATE_FACILITY:- case STORE_FACILITY_LIST_EXTENDED_FACILITY:- return (__ARCH__ >= 7 /* z9-109 */);- case GENERAL_INSTRUCTION_EXTENSION_FACILITY:- return (__ARCH__ >= 8 /* z10 */);- case DISTINCT_OPERAND_FACILITY:- return (__ARCH__ >= 9 /* z196 */);- case MISCELLANEOUS_INSTRUCTION_EXTENSIONS_1_FACILITY:- return (__ARCH__ >= 10 /* zEC12 */);- case LOAD_STORE_ON_CONDITION_2_FACILITY:- case VECTOR_FACILITY:- return (__ARCH__ >= 11 /* z13 */);- case MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY:- case VECTOR_ENHANCEMENTS_1_FACILITY:- return (__ARCH__ >= 12 /* z14 */);- default:- SLJIT_UNREACHABLE();- }-#endif- return 0;-}--static SLJIT_INLINE unsigned long get_hwcap()-{- static unsigned long hwcap = 0;- if (SLJIT_UNLIKELY(!hwcap)) {- hwcap = getauxval(AT_HWCAP);- SLJIT_ASSERT(hwcap != 0);- }- return hwcap;-}--static SLJIT_INLINE int have_stfle()-{- if (have_facility_static(STORE_FACILITY_LIST_EXTENDED_FACILITY))- return 1;-- return (get_hwcap() & HWCAP_S390_STFLE);-}--/* Report whether the given facility is available. This function always- performs a runtime check. */-static int have_facility_dynamic(facility_bit x)-{-#if ENABLE_DYNAMIC_FACILITY_DETECTION- static struct {- sljit_uw bits[4];- } cpu_features;- size_t size = sizeof(cpu_features);- const sljit_uw word_index = x >> 6;- const sljit_uw bit_index = ((1UL << 63) >> (x & 63));-- SLJIT_ASSERT(x < size * 8);- if (SLJIT_UNLIKELY(!have_stfle()))- return 0;-- if (SLJIT_UNLIKELY(cpu_features.bits[0] == 0)) {- __asm__ __volatile__ (- "lgr %%r0, %0;"- "stfle 0(%1);"- /* outputs */:- /* inputs */: "d" ((size / 8) - 1), "a" (&cpu_features)- /* clobbers */: "r0", "cc", "memory"- );- SLJIT_ASSERT(cpu_features.bits[0] != 0);- }- return (cpu_features.bits[word_index] & bit_index) != 0;-#else- return 0;-#endif-}--#define HAVE_FACILITY(name, bit) \-static SLJIT_INLINE int name() \-{ \- static int have = -1; \- /* Static check first. May allow the function to be optimized away. */ \- if (have_facility_static(bit)) \- have = 1; \- else if (SLJIT_UNLIKELY(have < 0)) \- have = have_facility_dynamic(bit) ? 1 : 0; \-\- return have; \-}--HAVE_FACILITY(have_eimm, EXTENDED_IMMEDIATE_FACILITY)-HAVE_FACILITY(have_ldisp, FAST_LONG_DISPLACEMENT_FACILITY)-HAVE_FACILITY(have_genext, GENERAL_INSTRUCTION_EXTENSION_FACILITY)-HAVE_FACILITY(have_lscond1, LOAD_STORE_ON_CONDITION_1_FACILITY)-HAVE_FACILITY(have_lscond2, LOAD_STORE_ON_CONDITION_2_FACILITY)-HAVE_FACILITY(have_misc2, MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY)-#undef HAVE_FACILITY--#define is_u12(d) (0 <= (d) && (d) <= 0x00000fffL)-#define is_u32(d) (0 <= (d) && (d) <= 0xffffffffL)--#define CHECK_SIGNED(v, bitlen) \- ((v) >= -(1 << ((bitlen) - 1)) && (v) < (1 << ((bitlen) - 1)))--#define is_s8(d) CHECK_SIGNED((d), 8)-#define is_s16(d) CHECK_SIGNED((d), 16)-#define is_s20(d) CHECK_SIGNED((d), 20)-#define is_s32(d) ((d) == (sljit_s32)(d))--static SLJIT_INLINE sljit_ins disp_s20(sljit_s32 d)-{- SLJIT_ASSERT(is_s20(d));-- sljit_uw dh = (d >> 12) & 0xff;- sljit_uw dl = (d << 8) & 0xfff00;- return (dh | dl) << 8;-}--/* TODO(carenas): variadic macro is not strictly needed */-#define SLJIT_S390X_INSTRUCTION(op, ...) \-static SLJIT_INLINE sljit_ins op(__VA_ARGS__)--/* RR form instructions. */-#define SLJIT_S390X_RR(name, pattern) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src) \-{ \- return (pattern) | ((dst & 0xf) << 4) | (src & 0xf); \-}--/* AND */-SLJIT_S390X_RR(nr, 0x1400)--/* BRANCH AND SAVE */-SLJIT_S390X_RR(basr, 0x0d00)--/* BRANCH ON CONDITION */-SLJIT_S390X_RR(bcr, 0x0700) /* TODO(mundaym): type for mask? */--/* DIVIDE */-SLJIT_S390X_RR(dr, 0x1d00)--/* EXCLUSIVE OR */-SLJIT_S390X_RR(xr, 0x1700)--/* LOAD */-SLJIT_S390X_RR(lr, 0x1800)--/* LOAD COMPLEMENT */-SLJIT_S390X_RR(lcr, 0x1300)--/* OR */-SLJIT_S390X_RR(or, 0x1600)--#undef SLJIT_S390X_RR--/* RRE form instructions */-#define SLJIT_S390X_RRE(name, pattern) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src) \-{ \- return (pattern) | R4A(dst) | R0A(src); \-}--/* AND */-SLJIT_S390X_RRE(ngr, 0xb9800000)--/* DIVIDE LOGICAL */-SLJIT_S390X_RRE(dlr, 0xb9970000)-SLJIT_S390X_RRE(dlgr, 0xb9870000)--/* DIVIDE SINGLE */-SLJIT_S390X_RRE(dsgr, 0xb90d0000)--/* EXCLUSIVE OR */-SLJIT_S390X_RRE(xgr, 0xb9820000)--/* LOAD */-SLJIT_S390X_RRE(lgr, 0xb9040000)-SLJIT_S390X_RRE(lgfr, 0xb9140000)--/* LOAD BYTE */-SLJIT_S390X_RRE(lbr, 0xb9260000)-SLJIT_S390X_RRE(lgbr, 0xb9060000)--/* LOAD COMPLEMENT */-SLJIT_S390X_RRE(lcgr, 0xb9030000)--/* LOAD HALFWORD */-SLJIT_S390X_RRE(lhr, 0xb9270000)-SLJIT_S390X_RRE(lghr, 0xb9070000)--/* LOAD LOGICAL */-SLJIT_S390X_RRE(llgfr, 0xb9160000)--/* LOAD LOGICAL CHARACTER */-SLJIT_S390X_RRE(llcr, 0xb9940000)-SLJIT_S390X_RRE(llgcr, 0xb9840000)--/* LOAD LOGICAL HALFWORD */-SLJIT_S390X_RRE(llhr, 0xb9950000)-SLJIT_S390X_RRE(llghr, 0xb9850000)--/* MULTIPLY LOGICAL */-SLJIT_S390X_RRE(mlgr, 0xb9860000)--/* MULTIPLY SINGLE */-SLJIT_S390X_RRE(msgfr, 0xb91c0000)--/* OR */-SLJIT_S390X_RRE(ogr, 0xb9810000)--/* SUBTRACT */-SLJIT_S390X_RRE(sgr, 0xb9090000)--#undef SLJIT_S390X_RRE--/* RI-a form instructions */-#define SLJIT_S390X_RIA(name, pattern, imm_type) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \-{ \- return (pattern) | R20A(reg) | (imm & 0xffff); \-}--/* ADD HALFWORD IMMEDIATE */-SLJIT_S390X_RIA(aghi, 0xa70b0000, sljit_s16)--/* LOAD HALFWORD IMMEDIATE */-SLJIT_S390X_RIA(lhi, 0xa7080000, sljit_s16)-SLJIT_S390X_RIA(lghi, 0xa7090000, sljit_s16)--/* LOAD LOGICAL IMMEDIATE */-SLJIT_S390X_RIA(llihh, 0xa50c0000, sljit_u16)-SLJIT_S390X_RIA(llihl, 0xa50d0000, sljit_u16)-SLJIT_S390X_RIA(llilh, 0xa50e0000, sljit_u16)-SLJIT_S390X_RIA(llill, 0xa50f0000, sljit_u16)--/* MULTIPLY HALFWORD IMMEDIATE */-SLJIT_S390X_RIA(mhi, 0xa70c0000, sljit_s16)-SLJIT_S390X_RIA(mghi, 0xa70d0000, sljit_s16)--/* OR IMMEDIATE */-SLJIT_S390X_RIA(oilh, 0xa50a0000, sljit_u16)--#undef SLJIT_S390X_RIA--/* RIL-a form instructions (requires extended immediate facility) */-#define SLJIT_S390X_RILA(name, pattern, imm_type) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \-{ \- SLJIT_ASSERT(have_eimm()); \- return (pattern) | R36A(reg) | ((sljit_ins)imm & 0xffffffffu); \-}--/* ADD IMMEDIATE */-SLJIT_S390X_RILA(agfi, 0xc20800000000, sljit_s32)--/* ADD IMMEDIATE HIGH */-SLJIT_S390X_RILA(aih, 0xcc0800000000, sljit_s32) /* TODO(mundaym): high-word facility? */--/* AND IMMEDIATE */-SLJIT_S390X_RILA(nihf, 0xc00a00000000, sljit_u32)--/* EXCLUSIVE OR IMMEDIATE */-SLJIT_S390X_RILA(xilf, 0xc00700000000, sljit_u32)--/* INSERT IMMEDIATE */-SLJIT_S390X_RILA(iihf, 0xc00800000000, sljit_u32)-SLJIT_S390X_RILA(iilf, 0xc00900000000, sljit_u32)--/* LOAD IMMEDIATE */-SLJIT_S390X_RILA(lgfi, 0xc00100000000, sljit_s32)--/* LOAD LOGICAL IMMEDIATE */-SLJIT_S390X_RILA(llihf, 0xc00e00000000, sljit_u32)-SLJIT_S390X_RILA(llilf, 0xc00f00000000, sljit_u32)--/* SUBTRACT LOGICAL IMMEDIATE */-SLJIT_S390X_RILA(slfi, 0xc20500000000, sljit_u32)--#undef SLJIT_S390X_RILA--/* RX-a form instructions */-#define SLJIT_S390X_RXA(name, pattern) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b) \-{ \- SLJIT_ASSERT((d & 0xfff) == d); \-\- return (pattern) | R20A(r) | R16A(x) | R12A(b) | (sljit_ins)(d & 0xfff); \-}--/* LOAD */-SLJIT_S390X_RXA(l, 0x58000000)--/* LOAD ADDRESS */-SLJIT_S390X_RXA(la, 0x41000000)--/* LOAD HALFWORD */-SLJIT_S390X_RXA(lh, 0x48000000)--/* MULTIPLY SINGLE */-SLJIT_S390X_RXA(ms, 0x71000000)--/* STORE */-SLJIT_S390X_RXA(st, 0x50000000)--/* STORE CHARACTER */-SLJIT_S390X_RXA(stc, 0x42000000)--/* STORE HALFWORD */-SLJIT_S390X_RXA(sth, 0x40000000)--#undef SLJIT_S390X_RXA--/* RXY-a instructions */-#define SLJIT_S390X_RXYA(name, pattern, cond) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b) \-{ \- SLJIT_ASSERT(cond); \-\- return (pattern) | R36A(r) | R32A(x) | R28A(b) | disp_s20(d); \-}--/* LOAD */-SLJIT_S390X_RXYA(ly, 0xe30000000058, have_ldisp())-SLJIT_S390X_RXYA(lg, 0xe30000000004, 1)-SLJIT_S390X_RXYA(lgf, 0xe30000000014, 1)--/* LOAD BYTE */-SLJIT_S390X_RXYA(lb, 0xe30000000076, have_ldisp())-SLJIT_S390X_RXYA(lgb, 0xe30000000077, have_ldisp())--/* LOAD HALFWORD */-SLJIT_S390X_RXYA(lhy, 0xe30000000078, have_ldisp())-SLJIT_S390X_RXYA(lgh, 0xe30000000015, 1)--/* LOAD LOGICAL */-SLJIT_S390X_RXYA(llgf, 0xe30000000016, 1)--/* LOAD LOGICAL CHARACTER */-SLJIT_S390X_RXYA(llc, 0xe30000000094, have_eimm())-SLJIT_S390X_RXYA(llgc, 0xe30000000090, 1)--/* LOAD LOGICAL HALFWORD */-SLJIT_S390X_RXYA(llh, 0xe30000000095, have_eimm())-SLJIT_S390X_RXYA(llgh, 0xe30000000091, 1)--/* MULTIPLY SINGLE */-SLJIT_S390X_RXYA(msy, 0xe30000000051, have_ldisp())-SLJIT_S390X_RXYA(msg, 0xe3000000000c, 1)--/* STORE */-SLJIT_S390X_RXYA(sty, 0xe30000000050, have_ldisp())-SLJIT_S390X_RXYA(stg, 0xe30000000024, 1)--/* STORE CHARACTER */-SLJIT_S390X_RXYA(stcy, 0xe30000000072, have_ldisp())--/* STORE HALFWORD */-SLJIT_S390X_RXYA(sthy, 0xe30000000070, have_ldisp())--#undef SLJIT_S390X_RXYA--/* RSY-a instructions */-#define SLJIT_S390X_RSYA(name, pattern, cond) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_s32 d, sljit_gpr b) \-{ \- SLJIT_ASSERT(cond); \-\- return (pattern) | R36A(dst) | R32A(src) | R28A(b) | disp_s20(d); \-}--/* LOAD MULTIPLE */-SLJIT_S390X_RSYA(lmg, 0xeb0000000004, 1)--/* SHIFT LEFT LOGICAL */-SLJIT_S390X_RSYA(sllg, 0xeb000000000d, 1)--/* SHIFT RIGHT SINGLE */-SLJIT_S390X_RSYA(srag, 0xeb000000000a, 1)--/* STORE MULTIPLE */-SLJIT_S390X_RSYA(stmg, 0xeb0000000024, 1)--#undef SLJIT_S390X_RSYA--/* RIE-f instructions (require general-instructions-extension facility) */-#define SLJIT_S390X_RIEF(name, pattern) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_u8 start, sljit_u8 end, sljit_u8 rot) \-{ \- sljit_ins i3, i4, i5; \-\- SLJIT_ASSERT(have_genext()); \- i3 = (sljit_ins)start << 24; \- i4 = (sljit_ins)end << 16; \- i5 = (sljit_ins)rot << 8; \-\- return (pattern) | R36A(dst & 0xf) | R32A(src & 0xf) | i3 | i4 | i5; \-}--/* ROTATE THEN AND SELECTED BITS */-/* SLJIT_S390X_RIEF(rnsbg, 0xec0000000054) */--/* ROTATE THEN EXCLUSIVE OR SELECTED BITS */-/* SLJIT_S390X_RIEF(rxsbg, 0xec0000000057) */--/* ROTATE THEN OR SELECTED BITS */-SLJIT_S390X_RIEF(rosbg, 0xec0000000056)--/* ROTATE THEN INSERT SELECTED BITS */-/* SLJIT_S390X_RIEF(risbg, 0xec0000000055) */-/* SLJIT_S390X_RIEF(risbgn, 0xec0000000059) */--/* ROTATE THEN INSERT SELECTED BITS HIGH */-SLJIT_S390X_RIEF(risbhg, 0xec000000005d)--/* ROTATE THEN INSERT SELECTED BITS LOW */-/* SLJIT_S390X_RIEF(risblg, 0xec0000000051) */--#undef SLJIT_S390X_RIEF--/* RRF-c instructions (require load/store-on-condition 1 facility) */-#define SLJIT_S390X_RRFC(name, pattern) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_uw mask) \-{ \- sljit_ins m3; \-\- SLJIT_ASSERT(have_lscond1()); \- m3 = (sljit_ins)(mask & 0xf) << 12; \-\- return (pattern) | m3 | R4A(dst) | R0A(src); \-}--/* LOAD HALFWORD IMMEDIATE ON CONDITION */-SLJIT_S390X_RRFC(locr, 0xb9f20000)-SLJIT_S390X_RRFC(locgr, 0xb9e20000)--#undef SLJIT_S390X_RRFC--/* RIE-g instructions (require load/store-on-condition 2 facility) */-#define SLJIT_S390X_RIEG(name, pattern) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw imm, sljit_uw mask) \-{ \- sljit_ins m3, i2; \-\- SLJIT_ASSERT(have_lscond2()); \- m3 = (sljit_ins)(mask & 0xf) << 32; \- i2 = (sljit_ins)(imm & 0xffffL) << 16; \-\- return (pattern) | R36A(reg) | m3 | i2; \-}--/* LOAD HALFWORD IMMEDIATE ON CONDITION */-SLJIT_S390X_RIEG(lochi, 0xec0000000042)-SLJIT_S390X_RIEG(locghi, 0xec0000000046)--#undef SLJIT_S390X_RIEG--#define SLJIT_S390X_RILB(name, pattern, cond) \-SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw ri) \-{ \- SLJIT_ASSERT(cond); \-\- return (pattern) | R36A(reg) | (sljit_ins)(ri & 0xffffffff); \-}--/* BRANCH RELATIVE AND SAVE LONG */-SLJIT_S390X_RILB(brasl, 0xc00500000000, 1)--/* LOAD ADDRESS RELATIVE LONG */-SLJIT_S390X_RILB(larl, 0xc00000000000, 1)--/* LOAD RELATIVE LONG */-SLJIT_S390X_RILB(lgrl, 0xc40800000000, have_genext())--#undef SLJIT_S390X_RILB--SLJIT_S390X_INSTRUCTION(br, sljit_gpr target)-{- return 0x07f0 | target;-}--SLJIT_S390X_INSTRUCTION(brc, sljit_uw mask, sljit_sw target)-{- sljit_ins m1 = (sljit_ins)(mask & 0xf) << 20;- sljit_ins ri2 = (sljit_ins)target & 0xffff;- return 0xa7040000L | m1 | ri2;-}--SLJIT_S390X_INSTRUCTION(brcl, sljit_uw mask, sljit_sw target)-{- sljit_ins m1 = (sljit_ins)(mask & 0xf) << 36;- sljit_ins ri2 = (sljit_ins)target & 0xffffffff;- return 0xc00400000000L | m1 | ri2;-}--SLJIT_S390X_INSTRUCTION(flogr, sljit_gpr dst, sljit_gpr src)-{- SLJIT_ASSERT(have_eimm());- return 0xb9830000 | R8A(dst) | R0A(src);-}--/* INSERT PROGRAM MASK */-SLJIT_S390X_INSTRUCTION(ipm, sljit_gpr dst)-{- return 0xb2220000 | R4A(dst);-}--/* SET PROGRAM MASK */-SLJIT_S390X_INSTRUCTION(spm, sljit_gpr dst)-{- return 0x0400 | R4A(dst);-}--/* ROTATE THEN INSERT SELECTED BITS HIGH (ZERO) */-SLJIT_S390X_INSTRUCTION(risbhgz, sljit_gpr dst, sljit_gpr src, sljit_u8 start, sljit_u8 end, sljit_u8 rot)-{- return risbhg(dst, src, start, 0x8 | end, rot);-}--#undef SLJIT_S390X_INSTRUCTION--static sljit_s32 update_zero_overflow(struct sljit_compiler *compiler, sljit_s32 op, sljit_gpr dst_r)-{- /* Condition codes: bits 18 and 19.- Transformation:- 0 (zero and no overflow) : unchanged- 1 (non-zero and no overflow) : unchanged- 2 (zero and overflow) : decreased by 1- 3 (non-zero and overflow) : decreased by 1 if non-zero */- FAIL_IF(push_inst(compiler, brc(0xc, 2 + 2 + ((op & SLJIT_32) ? 1 : 2) + 2 + 3 + 1)));- FAIL_IF(push_inst(compiler, ipm(tmp1)));- FAIL_IF(push_inst(compiler, (op & SLJIT_32) ? or(dst_r, dst_r) : ogr(dst_r, dst_r)));- FAIL_IF(push_inst(compiler, brc(0x8, 2 + 3)));- FAIL_IF(push_inst(compiler, slfi(tmp1, 0x10000000)));- FAIL_IF(push_inst(compiler, spm(tmp1)));- return SLJIT_SUCCESS;-}--/* load 64-bit immediate into register without clobbering flags */-static sljit_s32 push_load_imm_inst(struct sljit_compiler *compiler, sljit_gpr target, sljit_sw v)-{- /* 4 byte instructions */- if (is_s16(v))- return push_inst(compiler, lghi(target, (sljit_s16)v));-- if (((sljit_uw)v & ~(sljit_uw)0x000000000000ffff) == 0)- return push_inst(compiler, llill(target, (sljit_u16)v));-- if (((sljit_uw)v & ~(sljit_uw)0x00000000ffff0000) == 0)- return push_inst(compiler, llilh(target, (sljit_u16)(v >> 16)));-- if (((sljit_uw)v & ~(sljit_uw)0x0000ffff00000000) == 0)- return push_inst(compiler, llihl(target, (sljit_u16)(v >> 32)));-- if (((sljit_uw)v & ~(sljit_uw)0xffff000000000000) == 0)- return push_inst(compiler, llihh(target, (sljit_u16)(v >> 48)));-- /* 6 byte instructions (requires extended immediate facility) */- if (have_eimm()) {- if (is_s32(v))- return push_inst(compiler, lgfi(target, (sljit_s32)v));-- if (((sljit_uw)v >> 32) == 0)- return push_inst(compiler, llilf(target, (sljit_u32)v));-- if (((sljit_uw)v << 32) == 0)- return push_inst(compiler, llihf(target, (sljit_u32)((sljit_uw)v >> 32)));-- FAIL_IF(push_inst(compiler, llilf(target, (sljit_u32)v)));- return push_inst(compiler, iihf(target, (sljit_u32)(v >> 32)));- }-- /* TODO(mundaym): instruction sequences that don't use extended immediates */- abort();-}--struct addr {- sljit_gpr base;- sljit_gpr index;- sljit_s32 offset;-};--/* transform memory operand into D(X,B) form with a signed 20-bit offset */-static sljit_s32 make_addr_bxy(struct sljit_compiler *compiler,- struct addr *addr, sljit_s32 mem, sljit_sw off,- sljit_gpr tmp /* clobbered, must not be r0 */)-{- sljit_gpr base = r0;- sljit_gpr index = r0;-- SLJIT_ASSERT(tmp != r0);- if (mem & REG_MASK)- base = gpr(mem & REG_MASK);-- if (mem & OFFS_REG_MASK) {- index = gpr(OFFS_REG(mem));- if (off != 0) {- /* shift and put the result into tmp */- SLJIT_ASSERT(0 <= off && off < 64);- FAIL_IF(push_inst(compiler, sllg(tmp, index, (sljit_s32)off, 0)));- index = tmp;- off = 0; /* clear offset */- }- }- else if (!is_s20(off)) {- FAIL_IF(push_load_imm_inst(compiler, tmp, off));- index = tmp;- off = 0; /* clear offset */- }- addr->base = base;- addr->index = index;- addr->offset = (sljit_s32)off;- return SLJIT_SUCCESS;-}--/* transform memory operand into D(X,B) form with an unsigned 12-bit offset */-static sljit_s32 make_addr_bx(struct sljit_compiler *compiler,- struct addr *addr, sljit_s32 mem, sljit_sw off,- sljit_gpr tmp /* clobbered, must not be r0 */)-{- sljit_gpr base = r0;- sljit_gpr index = r0;-- SLJIT_ASSERT(tmp != r0);- if (mem & REG_MASK)- base = gpr(mem & REG_MASK);-- if (mem & OFFS_REG_MASK) {- index = gpr(OFFS_REG(mem));- if (off != 0) {- /* shift and put the result into tmp */- SLJIT_ASSERT(0 <= off && off < 64);- FAIL_IF(push_inst(compiler, sllg(tmp, index, (sljit_s32)off, 0)));- index = tmp;- off = 0; /* clear offset */- }- }- else if (!is_u12(off)) {- FAIL_IF(push_load_imm_inst(compiler, tmp, off));- index = tmp;- off = 0; /* clear offset */- }- addr->base = base;- addr->index = index;- addr->offset = (sljit_s32)off;- return SLJIT_SUCCESS;-}--#define EVAL(op, r, addr) op(r, addr.offset, addr.index, addr.base)-#define WHEN(cond, r, i1, i2, addr) \- (cond) ? EVAL(i1, r, addr) : EVAL(i2, r, addr)--/* May clobber tmp1. */-static sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst,- sljit_s32 src, sljit_sw srcw,- sljit_s32 is_32bit)-{- struct addr addr;- sljit_ins ins;-- SLJIT_ASSERT(src & SLJIT_MEM);- if (have_ldisp() || !is_32bit)- FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1));- else- FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1));-- if (is_32bit)- ins = WHEN(is_u12(addr.offset), dst, l, ly, addr);- else- ins = lg(dst, addr.offset, addr.index, addr.base);-- return push_inst(compiler, ins);-}--/* May clobber tmp1. */-static sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src,- sljit_s32 dst, sljit_sw dstw,- sljit_s32 is_32bit)-{- struct addr addr;- sljit_ins ins;-- SLJIT_ASSERT(dst & SLJIT_MEM);- if (have_ldisp() || !is_32bit)- FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1));- else- FAIL_IF(make_addr_bx(compiler, &addr, dst, dstw, tmp1));-- if (is_32bit)- ins = WHEN(is_u12(addr.offset), src, st, sty, addr);- else- ins = stg(src, addr.offset, addr.index, addr.base);-- return push_inst(compiler, ins);-}--#undef WHEN--static sljit_s32 emit_move(struct sljit_compiler *compiler,- sljit_gpr dst_r,- sljit_s32 src, sljit_sw srcw)-{- SLJIT_ASSERT(!IS_GPR_REG(src) || dst_r != gpr(src & REG_MASK));-- if (src & SLJIT_IMM)- return push_load_imm_inst(compiler, dst_r, srcw);-- if (src & SLJIT_MEM)- return load_word(compiler, dst_r, src, srcw, (compiler->mode & SLJIT_32) != 0);-- sljit_gpr src_r = gpr(src & REG_MASK);- return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, src_r) : lgr(dst_r, src_r));-}--static sljit_s32 emit_rr(struct sljit_compiler *compiler, sljit_ins ins,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_gpr dst_r = tmp0;- sljit_gpr src_r = tmp1;- sljit_s32 needs_move = 1;-- if (FAST_IS_REG(dst)) {- dst_r = gpr(dst);-- if (dst == src1)- needs_move = 0;- else if (dst == src2) {- dst_r = tmp0;- needs_move = 2;- }- }-- if (needs_move)- FAIL_IF(emit_move(compiler, dst_r, src1, src1w));-- if (FAST_IS_REG(src2))- src_r = gpr(src2);- else- FAIL_IF(emit_move(compiler, tmp1, src2, src2w));-- FAIL_IF(push_inst(compiler, ins | R4A(dst_r) | R0A(src_r)));-- if (needs_move != 2)- return SLJIT_SUCCESS;-- dst_r = gpr(dst & REG_MASK);- return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));-}--static sljit_s32 emit_rr1(struct sljit_compiler *compiler, sljit_ins ins,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w)-{- sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;- sljit_gpr src_r = tmp1;-- if (FAST_IS_REG(src1))- src_r = gpr(src1);- else- FAIL_IF(emit_move(compiler, tmp1, src1, src1w));-- return push_inst(compiler, ins | R4A(dst_r) | R0A(src_r));-}--static sljit_s32 emit_rrf(struct sljit_compiler *compiler, sljit_ins ins,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;- sljit_gpr src1_r = tmp0;- sljit_gpr src2_r = tmp1;-- if (FAST_IS_REG(src1))- src1_r = gpr(src1);- else- FAIL_IF(emit_move(compiler, tmp0, src1, src1w));-- if (FAST_IS_REG(src2))- src2_r = gpr(src2);- else- FAIL_IF(emit_move(compiler, tmp1, src2, src2w));-- return push_inst(compiler, ins | R4A(dst_r) | R0A(src1_r) | R12A(src2_r));-}--typedef enum {- RI_A,- RIL_A,-} emit_ril_type;--static sljit_s32 emit_ri(struct sljit_compiler *compiler, sljit_ins ins,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_sw src2w,- emit_ril_type type)-{- sljit_gpr dst_r = tmp0;- sljit_s32 needs_move = 1;-- if (FAST_IS_REG(dst)) {- dst_r = gpr(dst);-- if (dst == src1)- needs_move = 0;- }-- if (needs_move)- FAIL_IF(emit_move(compiler, dst_r, src1, src1w));-- if (type == RIL_A)- return push_inst(compiler, ins | R36A(dst_r) | (src2w & 0xffffffff));- return push_inst(compiler, ins | R20A(dst_r) | (src2w & 0xffff));-}--static sljit_s32 emit_rie_d(struct sljit_compiler *compiler, sljit_ins ins,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_sw src2w)-{- sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;- sljit_gpr src_r = tmp0;-- if (!FAST_IS_REG(src1))- FAIL_IF(emit_move(compiler, tmp0, src1, src1w));- else- src_r = gpr(src1 & REG_MASK);-- return push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | (sljit_ins)(src2w & 0xffff) << 16);-}--typedef enum {- RX_A,- RXY_A,-} emit_rx_type;--static sljit_s32 emit_rx(struct sljit_compiler *compiler, sljit_ins ins,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w,- emit_rx_type type)-{- sljit_gpr dst_r = tmp0;- sljit_s32 needs_move = 1;- sljit_gpr base, index;-- SLJIT_ASSERT(src2 & SLJIT_MEM);-- if (FAST_IS_REG(dst)) {- dst_r = gpr(dst);-- if (dst == src1)- needs_move = 0;- else if (dst == (src2 & REG_MASK) || (dst == OFFS_REG(src2))) {- dst_r = tmp0;- needs_move = 2;- }- }-- if (needs_move)- FAIL_IF(emit_move(compiler, dst_r, src1, src1w));-- base = gpr(src2 & REG_MASK);- index = tmp0;-- if (src2 & OFFS_REG_MASK) {- index = gpr(OFFS_REG(src2));-- if (src2w != 0) {- FAIL_IF(push_inst(compiler, sllg(tmp1, index, src2w & 0x3, 0)));- src2w = 0;- index = tmp1;- }- } else if ((type == RX_A && !is_u12(src2w)) || (type == RXY_A && !is_s20(src2w))) {- FAIL_IF(push_load_imm_inst(compiler, tmp1, src2w));-- if (src2 & REG_MASK)- index = tmp1;- else- base = tmp1;- src2w = 0;- }-- if (type == RX_A)- ins |= R20A(dst_r) | R16A(index) | R12A(base) | (sljit_ins)src2w;- else- ins |= R36A(dst_r) | R32A(index) | R28A(base) | disp_s20((sljit_s32)src2w);-- FAIL_IF(push_inst(compiler, ins));-- if (needs_move != 2)- return SLJIT_SUCCESS;-- dst_r = gpr(dst);- return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));-}--static sljit_s32 emit_siy(struct sljit_compiler *compiler, sljit_ins ins,- sljit_s32 dst, sljit_sw dstw,- sljit_sw srcw)-{- SLJIT_ASSERT(dst & SLJIT_MEM);-- sljit_gpr dst_r = tmp1;-- if (dst & OFFS_REG_MASK) {- sljit_gpr index = tmp1;-- if ((dstw & 0x3) == 0)- index = gpr(OFFS_REG(dst));- else- FAIL_IF(push_inst(compiler, sllg(tmp1, index, dstw & 0x3, 0)));-- FAIL_IF(push_inst(compiler, la(tmp1, 0, dst_r, index)));- dstw = 0;- }- else if (!is_s20(dstw)) {- FAIL_IF(push_load_imm_inst(compiler, tmp1, dstw));-- if (dst & REG_MASK)- FAIL_IF(push_inst(compiler, la(tmp1, 0, dst_r, tmp1)));-- dstw = 0;- }- else- dst_r = gpr(dst & REG_MASK);-- return push_inst(compiler, ins | ((sljit_ins)(srcw & 0xff) << 32) | R28A(dst_r) | disp_s20((sljit_s32)dstw));-}--struct ins_forms {- sljit_ins op_r;- sljit_ins op_gr;- sljit_ins op_rk;- sljit_ins op_grk;- sljit_ins op;- sljit_ins op_y;- sljit_ins op_g;-};--static sljit_s32 emit_commutative(struct sljit_compiler *compiler, const struct ins_forms *forms,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_s32 mode = compiler->mode;- sljit_ins ins, ins_k;-- if ((src1 | src2) & SLJIT_MEM) {- sljit_ins ins12, ins20;-- if (mode & SLJIT_32) {- ins12 = forms->op;- ins20 = forms->op_y;- }- else {- ins12 = 0;- ins20 = forms->op_g;- }-- if (ins12 && ins20) {- /* Extra instructions needed for address computation can be executed independently. */- if ((src2 & SLJIT_MEM) && (!(src1 & SLJIT_MEM)- || ((src1 & OFFS_REG_MASK) ? (src1w & 0x3) == 0 : is_s20(src1w)))) {- if ((src2 & OFFS_REG_MASK) || is_u12(src2w) || !is_s20(src2w))- return emit_rx(compiler, ins12, dst, src1, src1w, src2, src2w, RX_A);-- return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);- }-- if (src1 & SLJIT_MEM) {- if ((src1 & OFFS_REG_MASK) || is_u12(src1w) || !is_s20(src1w))- return emit_rx(compiler, ins12, dst, src2, src2w, src1, src1w, RX_A);-- return emit_rx(compiler, ins20, dst, src2, src2w, src1, src1w, RXY_A);- }- }- else if (ins12 || ins20) {- emit_rx_type rx_type;-- if (ins12) {- rx_type = RX_A;- ins = ins12;- }- else {- rx_type = RXY_A;- ins = ins20;- }-- if ((src2 & SLJIT_MEM) && (!(src1 & SLJIT_MEM)- || ((src1 & OFFS_REG_MASK) ? (src1w & 0x3) == 0 : (rx_type == RX_A ? is_u12(src1w) : is_s20(src1w)))))- return emit_rx(compiler, ins, dst, src1, src1w, src2, src2w, rx_type);-- if (src1 & SLJIT_MEM)- return emit_rx(compiler, ins, dst, src2, src2w, src1, src1w, rx_type);- }- }-- if (mode & SLJIT_32) {- ins = forms->op_r;- ins_k = forms->op_rk;- }- else {- ins = forms->op_gr;- ins_k = forms->op_grk;- }-- SLJIT_ASSERT(ins != 0 || ins_k != 0);-- if (ins && FAST_IS_REG(dst)) {- if (dst == src1)- return emit_rr(compiler, ins, dst, src1, src1w, src2, src2w);-- if (dst == src2)- return emit_rr(compiler, ins, dst, src2, src2w, src1, src1w);- }-- if (ins_k == 0)- return emit_rr(compiler, ins, dst, src1, src1w, src2, src2w);-- return emit_rrf(compiler, ins_k, dst, src1, src1w, src2, src2w);-}--static sljit_s32 emit_non_commutative(struct sljit_compiler *compiler, const struct ins_forms *forms,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_s32 mode = compiler->mode;- sljit_ins ins;-- if (src2 & SLJIT_MEM) {- sljit_ins ins12, ins20;-- if (mode & SLJIT_32) {- ins12 = forms->op;- ins20 = forms->op_y;- }- else {- ins12 = 0;- ins20 = forms->op_g;- }-- if (ins12 && ins20) {- if ((src2 & OFFS_REG_MASK) || is_u12(src2w) || !is_s20(src2w))- return emit_rx(compiler, ins12, dst, src1, src1w, src2, src2w, RX_A);-- return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);- }- else if (ins12)- return emit_rx(compiler, ins12, dst, src1, src1w, src2, src2w, RX_A);- else if (ins20)- return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);- }-- ins = (mode & SLJIT_32) ? forms->op_rk : forms->op_grk;-- if (ins == 0 || (FAST_IS_REG(dst) && dst == src1))- return emit_rr(compiler, (mode & SLJIT_32) ? forms->op_r : forms->op_gr, dst, src1, src1w, src2, src2w);-- return emit_rrf(compiler, ins, dst, src1, src1w, src2, src2w);-}--SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)-{- struct sljit_label *label;- struct sljit_jump *jump;- struct sljit_s390x_const *const_;- struct sljit_put_label *put_label;- sljit_sw executable_offset;- sljit_uw ins_size = 0; /* instructions */- sljit_uw pool_size = 0; /* literal pool */- sljit_uw pad_size;- sljit_uw i, j = 0;- struct sljit_memory_fragment *buf;- void *code, *code_ptr;- sljit_uw *pool, *pool_ptr;- sljit_sw source, offset; /* TODO(carenas): only need 32 bit */-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_generate_code(compiler));- reverse_buf(compiler);-- /* branch handling */- label = compiler->labels;- jump = compiler->jumps;- put_label = compiler->put_labels;-- /* TODO(carenas): compiler->executable_size could be calculated- * before to avoid the following loop (except for- * pool_size)- */- /* calculate the size of the code */- for (buf = compiler->buf; buf != NULL; buf = buf->next) {- sljit_uw len = buf->used_size / sizeof(sljit_ins);- sljit_ins *ibuf = (sljit_ins *)buf->memory;- for (i = 0; i < len; ++i, ++j) {- sljit_ins ins = ibuf[i];-- /* TODO(carenas): instruction tag vs size/addr == j- * using instruction tags for const is creative- * but unlike all other architectures, and is not- * done consistently for all other objects.- * This might need reviewing later.- */- if (ins & sljit_ins_const) {- pool_size += sizeof(*pool);- ins &= ~sljit_ins_const;- }- if (label && label->size == j) {- label->size = ins_size;- label = label->next;- }- if (jump && jump->addr == j) {- if ((jump->flags & SLJIT_REWRITABLE_JUMP) || (jump->flags & JUMP_ADDR)) {- /* encoded: */- /* brasl %r14, <rel_addr> (or brcl <mask>, <rel_addr>) */- /* replace with: */- /* lgrl %r1, <pool_addr> */- /* bras %r14, %r1 (or bcr <mask>, %r1) */- pool_size += sizeof(*pool);- ins_size += 2;- }- jump = jump->next;- }- if (put_label && put_label->addr == j) {- pool_size += sizeof(*pool);- put_label = put_label->next;- }- ins_size += sizeof_ins(ins);- }- }-- /* emit trailing label */- if (label && label->size == j) {- label->size = ins_size;- label = label->next;- }-- SLJIT_ASSERT(!label);- SLJIT_ASSERT(!jump);- SLJIT_ASSERT(!put_label);-- /* pad code size to 8 bytes so is accessible with half word offsets */- /* the literal pool needs to be doubleword aligned */- pad_size = ((ins_size + 7UL) & ~7UL) - ins_size;- SLJIT_ASSERT(pad_size < 8UL);-- /* allocate target buffer */- code = SLJIT_MALLOC_EXEC(ins_size + pad_size + pool_size,- compiler->exec_allocator_data);- PTR_FAIL_WITH_EXEC_IF(code);- code_ptr = code;- executable_offset = SLJIT_EXEC_OFFSET(code);-- /* TODO(carenas): pool is optional, and the ABI recommends it to- * be created before the function code, instead of- * globally; if generated code is too big could- * need offsets bigger than 32bit words and asser()- */- pool = (sljit_uw *)((sljit_uw)code + ins_size + pad_size);- pool_ptr = pool;- const_ = (struct sljit_s390x_const *)compiler->consts;-- /* update label addresses */- label = compiler->labels;- while (label) {- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(- (sljit_uw)code_ptr + label->size, executable_offset);- label = label->next;- }-- /* reset jumps */- jump = compiler->jumps;- put_label = compiler->put_labels;-- /* emit the code */- j = 0;- for (buf = compiler->buf; buf != NULL; buf = buf->next) {- sljit_uw len = buf->used_size / sizeof(sljit_ins);- sljit_ins *ibuf = (sljit_ins *)buf->memory;- for (i = 0; i < len; ++i, ++j) {- sljit_ins ins = ibuf[i];- if (ins & sljit_ins_const) {- /* clear the const tag */- ins &= ~sljit_ins_const;-- /* update instruction with relative address of constant */- source = (sljit_sw)code_ptr;- offset = (sljit_sw)pool_ptr - source;-- SLJIT_ASSERT(!(offset & 1));- offset >>= 1; /* halfword (not byte) offset */- SLJIT_ASSERT(is_s32(offset));-- ins |= (sljit_ins)offset & 0xffffffff;-- /* update address */- const_->const_.addr = (sljit_uw)pool_ptr;-- /* store initial value into pool and update pool address */- *(pool_ptr++) = (sljit_uw)const_->init_value;-- /* move to next constant */- const_ = (struct sljit_s390x_const *)const_->const_.next;- }- if (jump && jump->addr == j) {- sljit_sw target = (sljit_sw)((jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);- if ((jump->flags & SLJIT_REWRITABLE_JUMP) || (jump->flags & JUMP_ADDR)) {- jump->addr = (sljit_uw)pool_ptr;-- /* load address into tmp1 */- source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;-- SLJIT_ASSERT(!(offset & 1));- offset >>= 1;- SLJIT_ASSERT(is_s32(offset));-- encode_inst(&code_ptr, lgrl(tmp1, offset & 0xffffffff));-- /* store jump target into pool and update pool address */- *(pool_ptr++) = (sljit_uw)target;-- /* branch to tmp1 */- sljit_ins op = (ins >> 32) & 0xf;- sljit_ins arg = (ins >> 36) & 0xf;- switch (op) {- case 4: /* brcl -> bcr */- ins = bcr(arg, tmp1);- break;- case 5: /* brasl -> basr */- ins = basr(arg, tmp1);- break;- default:- abort();- }- }- else {- jump->addr = (sljit_uw)code_ptr + 2;- source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- offset = target - source;-- /* offset must be halfword aligned */- SLJIT_ASSERT(!(offset & 1));- offset >>= 1;- SLJIT_ASSERT(is_s32(offset)); /* TODO(mundaym): handle arbitrary offsets */-- /* patch jump target */- ins |= (sljit_ins)offset & 0xffffffff;- }- jump = jump->next;- }- if (put_label && put_label->addr == j) {- source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);-- SLJIT_ASSERT(put_label->label);- put_label->addr = (sljit_uw)code_ptr;-- /* store target into pool */- *pool_ptr = put_label->label->addr;- offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;- pool_ptr++;-- SLJIT_ASSERT(!(offset & 1));- offset >>= 1;- SLJIT_ASSERT(is_s32(offset));- ins |= (sljit_ins)offset & 0xffffffff;-- put_label = put_label->next;- }- encode_inst(&code_ptr, ins);- }- }- SLJIT_ASSERT((sljit_u8 *)code + ins_size == code_ptr);- SLJIT_ASSERT((sljit_u8 *)pool + pool_size == (sljit_u8 *)pool_ptr);-- compiler->error = SLJIT_ERR_COMPILED;- compiler->executable_offset = executable_offset;- compiler->executable_size = ins_size;- code = SLJIT_ADD_EXEC_OFFSET(code, executable_offset);- code_ptr = SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- SLJIT_CACHE_FLUSH(code, code_ptr);- SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);- return code;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)-{- /* TODO(mundaym): implement all */- switch (feature_type) {- case SLJIT_HAS_CLZ:- return have_eimm() ? 1 : 0; /* FLOGR instruction */- case SLJIT_HAS_CMOV:- return have_lscond1() ? 1 : 0;- case SLJIT_HAS_FPU:- return 1;- }- return 0;-}--/* --------------------------------------------------------------------- */-/* Entry, exit */-/* --------------------------------------------------------------------- */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 word_arg_count = 0;- sljit_s32 offset, i, tmp;-- CHECK_ERROR();- CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- /* Saved registers are stored in callee allocated save area. */- SLJIT_ASSERT(gpr(SLJIT_FIRST_SAVED_REG) == r6 && gpr(SLJIT_S0) == r13);-- offset = 2 * SSIZE_OF(sw);- if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) {- FAIL_IF(push_inst(compiler, stmg(r6, r14, offset, r15))); /* save registers TODO(MGM): optimize */- offset += 9 * SSIZE_OF(sw);- } else {- if (scratches == SLJIT_FIRST_SAVED_REG) {- FAIL_IF(push_inst(compiler, stg(r6, offset, 0, r15)));- offset += SSIZE_OF(sw);- } else if (scratches > SLJIT_FIRST_SAVED_REG) {- FAIL_IF(push_inst(compiler, stmg(r6, r6 + (sljit_gpr)(scratches - SLJIT_FIRST_SAVED_REG), offset, r15)));- offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw);- }-- if (saveds == 0) {- FAIL_IF(push_inst(compiler, stg(r14, offset, 0, r15)));- offset += SSIZE_OF(sw);- } else {- FAIL_IF(push_inst(compiler, stmg(r14 - (sljit_gpr)saveds, r14, offset, r15)));- offset += (saveds + 1) * SSIZE_OF(sw);- }- }-- tmp = SLJIT_FS0 - fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- FAIL_IF(push_inst(compiler, 0x60000000 /* std */ | F20(i) | R12A(r15) | (sljit_ins)offset));- offset += SSIZE_OF(sw);- }-- for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- FAIL_IF(push_inst(compiler, 0x60000000 /* std */ | F20(i) | R12A(r15) | (sljit_ins)offset));- offset += SSIZE_OF(sw);- }-- local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf;- compiler->local_size = local_size;-- FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size)));-- arg_types >>= SLJIT_ARG_SHIFT;- tmp = 0;- while (arg_types > 0) {- if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S0 - tmp), gpr(SLJIT_R0 + word_arg_count))));- tmp++;- }- word_arg_count++;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- CHECK_ERROR();- CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- compiler->local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf;- return SLJIT_SUCCESS;-}--static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)-{- sljit_s32 offset, i, tmp;- sljit_s32 local_size = compiler->local_size;- sljit_s32 saveds = compiler->saveds;- sljit_s32 scratches = compiler->scratches;-- if (is_u12(local_size))- FAIL_IF(push_inst(compiler, 0x41000000 /* ly */ | R20A(r15) | R12A(r15) | (sljit_ins)local_size));- else- FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(local_size)));-- offset = 2 * SSIZE_OF(sw);- if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) {- FAIL_IF(push_inst(compiler, lmg(r6, r14, offset, r15))); /* save registers TODO(MGM): optimize */- offset += 9 * SSIZE_OF(sw);- } else {- if (scratches == SLJIT_FIRST_SAVED_REG) {- FAIL_IF(push_inst(compiler, lg(r6, offset, 0, r15)));- offset += SSIZE_OF(sw);- } else if (scratches > SLJIT_FIRST_SAVED_REG) {- FAIL_IF(push_inst(compiler, lmg(r6, r6 + (sljit_gpr)(scratches - SLJIT_FIRST_SAVED_REG), offset, r15)));- offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw);- }-- if (saveds == 0) {- FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15)));- offset += SSIZE_OF(sw);- } else {- FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, r14, offset, r15)));- offset += (saveds + 1) * SSIZE_OF(sw);- }- }-- tmp = SLJIT_FS0 - compiler->fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- FAIL_IF(push_inst(compiler, 0x68000000 /* ld */ | F20(i) | R12A(r15) | (sljit_ins)offset));- offset += SSIZE_OF(sw);- }-- for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- FAIL_IF(push_inst(compiler, 0x68000000 /* ld */ | F20(i) | R12A(r15) | (sljit_ins)offset));- offset += SSIZE_OF(sw);- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)-{- CHECK_ERROR();- CHECK(check_sljit_emit_return_void(compiler));-- FAIL_IF(emit_stack_frame_release(compiler));- return push_inst(compiler, br(r14)); /* return */-}--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)-{- sljit_gpr arg0 = gpr(SLJIT_R0);- sljit_gpr arg1 = gpr(SLJIT_R1);-- CHECK_ERROR();- CHECK(check_sljit_emit_op0(compiler, op));-- op = GET_OPCODE(op) | (op & SLJIT_32);- switch (op) {- case SLJIT_BREAKPOINT:- /* The following invalid instruction is emitted by gdb. */- return push_inst(compiler, 0x0001 /* 2-byte trap */);- case SLJIT_NOP:- return push_inst(compiler, 0x0700 /* 2-byte nop */);- case SLJIT_LMUL_UW:- FAIL_IF(push_inst(compiler, mlgr(arg0, arg0)));- break;- case SLJIT_LMUL_SW:- /* signed multiplication from: */- /* Hacker's Delight, Second Edition: Chapter 8-3. */- FAIL_IF(push_inst(compiler, srag(tmp0, arg0, 63, 0)));- FAIL_IF(push_inst(compiler, srag(tmp1, arg1, 63, 0)));- FAIL_IF(push_inst(compiler, ngr(tmp0, arg1)));- FAIL_IF(push_inst(compiler, ngr(tmp1, arg0)));-- /* unsigned multiplication */- FAIL_IF(push_inst(compiler, mlgr(arg0, arg0)));-- FAIL_IF(push_inst(compiler, sgr(arg0, tmp0)));- FAIL_IF(push_inst(compiler, sgr(arg0, tmp1)));- break;- case SLJIT_DIV_U32:- case SLJIT_DIVMOD_U32:- FAIL_IF(push_inst(compiler, lhi(tmp0, 0)));- FAIL_IF(push_inst(compiler, lr(tmp1, arg0)));- FAIL_IF(push_inst(compiler, dlr(tmp0, arg1)));- FAIL_IF(push_inst(compiler, lr(arg0, tmp1))); /* quotient */- if (op == SLJIT_DIVMOD_U32)- return push_inst(compiler, lr(arg1, tmp0)); /* remainder */-- return SLJIT_SUCCESS;- case SLJIT_DIV_S32:- case SLJIT_DIVMOD_S32:- FAIL_IF(push_inst(compiler, lhi(tmp0, 0)));- FAIL_IF(push_inst(compiler, lr(tmp1, arg0)));- FAIL_IF(push_inst(compiler, dr(tmp0, arg1)));- FAIL_IF(push_inst(compiler, lr(arg0, tmp1))); /* quotient */- if (op == SLJIT_DIVMOD_S32)- return push_inst(compiler, lr(arg1, tmp0)); /* remainder */-- return SLJIT_SUCCESS;- case SLJIT_DIV_UW:- case SLJIT_DIVMOD_UW:- FAIL_IF(push_inst(compiler, lghi(tmp0, 0)));- FAIL_IF(push_inst(compiler, lgr(tmp1, arg0)));- FAIL_IF(push_inst(compiler, dlgr(tmp0, arg1)));- FAIL_IF(push_inst(compiler, lgr(arg0, tmp1))); /* quotient */- if (op == SLJIT_DIVMOD_UW)- return push_inst(compiler, lgr(arg1, tmp0)); /* remainder */-- return SLJIT_SUCCESS;- case SLJIT_DIV_SW:- case SLJIT_DIVMOD_SW:- FAIL_IF(push_inst(compiler, lgr(tmp1, arg0)));- FAIL_IF(push_inst(compiler, dsgr(tmp0, arg1)));- FAIL_IF(push_inst(compiler, lgr(arg0, tmp1))); /* quotient */- if (op == SLJIT_DIVMOD_SW)- return push_inst(compiler, lgr(arg1, tmp0)); /* remainder */-- return SLJIT_SUCCESS;- case SLJIT_ENDBR:- return SLJIT_SUCCESS;- case SLJIT_SKIP_FRAMES_BEFORE_RETURN:- return SLJIT_SUCCESS;- default:- SLJIT_UNREACHABLE();- }- /* swap result registers */- FAIL_IF(push_inst(compiler, lgr(tmp0, arg0)));- FAIL_IF(push_inst(compiler, lgr(arg0, arg1)));- return push_inst(compiler, lgr(arg1, tmp0));-}--/* LEVAL will be defined later with different parameters as needed */-#define WHEN2(cond, i1, i2) (cond) ? LEVAL(i1) : LEVAL(i2)--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_ins ins;- struct addr mem;- sljit_gpr dst_r;- sljit_gpr src_r;- sljit_s32 opcode = GET_OPCODE(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 (opcode >= SLJIT_MOV && opcode <= SLJIT_MOV_P) {- /* LOAD REGISTER */- if (FAST_IS_REG(dst) && FAST_IS_REG(src)) {- dst_r = gpr(dst);- src_r = gpr(src);- switch (opcode | (op & SLJIT_32)) {- /* 32-bit */- case SLJIT_MOV32_U8:- ins = llcr(dst_r, src_r);- break;- case SLJIT_MOV32_S8:- ins = lbr(dst_r, src_r);- break;- case SLJIT_MOV32_U16:- ins = llhr(dst_r, src_r);- break;- case SLJIT_MOV32_S16:- ins = lhr(dst_r, src_r);- break;- case SLJIT_MOV32:- if (dst_r == src_r)- return SLJIT_SUCCESS;- ins = lr(dst_r, src_r);- break;- /* 64-bit */- case SLJIT_MOV_U8:- ins = llgcr(dst_r, src_r);- break;- case SLJIT_MOV_S8:- ins = lgbr(dst_r, src_r);- break;- case SLJIT_MOV_U16:- ins = llghr(dst_r, src_r);- break;- case SLJIT_MOV_S16:- ins = lghr(dst_r, src_r);- break;- case SLJIT_MOV_U32:- ins = llgfr(dst_r, src_r);- break;- case SLJIT_MOV_S32:- ins = lgfr(dst_r, src_r);- break;- case SLJIT_MOV:- case SLJIT_MOV_P:- if (dst_r == src_r)- return SLJIT_SUCCESS;- ins = lgr(dst_r, src_r);- break;- default:- ins = 0;- SLJIT_UNREACHABLE();- break;- }- FAIL_IF(push_inst(compiler, ins));- return SLJIT_SUCCESS;- }- /* LOAD IMMEDIATE */- if (FAST_IS_REG(dst) && (src & SLJIT_IMM)) {- switch (opcode) {- case SLJIT_MOV_U8:- srcw = (sljit_sw)((sljit_u8)(srcw));- break;- case SLJIT_MOV_S8:- srcw = (sljit_sw)((sljit_s8)(srcw));- break;- case SLJIT_MOV_U16:- srcw = (sljit_sw)((sljit_u16)(srcw));- break;- case SLJIT_MOV_S16:- srcw = (sljit_sw)((sljit_s16)(srcw));- break;- case SLJIT_MOV_U32:- srcw = (sljit_sw)((sljit_u32)(srcw));- break;- case SLJIT_MOV_S32:- case SLJIT_MOV32:- srcw = (sljit_sw)((sljit_s32)(srcw));- break;- }- return push_load_imm_inst(compiler, gpr(dst), srcw);- }- /* LOAD */- /* TODO(carenas): avoid reg being defined later */- #define LEVAL(i) EVAL(i, reg, mem)- if (FAST_IS_REG(dst) && (src & SLJIT_MEM)) {- sljit_gpr reg = gpr(dst);-- FAIL_IF(make_addr_bxy(compiler, &mem, src, srcw, tmp1));- /* TODO(carenas): convert all calls below to LEVAL */- switch (opcode | (op & SLJIT_32)) {- case SLJIT_MOV32_U8:- ins = llc(reg, mem.offset, mem.index, mem.base);- break;- case SLJIT_MOV32_S8:- ins = lb(reg, mem.offset, mem.index, mem.base);- break;- case SLJIT_MOV32_U16:- ins = llh(reg, mem.offset, mem.index, mem.base);- break;- case SLJIT_MOV32_S16:- ins = WHEN2(is_u12(mem.offset), lh, lhy);- break;- case SLJIT_MOV32:- ins = WHEN2(is_u12(mem.offset), l, ly);- break;- case SLJIT_MOV_U8:- ins = LEVAL(llgc);- break;- case SLJIT_MOV_S8:- ins = lgb(reg, mem.offset, mem.index, mem.base);- break;- case SLJIT_MOV_U16:- ins = LEVAL(llgh);- break;- case SLJIT_MOV_S16:- ins = lgh(reg, mem.offset, mem.index, mem.base);- break;- case SLJIT_MOV_U32:- ins = LEVAL(llgf);- break;- case SLJIT_MOV_S32:- ins = lgf(reg, mem.offset, mem.index, mem.base);- break;- case SLJIT_MOV_P:- case SLJIT_MOV:- ins = lg(reg, mem.offset, mem.index, mem.base);- break;- default:- ins = 0;- SLJIT_UNREACHABLE();- break;- }- FAIL_IF(push_inst(compiler, ins));- return SLJIT_SUCCESS;- }- /* STORE and STORE IMMEDIATE */- if ((dst & SLJIT_MEM)- && (FAST_IS_REG(src) || (src & SLJIT_IMM))) {- sljit_gpr reg = FAST_IS_REG(src) ? gpr(src) : tmp0;- if (src & SLJIT_IMM) {- /* TODO(mundaym): MOVE IMMEDIATE? */- FAIL_IF(push_load_imm_inst(compiler, reg, srcw));- }- struct addr mem;- FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));- switch (opcode) {- case SLJIT_MOV_U8:- case SLJIT_MOV_S8:- return push_inst(compiler,- WHEN2(is_u12(mem.offset), stc, stcy));- case SLJIT_MOV_U16:- case SLJIT_MOV_S16:- return push_inst(compiler,- WHEN2(is_u12(mem.offset), sth, sthy));- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:- return push_inst(compiler,- WHEN2(is_u12(mem.offset), st, sty));- case SLJIT_MOV_P:- case SLJIT_MOV:- FAIL_IF(push_inst(compiler, LEVAL(stg)));- return SLJIT_SUCCESS;- default:- SLJIT_UNREACHABLE();- }- }- #undef LEVAL- /* MOVE CHARACTERS */- if ((dst & SLJIT_MEM) && (src & SLJIT_MEM)) {- struct addr mem;- FAIL_IF(make_addr_bxy(compiler, &mem, src, srcw, tmp1));- switch (opcode) {- case SLJIT_MOV_U8:- case SLJIT_MOV_S8:- FAIL_IF(push_inst(compiler,- EVAL(llgc, tmp0, mem)));- FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));- return push_inst(compiler,- EVAL(stcy, tmp0, mem));- case SLJIT_MOV_U16:- case SLJIT_MOV_S16:- FAIL_IF(push_inst(compiler,- EVAL(llgh, tmp0, mem)));- FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));- return push_inst(compiler,- EVAL(sthy, tmp0, mem));- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:- FAIL_IF(push_inst(compiler,- EVAL(ly, tmp0, mem)));- FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));- return push_inst(compiler,- EVAL(sty, tmp0, mem));- case SLJIT_MOV_P:- case SLJIT_MOV:- FAIL_IF(push_inst(compiler,- EVAL(lg, tmp0, mem)));- FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));- FAIL_IF(push_inst(compiler,- EVAL(stg, tmp0, mem)));- return SLJIT_SUCCESS;- default:- SLJIT_UNREACHABLE();- }- }- SLJIT_UNREACHABLE();- }-- SLJIT_ASSERT((src & SLJIT_IMM) == 0); /* no immediates */-- dst_r = FAST_IS_REG(dst) ? gpr(REG_MASK & dst) : tmp0;- src_r = FAST_IS_REG(src) ? gpr(REG_MASK & src) : tmp0;- if (src & SLJIT_MEM)- FAIL_IF(load_word(compiler, src_r, src, srcw, src & SLJIT_32));-- compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z);-- /* TODO(mundaym): optimize loads and stores */- switch (opcode | (op & SLJIT_32)) {- case SLJIT_NOT:- /* emulate ~x with x^-1 */- FAIL_IF(push_load_imm_inst(compiler, tmp1, -1));- if (src_r != dst_r)- FAIL_IF(push_inst(compiler, lgr(dst_r, src_r)));-- FAIL_IF(push_inst(compiler, xgr(dst_r, tmp1)));- break;- case SLJIT_NOT32:- /* emulate ~x with x^-1 */- if (have_eimm())- FAIL_IF(push_inst(compiler, xilf(dst_r, 0xffffffff)));- else {- FAIL_IF(push_load_imm_inst(compiler, tmp1, -1));- if (src_r != dst_r)- FAIL_IF(push_inst(compiler, lr(dst_r, src_r)));-- FAIL_IF(push_inst(compiler, xr(dst_r, tmp1)));- }- break;- case SLJIT_CLZ:- if (have_eimm()) {- FAIL_IF(push_inst(compiler, flogr(tmp0, src_r))); /* clobbers tmp1 */- if (dst_r != tmp0)- FAIL_IF(push_inst(compiler, lgr(dst_r, tmp0)));- } else {- abort(); /* TODO(mundaym): no eimm (?) */- }- break;- case SLJIT_CLZ32:- if (have_eimm()) {- FAIL_IF(push_inst(compiler, sllg(tmp1, src_r, 32, 0)));- FAIL_IF(push_inst(compiler, iilf(tmp1, 0xffffffff)));- FAIL_IF(push_inst(compiler, flogr(tmp0, tmp1))); /* clobbers tmp1 */- if (dst_r != tmp0)- FAIL_IF(push_inst(compiler, lr(dst_r, tmp0)));- } else {- abort(); /* TODO(mundaym): no eimm (?) */- }- break;- default:- SLJIT_UNREACHABLE();- }-- if ((op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW))- FAIL_IF(update_zero_overflow(compiler, op, dst_r));-- /* TODO(carenas): doesn't need FAIL_IF */- if (dst & SLJIT_MEM)- FAIL_IF(store_word(compiler, dst_r, dst, dstw, op & SLJIT_32));-- return SLJIT_SUCCESS;-}--static SLJIT_INLINE int is_commutative(sljit_s32 op)-{- switch (GET_OPCODE(op)) {- case SLJIT_ADD:- case SLJIT_ADDC:- case SLJIT_MUL:- case SLJIT_AND:- case SLJIT_OR:- case SLJIT_XOR:- return 1;- }- return 0;-}--static SLJIT_INLINE int is_shift(sljit_s32 op) {- sljit_s32 v = GET_OPCODE(op);- return (v == SLJIT_SHL || v == SLJIT_ASHR || v == SLJIT_LSHR) ? 1 : 0;-}--static const struct ins_forms add_forms = {- 0x1a00, /* ar */- 0xb9080000, /* agr */- 0xb9f80000, /* ark */- 0xb9e80000, /* agrk */- 0x5a000000, /* a */- 0xe3000000005a, /* ay */- 0xe30000000008, /* ag */-};--static const struct ins_forms logical_add_forms = {- 0x1e00, /* alr */- 0xb90a0000, /* algr */- 0xb9fa0000, /* alrk */- 0xb9ea0000, /* algrk */- 0x5e000000, /* al */- 0xe3000000005e, /* aly */- 0xe3000000000a, /* alg */-};--static sljit_s32 sljit_emit_add(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)-{- int sets_overflow = (op & VARIABLE_FLAG_MASK) == SLJIT_SET_OVERFLOW;- int sets_zero_overflow = (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW);- const struct ins_forms *forms;- sljit_ins ins;-- if (src2 & SLJIT_IMM) {- if (!sets_zero_overflow && is_s8(src2w) && (src1 & SLJIT_MEM) && (dst == src1 && dstw == src1w)) {- if (sets_overflow)- ins = (op & SLJIT_32) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;- else- ins = (op & SLJIT_32) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;- return emit_siy(compiler, ins, dst, dstw, src2w);- }-- if (is_s16(src2w)) {- if (sets_overflow)- ins = (op & SLJIT_32) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;- else- ins = (op & SLJIT_32) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;- FAIL_IF(emit_rie_d(compiler, ins, dst, src1, src1w, src2w));- goto done;- }-- if (!sets_overflow) {- if ((op & SLJIT_32) || is_u32(src2w)) {- ins = (op & SLJIT_32) ? 0xc20b00000000 /* alfi */ : 0xc20a00000000 /* algfi */;- FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));- goto done;- }- if (is_u32(-src2w)) {- FAIL_IF(emit_ri(compiler, 0xc20400000000 /* slgfi */, dst, src1, src1w, -src2w, RIL_A));- goto done;- }- }- else if ((op & SLJIT_32) || is_s32(src2w)) {- ins = (op & SLJIT_32) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;- FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));- goto done;- }- }-- forms = sets_overflow ? &add_forms : &logical_add_forms;- FAIL_IF(emit_commutative(compiler, forms, dst, src1, src1w, src2, src2w));--done:- if (sets_zero_overflow)- FAIL_IF(update_zero_overflow(compiler, op, FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0));-- if (dst & SLJIT_MEM)- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);-- return SLJIT_SUCCESS;-}--static const struct ins_forms sub_forms = {- 0x1b00, /* sr */- 0xb9090000, /* sgr */- 0xb9f90000, /* srk */- 0xb9e90000, /* sgrk */- 0x5b000000, /* s */- 0xe3000000005b, /* sy */- 0xe30000000009, /* sg */-};--static const struct ins_forms logical_sub_forms = {- 0x1f00, /* slr */- 0xb90b0000, /* slgr */- 0xb9fb0000, /* slrk */- 0xb9eb0000, /* slgrk */- 0x5f000000, /* sl */- 0xe3000000005f, /* sly */- 0xe3000000000b, /* slg */-};--static sljit_s32 sljit_emit_sub(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_s32 flag_type = GET_FLAG_TYPE(op);- int sets_signed = (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_NOT_OVERFLOW);- int sets_zero_overflow = (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW);- const struct ins_forms *forms;- sljit_ins ins;-- if (dst == (sljit_s32)tmp0 && flag_type <= SLJIT_SIG_LESS_EQUAL) {- int compare_signed = flag_type >= SLJIT_SIG_LESS;-- compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_COMPARE;-- if (src2 & SLJIT_IMM) {- if (compare_signed || ((op & VARIABLE_FLAG_MASK) == 0 && is_s32(src2w)))- {- if ((op & SLJIT_32) || is_s32(src2w)) {- ins = (op & SLJIT_32) ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */;- return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A);- }- }- else {- if ((op & SLJIT_32) || is_u32(src2w)) {- ins = (op & SLJIT_32) ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */;- return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A);- }- if (is_s16(src2w))- return emit_rie_d(compiler, 0xec00000000db /* alghsik */, (sljit_s32)tmp0, src1, src1w, src2w);- }- }- else if (src2 & SLJIT_MEM) {- if ((op & SLJIT_32) && ((src2 & OFFS_REG_MASK) || is_u12(src2w))) {- ins = compare_signed ? 0x59000000 /* c */ : 0x55000000 /* cl */;- return emit_rx(compiler, ins, src1, src1, src1w, src2, src2w, RX_A);- }-- if (compare_signed)- ins = (op & SLJIT_32) ? 0xe30000000059 /* cy */ : 0xe30000000020 /* cg */;- else- ins = (op & SLJIT_32) ? 0xe30000000055 /* cly */ : 0xe30000000021 /* clg */;- return emit_rx(compiler, ins, src1, src1, src1w, src2, src2w, RXY_A);- }-- if (compare_signed)- ins = (op & SLJIT_32) ? 0x1900 /* cr */ : 0xb9200000 /* cgr */;- else- ins = (op & SLJIT_32) ? 0x1500 /* clr */ : 0xb9210000 /* clgr */;- return emit_rr(compiler, ins, src1, src1, src1w, src2, src2w);- }-- if (src1 == SLJIT_IMM && src1w == 0 && (flag_type == 0 || sets_signed)) {- ins = (op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */;- FAIL_IF(emit_rr1(compiler, ins, dst, src2, src2w));- goto done;- }-- if (src2 & SLJIT_IMM) {- sljit_sw neg_src2w = -src2w;-- if (sets_signed || neg_src2w != 0 || (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == 0) {- if (!sets_zero_overflow && is_s8(neg_src2w) && (src1 & SLJIT_MEM) && (dst == src1 && dstw == src1w)) {- if (sets_signed)- ins = (op & SLJIT_32) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;- else- ins = (op & SLJIT_32) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;- return emit_siy(compiler, ins, dst, dstw, neg_src2w);- }-- if (is_s16(neg_src2w)) {- if (sets_signed)- ins = (op & SLJIT_32) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;- else- ins = (op & SLJIT_32) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;- FAIL_IF(emit_rie_d(compiler, ins, dst, src1, src1w, neg_src2w));- goto done;- }- }-- if (!sets_signed) {- if ((op & SLJIT_32) || is_u32(src2w)) {- ins = (op & SLJIT_32) ? 0xc20500000000 /* slfi */ : 0xc20400000000 /* slgfi */;- FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));- goto done;- }- if (is_u32(neg_src2w)) {- FAIL_IF(emit_ri(compiler, 0xc20a00000000 /* algfi */, dst, src1, src1w, neg_src2w, RIL_A));- goto done;- }- }- else if ((op & SLJIT_32) || is_s32(neg_src2w)) {- ins = (op & SLJIT_32) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;- FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, neg_src2w, RIL_A));- goto done;- }- }-- forms = sets_signed ? &sub_forms : &logical_sub_forms;- FAIL_IF(emit_non_commutative(compiler, forms, dst, src1, src1w, src2, src2w));--done:- if (sets_signed) {- sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;-- if ((op & VARIABLE_FLAG_MASK) != SLJIT_SET_OVERFLOW) {- /* In case of overflow, the sign bit of the two source operands must be different, and- - the first operand is greater if the sign bit of the result is set- - the first operand is less if the sign bit of the result is not set- The -result operation sets the corrent sign, because the result cannot be zero.- The overflow is considered greater, since the result must be equal to INT_MIN so its sign bit is set. */- FAIL_IF(push_inst(compiler, brc(0xe, 2 + 2)));- FAIL_IF(push_inst(compiler, (op & SLJIT_32) ? lcr(tmp1, dst_r) : lcgr(tmp1, dst_r)));- }- else if (op & SLJIT_SET_Z)- FAIL_IF(update_zero_overflow(compiler, op, dst_r));- }-- if (dst & SLJIT_MEM)- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);-- return SLJIT_SUCCESS;-}--static const struct ins_forms multiply_forms = {- 0xb2520000, /* msr */- 0xb90c0000, /* msgr */- 0xb9fd0000, /* msrkc */- 0xb9ed0000, /* msgrkc */- 0x71000000, /* ms */- 0xe30000000051, /* msy */- 0xe3000000000c, /* msg */-};--static const struct ins_forms multiply_overflow_forms = {- 0,- 0,- 0xb9fd0000, /* msrkc */- 0xb9ed0000, /* msgrkc */- 0,- 0xe30000000053, /* msc */- 0xe30000000083, /* msgc */-};--static sljit_s32 sljit_emit_multiply(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_ins ins;-- if (HAS_FLAGS(op)) {- /* if have_misc2 fails, this operation should be emulated. 32 bit emulation:- FAIL_IF(push_inst(compiler, lgfr(tmp0, src1_r)));- FAIL_IF(push_inst(compiler, msgfr(tmp0, src2_r)));- if (dst_r != tmp0) {- FAIL_IF(push_inst(compiler, lr(dst_r, tmp0)));- }- FAIL_IF(push_inst(compiler, aih(tmp0, 1)));- FAIL_IF(push_inst(compiler, nihf(tmp0, ~1U)));- FAIL_IF(push_inst(compiler, ipm(tmp1)));- FAIL_IF(push_inst(compiler, oilh(tmp1, 0x2000))); */-- return emit_commutative(compiler, &multiply_overflow_forms, dst, src1, src1w, src2, src2w);- }-- if (src2 & SLJIT_IMM) {- if (is_s16(src2w)) {- ins = (op & SLJIT_32) ? 0xa70c0000 /* mhi */ : 0xa70d0000 /* mghi */;- return emit_ri(compiler, ins, dst, src1, src1w, src2w, RI_A);- }-- if (is_s32(src2w)) {- ins = (op & SLJIT_32) ? 0xc20100000000 /* msfi */ : 0xc20000000000 /* msgfi */;- return emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A);- }- }-- return emit_commutative(compiler, &multiply_forms, dst, src1, src1w, src2, src2w);-}--static sljit_s32 sljit_emit_bitwise_imm(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_uw imm, sljit_s32 count16)-{- sljit_s32 mode = compiler->mode;- sljit_gpr dst_r = tmp0;- sljit_s32 needs_move = 1;-- if (IS_GPR_REG(dst)) {- dst_r = gpr(dst & REG_MASK);- if (dst == src1)- needs_move = 0;- }-- if (needs_move)- FAIL_IF(emit_move(compiler, dst_r, src1, src1w));-- if (type == SLJIT_AND) {- if (!(mode & SLJIT_32))- FAIL_IF(push_inst(compiler, 0xc00a00000000 /* nihf */ | R36A(dst_r) | (imm >> 32)));- return push_inst(compiler, 0xc00b00000000 /* nilf */ | R36A(dst_r) | (imm & 0xffffffff));- }- else if (type == SLJIT_OR) {- if (count16 >= 3) {- FAIL_IF(push_inst(compiler, 0xc00c00000000 /* oihf */ | R36A(dst_r) | (imm >> 32)));- return push_inst(compiler, 0xc00d00000000 /* oilf */ | R36A(dst_r) | (imm & 0xffffffff));- }-- if (count16 >= 2) {- if ((imm & 0x00000000ffffffffull) == 0)- return push_inst(compiler, 0xc00c00000000 /* oihf */ | R36A(dst_r) | (imm >> 32));- if ((imm & 0xffffffff00000000ull) == 0)- return push_inst(compiler, 0xc00d00000000 /* oilf */ | R36A(dst_r) | (imm & 0xffffffff));- }-- if ((imm & 0xffff000000000000ull) != 0)- FAIL_IF(push_inst(compiler, 0xa5080000 /* oihh */ | R20A(dst_r) | (imm >> 48)));- if ((imm & 0x0000ffff00000000ull) != 0)- FAIL_IF(push_inst(compiler, 0xa5090000 /* oihl */ | R20A(dst_r) | ((imm >> 32) & 0xffff)));- if ((imm & 0x00000000ffff0000ull) != 0)- FAIL_IF(push_inst(compiler, 0xa50a0000 /* oilh */ | R20A(dst_r) | ((imm >> 16) & 0xffff)));- if ((imm & 0x000000000000ffffull) != 0 || imm == 0)- return push_inst(compiler, 0xa50b0000 /* oill */ | R20A(dst_r) | (imm & 0xffff));- return SLJIT_SUCCESS;- }-- if ((imm & 0xffffffff00000000ull) != 0)- FAIL_IF(push_inst(compiler, 0xc00600000000 /* xihf */ | R36A(dst_r) | (imm >> 32)));- if ((imm & 0x00000000ffffffffull) != 0 || imm == 0)- return push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(dst_r) | (imm & 0xffffffff));- return SLJIT_SUCCESS;-}--static const struct ins_forms bitwise_and_forms = {- 0x1400, /* nr */- 0xb9800000, /* ngr */- 0xb9f40000, /* nrk */- 0xb9e40000, /* ngrk */- 0x54000000, /* n */- 0xe30000000054, /* ny */- 0xe30000000080, /* ng */-};--static const struct ins_forms bitwise_or_forms = {- 0x1600, /* or */- 0xb9810000, /* ogr */- 0xb9f60000, /* ork */- 0xb9e60000, /* ogrk */- 0x56000000, /* o */- 0xe30000000056, /* oy */- 0xe30000000081, /* og */-};--static const struct ins_forms bitwise_xor_forms = {- 0x1700, /* xr */- 0xb9820000, /* xgr */- 0xb9f70000, /* xrk */- 0xb9e70000, /* xgrk */- 0x57000000, /* x */- 0xe30000000057, /* xy */- 0xe30000000082, /* xg */-};--static sljit_s32 sljit_emit_bitwise(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_s32 type = GET_OPCODE(op);- const struct ins_forms *forms;-- if ((src2 & SLJIT_IMM) && (!(op & SLJIT_SET_Z) || (type == SLJIT_AND && dst == (sljit_s32)tmp0))) {- sljit_s32 count16 = 0;- sljit_uw imm = (sljit_uw)src2w;-- if (op & SLJIT_32)- imm &= 0xffffffffull;-- if ((imm & 0x000000000000ffffull) != 0 || imm == 0)- count16++;- if ((imm & 0x00000000ffff0000ull) != 0)- count16++;- if ((imm & 0x0000ffff00000000ull) != 0)- count16++;- if ((imm & 0xffff000000000000ull) != 0)- count16++;-- if (type == SLJIT_AND && dst == (sljit_s32)tmp0 && count16 == 1) {- sljit_gpr src_r = tmp0;-- if (FAST_IS_REG(src1))- src_r = gpr(src1 & REG_MASK);- else- FAIL_IF(emit_move(compiler, tmp0, src1, src1w));-- if ((imm & 0x000000000000ffffull) != 0 || imm == 0)- return push_inst(compiler, 0xa7010000 | R20A(src_r) | imm);- if ((imm & 0x00000000ffff0000ull) != 0)- return push_inst(compiler, 0xa7000000 | R20A(src_r) | (imm >> 16));- if ((imm & 0x0000ffff00000000ull) != 0)- return push_inst(compiler, 0xa7030000 | R20A(src_r) | (imm >> 32));- return push_inst(compiler, 0xa7020000 | R20A(src_r) | (imm >> 48));- }-- if (!(op & SLJIT_SET_Z))- return sljit_emit_bitwise_imm(compiler, type, dst, src1, src1w, imm, count16);- }-- if (type == SLJIT_AND)- forms = &bitwise_and_forms;- else if (type == SLJIT_OR)- forms = &bitwise_or_forms;- else- forms = &bitwise_xor_forms;-- return emit_commutative(compiler, forms, dst, src1, src1w, src2, src2w);-}--static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 dst,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_s32 type = GET_OPCODE(op);- sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;- sljit_gpr src_r = tmp0;- sljit_gpr base_r = tmp0;- sljit_ins imm = 0;- sljit_ins ins;-- if (FAST_IS_REG(src1))- src_r = gpr(src1 & REG_MASK);- else- FAIL_IF(emit_move(compiler, tmp0, src1, src1w));-- if (src2 & SLJIT_IMM)- imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f));- else if (FAST_IS_REG(src2))- base_r = gpr(src2 & REG_MASK);- else {- FAIL_IF(emit_move(compiler, tmp1, src2, src2w));- base_r = tmp1;- }-- if ((op & SLJIT_32) && dst_r == src_r) {- if (type == SLJIT_SHL)- ins = 0x89000000 /* sll */;- else if (type == SLJIT_LSHR)- ins = 0x88000000 /* srl */;- else- ins = 0x8a000000 /* sra */;-- FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | R12A(base_r) | imm));- }- else {- if (type == SLJIT_SHL)- ins = (op & SLJIT_32) ? 0xeb00000000df /* sllk */ : 0xeb000000000d /* sllg */;- else if (type == SLJIT_LSHR)- ins = (op & SLJIT_32) ? 0xeb00000000de /* srlk */ : 0xeb000000000c /* srlg */;- else- ins = (op & SLJIT_32) ? 0xeb00000000dc /* srak */ : 0xeb000000000a /* srag */;-- FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | R28A(base_r) | (imm << 16)));- }-- if ((op & SLJIT_SET_Z) && type != SLJIT_ASHR)- return push_inst(compiler, (op & SLJIT_32) ? or(dst_r, dst_r) : ogr(dst_r, dst_r));-- return SLJIT_SUCCESS;-}--static const struct ins_forms addc_forms = {- 0xb9980000, /* alcr */- 0xb9880000, /* alcgr */- 0,- 0,- 0,- 0xe30000000098, /* alc */- 0xe30000000088, /* alcg */-};--static const struct ins_forms subc_forms = {- 0xb9990000, /* slbr */- 0xb9890000, /* slbgr */- 0,- 0,- 0,- 0xe30000000099, /* slb */- 0xe30000000089, /* slbg */-};--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, 0, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- compiler->mode = op & SLJIT_32;- compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z);-- if (is_commutative(op) && (src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM)) {- src1 ^= src2;- src2 ^= src1;- src1 ^= src2;-- src1w ^= src2w;- src2w ^= src1w;- src1w ^= src2w;- }-- switch (GET_OPCODE(op)) {- case SLJIT_ADD:- compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD;- return sljit_emit_add(compiler, op, dst, dstw, src1, src1w, src2, src2w);- case SLJIT_ADDC:- compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD;- FAIL_IF(emit_commutative(compiler, &addc_forms, dst, src1, src1w, src2, src2w));- if (dst & SLJIT_MEM)- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);- return SLJIT_SUCCESS;- case SLJIT_SUB:- compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_SUB;- return sljit_emit_sub(compiler, op, dst, dstw, src1, src1w, src2, src2w);- case SLJIT_SUBC:- compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_SUB;- FAIL_IF(emit_non_commutative(compiler, &subc_forms, dst, src1, src1w, src2, src2w));- if (dst & SLJIT_MEM)- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);- return SLJIT_SUCCESS;- case SLJIT_MUL:- FAIL_IF(sljit_emit_multiply(compiler, op, dst, src1, src1w, src2, src2w));- break;- case SLJIT_AND:- case SLJIT_OR:- case SLJIT_XOR:- FAIL_IF(sljit_emit_bitwise(compiler, op, dst, src1, src1w, src2, src2w));- break;- case SLJIT_SHL:- case SLJIT_LSHR:- case SLJIT_ASHR:- FAIL_IF(sljit_emit_shift(compiler, op, dst, src1, src1w, src2, src2w));- break;- }-- if (dst & SLJIT_MEM)- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 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_op2(compiler, op, (sljit_s32)tmp0, 0, src1, src1w, src2, src2w);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(- struct sljit_compiler *compiler,- sljit_s32 op, sljit_s32 src, sljit_sw srcw)-{- sljit_gpr src_r;-- CHECK_ERROR();- CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- switch (op) {- case SLJIT_FAST_RETURN:- src_r = FAST_IS_REG(src) ? gpr(src) : tmp1;- if (src & SLJIT_MEM)- FAIL_IF(load_word(compiler, tmp1, src, srcw, 0));-- return push_inst(compiler, br(src_r));- case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:- /* TODO(carenas): implement? */- return SLJIT_SUCCESS;- case SLJIT_PREFETCH_L1:- case SLJIT_PREFETCH_L2:- case SLJIT_PREFETCH_L3:- case SLJIT_PREFETCH_ONCE:- /* TODO(carenas): implement */- return SLJIT_SUCCESS;- default:- /* TODO(carenas): probably should not success by default */- return SLJIT_SUCCESS;- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)-{- CHECK_REG_INDEX(check_sljit_get_register_index(reg));- return (sljit_s32)gpr(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 (sljit_s32)fgpr(reg);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{- sljit_ins ins = 0;-- CHECK_ERROR();- CHECK(check_sljit_emit_op_custom(compiler, instruction, size));-- memcpy((sljit_u8 *)&ins + sizeof(ins) - size, instruction, size);- return push_inst(compiler, ins);-}--/* --------------------------------------------------------------------- */-/* Floating point operators */-/* --------------------------------------------------------------------- */--#define FLOAT_LOAD 0-#define FLOAT_STORE 1--static sljit_s32 float_mem(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 reg,- sljit_s32 mem, sljit_sw memw)-{- struct addr addr;- sljit_ins ins;-- SLJIT_ASSERT(mem & SLJIT_MEM);-- if ((mem & OFFS_REG_MASK) || is_u12(memw) || !is_s20(memw)) {- FAIL_IF(make_addr_bx(compiler, &addr, mem, memw, tmp1));-- if (op & FLOAT_STORE)- ins = (op & SLJIT_32) ? 0x70000000 /* ste */ : 0x60000000 /* std */;- else- ins = (op & SLJIT_32) ? 0x78000000 /* le */ : 0x68000000 /* ld */;-- return push_inst(compiler, ins | F20(reg) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset);- }-- FAIL_IF(make_addr_bxy(compiler, &addr, mem, memw, tmp1));-- if (op & FLOAT_STORE)- ins = (op & SLJIT_32) ? 0xed0000000066 /* stey */ : 0xed0000000067 /* stdy */;- else- ins = (op & SLJIT_32) ? 0xed0000000064 /* ley */ : 0xed0000000065 /* ldy */;-- return push_inst(compiler, ins | F36(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));-}--static sljit_s32 emit_float(struct sljit_compiler *compiler, sljit_ins ins_r, sljit_ins ins,- sljit_s32 reg,- sljit_s32 src, sljit_sw srcw)-{- struct addr addr;-- if (!(src & SLJIT_MEM))- return push_inst(compiler, ins_r | F4(reg) | F0(src));-- FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1));- return push_inst(compiler, ins | F36(reg) | R32A(addr.index) | R28A(addr.base) | ((sljit_ins)addr.offset << 16));-}--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_ins dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;- sljit_ins ins;-- if (src & SLJIT_MEM) {- FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src, srcw));- src = TMP_FREG1;- }-- /* M3 is set to 5 */- if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)- ins = (op & SLJIT_32) ? 0xb3a85000 /* cgebr */ : 0xb3a95000 /* cgdbr */;- else- ins = (op & SLJIT_32) ? 0xb3985000 /* cfebr */ : 0xb3995000 /* cfdbr */;-- FAIL_IF(push_inst(compiler, ins | R4A(dst_r) | F0(src)));-- if (dst & SLJIT_MEM)- return store_word(compiler, dst_r, dst, dstw, GET_OPCODE(op) >= SLJIT_CONV_S32_FROM_F64);-- return SLJIT_SUCCESS;-}--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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;- sljit_ins ins;-- if (src & SLJIT_IMM) {- FAIL_IF(push_load_imm_inst(compiler, tmp0, srcw));- src = (sljit_s32)tmp0;- }- else if (src & SLJIT_MEM) {- FAIL_IF(load_word(compiler, tmp0, src, srcw, GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_S32));- src = (sljit_s32)tmp0;- }-- if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)- ins = (op & SLJIT_32) ? 0xb3a40000 /* cegbr */ : 0xb3a50000 /* cdgbr */;- else- ins = (op & SLJIT_32) ? 0xb3940000 /* cefbr */ : 0xb3950000 /* cdfbr */;-- FAIL_IF(push_inst(compiler, ins | F4(dst_r) | R0(src)));-- if (dst & SLJIT_MEM)- return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);-- return SLJIT_SUCCESS;-}--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 ins_r, ins;-- if (src1 & SLJIT_MEM) {- FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src1, src1w));- src1 = TMP_FREG1;- }-- if (op & SLJIT_32) {- ins_r = 0xb3090000 /* cebr */;- ins = 0xed0000000009 /* ceb */;- } else {- ins_r = 0xb3190000 /* cdbr */;- ins = 0xed0000000019 /* cdb */;- }-- return emit_float(compiler, ins_r, ins, src1, src2, src2w);-}--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_s32 dst_r;- sljit_ins ins;-- CHECK_ERROR();-- SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- if (op == SLJIT_CONV_F64_FROM_F32)- FAIL_IF(emit_float(compiler, 0xb3040000 /* ldebr */, 0xed0000000004 /* ldeb */, dst_r, src, srcw));- else {- if (src & SLJIT_MEM) {- FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op == SLJIT_CONV_F32_FROM_F64 ? 0 : (op & SLJIT_32)), dst_r, src, srcw));- src = dst_r;- }-- switch (GET_OPCODE(op)) {- case SLJIT_MOV_F64:- if (FAST_IS_REG(dst)) {- if (dst == src)- return SLJIT_SUCCESS;-- ins = (op & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */;- break;- }- return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), src, dst, dstw);- case SLJIT_CONV_F64_FROM_F32:- /* Only SLJIT_CONV_F32_FROM_F64. */- ins = 0xb3440000 /* ledbr */;- break;- case SLJIT_NEG_F64:- ins = (op & SLJIT_32) ? 0xb3030000 /* lcebr */ : 0xb3130000 /* lcdbr */;- break;- default:- SLJIT_ASSERT(GET_OPCODE(op) == SLJIT_ABS_F64);- ins = (op & SLJIT_32) ? 0xb3000000 /* lpebr */ : 0xb3100000 /* lpdbr */;- break;- }-- FAIL_IF(push_inst(compiler, ins | F4(dst_r) | F0(src)));- }-- if (!(dst & SLJIT_MEM))- return SLJIT_SUCCESS;-- SLJIT_ASSERT(dst_r == TMP_FREG1);-- return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);-}--#define FLOAT_MOV(op, dst_r, src_r) \- (((op & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */) | F4(dst_r) | F0(src_r))--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_s32 dst_r = TMP_FREG1;- sljit_ins ins_r, ins;-- CHECK_ERROR();- CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- do {- if (FAST_IS_REG(dst)) {- dst_r = dst;-- if (dst == src1)- break;-- if (dst == src2) {- if (GET_OPCODE(op) == SLJIT_ADD_F64 || GET_OPCODE(op) == SLJIT_MUL_F64) {- src2 = src1;- src2w = src1w;- src1 = dst;- break;- }-- FAIL_IF(push_inst(compiler, FLOAT_MOV(op, TMP_FREG1, src2)));- src2 = TMP_FREG1;- }- }-- if (src1 & SLJIT_MEM)- FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), dst_r, src1, src1w));- else- FAIL_IF(push_inst(compiler, FLOAT_MOV(op, dst_r, src1)));- } while (0);-- switch (GET_OPCODE(op)) {- case SLJIT_ADD_F64:- ins_r = (op & SLJIT_32) ? 0xb30a0000 /* aebr */ : 0xb31a0000 /* adbr */;- ins = (op & SLJIT_32) ? 0xed000000000a /* aeb */ : 0xed000000001a /* adb */;- break;- case SLJIT_SUB_F64:- ins_r = (op & SLJIT_32) ? 0xb30b0000 /* sebr */ : 0xb31b0000 /* sdbr */;- ins = (op & SLJIT_32) ? 0xed000000000b /* seb */ : 0xed000000001b /* sdb */;- break;- case SLJIT_MUL_F64:- ins_r = (op & SLJIT_32) ? 0xb3170000 /* meebr */ : 0xb31c0000 /* mdbr */;- ins = (op & SLJIT_32) ? 0xed0000000017 /* meeb */ : 0xed000000001c /* mdb */;- break;- default:- SLJIT_ASSERT(GET_OPCODE(op) == SLJIT_DIV_F64);- ins_r = (op & SLJIT_32) ? 0xb30d0000 /* debr */ : 0xb31d0000 /* ddbr */;- ins = (op & SLJIT_32) ? 0xed000000000d /* deb */ : 0xed000000001d /* ddb */;- break;- }-- FAIL_IF(emit_float(compiler, ins_r, ins, dst_r, src2, src2w));-- if (dst & SLJIT_MEM)- return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);-- SLJIT_ASSERT(dst_r != TMP_FREG1);- return SLJIT_SUCCESS;-}--/* --------------------------------------------------------------------- */-/* Other instructions */-/* --------------------------------------------------------------------- */--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);-- if (FAST_IS_REG(dst))- return push_inst(compiler, lgr(gpr(dst), fast_link_r));-- /* memory */- return store_word(compiler, fast_link_r, dst, dstw, 0);-}--/* --------------------------------------------------------------------- */-/* Conditional instructions */-/* --------------------------------------------------------------------- */--SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)-{- struct sljit_label *label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_label(compiler));-- if (compiler->last_label && compiler->last_label->size == compiler->size)- return compiler->last_label;-- label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));- PTR_FAIL_IF(!label);- set_label(label, compiler);- return label;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)-{- sljit_u8 mask = ((type & 0xff) < SLJIT_JUMP) ? get_cc(compiler, type & 0xff) : 0xf;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_jump(compiler, type));-- /* record jump */- struct sljit_jump *jump = (struct sljit_jump *)- ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);- jump->addr = compiler->size;-- /* emit jump instruction */- type &= 0xff;- if (type >= SLJIT_FAST_CALL)- PTR_FAIL_IF(push_inst(compiler, brasl(type == SLJIT_FAST_CALL ? fast_link_r : link_r, 0)));- else- PTR_FAIL_IF(push_inst(compiler, brcl(mask, 0)));-- return jump;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types)-{- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));-- if (type & SLJIT_CALL_RETURN) {- PTR_FAIL_IF(emit_stack_frame_release(compiler));- type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);- }--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_jump(compiler, type);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)-{- sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp1;-- CHECK_ERROR();- CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));-- if (src & SLJIT_IMM) {- SLJIT_ASSERT(!(srcw & 1)); /* target address must be even */- FAIL_IF(push_load_imm_inst(compiler, src_r, srcw));- }- else if (src & SLJIT_MEM) {- ADJUST_LOCAL_OFFSET(src, srcw);- FAIL_IF(load_word(compiler, src_r, src, srcw, 0 /* 64-bit */));- }-- /* emit jump instruction */- if (type >= SLJIT_FAST_CALL)- return push_inst(compiler, basr(type == SLJIT_FAST_CALL ? fast_link_r : link_r, src_r));-- return push_inst(compiler, br(src_r));-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));-- SLJIT_ASSERT(gpr(TMP_REG2) == tmp1);-- if (src & SLJIT_MEM) {- ADJUST_LOCAL_OFFSET(src, srcw);- FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */));- src = TMP_REG2;- }-- if (type & SLJIT_CALL_RETURN) {- if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {- FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src))));- src = TMP_REG2;- }-- FAIL_IF(emit_stack_frame_release(compiler));- type = SLJIT_JUMP;- }--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_ijump(compiler, type, src, srcw);-}--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_u8 mask = get_cc(compiler, type & 0xff);-- CHECK_ERROR();- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));-- sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;- sljit_gpr loc_r = tmp1;- switch (GET_OPCODE(op)) {- case SLJIT_AND:- case SLJIT_OR:- case SLJIT_XOR:- compiler->status_flags_state = op & SLJIT_SET_Z;-- /* dst is also source operand */- if (dst & SLJIT_MEM)- FAIL_IF(load_word(compiler, dst_r, dst, dstw, op & SLJIT_32));-- break;- case SLJIT_MOV32:- op |= SLJIT_32;- /* fallthrough */- case SLJIT_MOV:- /* can write straight into destination */- loc_r = dst_r;- break;- default:- SLJIT_UNREACHABLE();- }-- /* TODO(mundaym): fold into cmov helper function? */- #define LEVAL(i) i(loc_r, 1, mask)- if (have_lscond2()) {- FAIL_IF(push_load_imm_inst(compiler, loc_r, 0));- FAIL_IF(push_inst(compiler,- WHEN2(op & SLJIT_32, lochi, locghi)));- } else {- /* TODO(mundaym): no load/store-on-condition 2 facility (ipm? branch-and-set?) */- abort();- }- #undef LEVAL-- /* apply bitwise op and set condition codes */- switch (GET_OPCODE(op)) {- #define LEVAL(i) i(dst_r, loc_r)- case SLJIT_AND:- FAIL_IF(push_inst(compiler,- WHEN2(op & SLJIT_32, nr, ngr)));- break;- case SLJIT_OR:- FAIL_IF(push_inst(compiler,- WHEN2(op & SLJIT_32, or, ogr)));- break;- case SLJIT_XOR:- FAIL_IF(push_inst(compiler,- WHEN2(op & SLJIT_32, xr, xgr)));- break;- #undef LEVAL- }-- /* store result to memory if required */- if (dst & SLJIT_MEM)- return store_word(compiler, dst_r, dst, dstw, (op & SLJIT_32));-- 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_u8 mask = get_cc(compiler, type & 0xff);- sljit_gpr dst_r = gpr(dst_reg & ~SLJIT_32);- sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp0;-- CHECK_ERROR();- CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));-- if (src & SLJIT_IMM) {- /* TODO(mundaym): fast path with lscond2 */- FAIL_IF(push_load_imm_inst(compiler, src_r, srcw));- }-- #define LEVAL(i) i(dst_r, src_r, mask)- if (have_lscond1())- return push_inst(compiler,- WHEN2(dst_reg & SLJIT_32, locr, locgr));-- #undef LEVAL-- /* TODO(mundaym): implement */- return SLJIT_ERR_UNSUPPORTED;-}--/* --------------------------------------------------------------------- */-/* Other instructions */-/* --------------------------------------------------------------------- */--/* On s390x we build a literal pool to hold constants. This has two main- advantages:-- 1. we only need one instruction in the instruction stream (LGRL)- 2. we can store 64 bit addresses and use 32 bit offsets-- To retrofit the extra information needed to build the literal pool we- add a new sljit_s390x_const struct that contains the initial value but- can still be cast to a sljit_const. */--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_s390x_const *const_;- sljit_gpr dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));-- const_ = (struct sljit_s390x_const*)ensure_abuf(compiler,- sizeof(struct sljit_s390x_const));- PTR_FAIL_IF(!const_);- set_const((struct sljit_const*)const_, compiler);- const_->init_value = init_value;-- dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;- if (have_genext())- PTR_FAIL_IF(push_inst(compiler, sljit_ins_const | lgrl(dst_r, 0)));- else {- PTR_FAIL_IF(push_inst(compiler, sljit_ins_const | larl(tmp1, 0)));- PTR_FAIL_IF(push_inst(compiler, lg(dst_r, 0, r0, tmp1)));- }-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, 0 /* always 64-bit */));-- return (struct sljit_const*)const_;-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)-{- /* Update the constant pool. */- sljit_uw *ptr = (sljit_uw *)addr;- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);- *ptr = new_target;- SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);- SLJIT_CACHE_FLUSH(ptr, ptr + 1);-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)-{- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label *sljit_emit_put_label(- struct sljit_compiler *compiler,- sljit_s32 dst, sljit_sw dstw)-{- struct sljit_put_label *put_label;- sljit_gpr dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);-- put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));- PTR_FAIL_IF(!put_label);- set_put_label(put_label, compiler, 0);-- dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;-- if (have_genext())- PTR_FAIL_IF(push_inst(compiler, lgrl(dst_r, 0)));- else {- PTR_FAIL_IF(push_inst(compiler, larl(tmp1, 0)));- PTR_FAIL_IF(push_inst(compiler, lg(dst_r, 0, r0, tmp1)));- }-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, 0));-- return put_label;+/* Instructions are stored as 64 bit values regardless their size. */+typedef sljit_uw sljit_ins;++#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {+ 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 0, 1, 14+};++/* there are also a[2-15] available, but they are slower to access and+ * their use is limited as mundaym explained:+ * https://github.com/zherczeg/sljit/pull/91#discussion_r486895689+ */++/* General Purpose Registers [0-15]. */+typedef sljit_uw sljit_gpr;++/*+ * WARNING+ * the following code is non standard and should be improved for+ * consistency, but doesn't use SLJIT_NUMBER_OF_REGISTERS based+ * registers because r0 and r1 are the ABI recommended volatiles.+ * there is a gpr() function that maps sljit to physical register numbers+ * that should be used instead of the usual index into reg_map[] and+ * will be retired ASAP (TODO: carenas)+ */++static const sljit_gpr r0 = 0; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 2]: 0 in address calculations; reserved */+static const sljit_gpr r1 = 1; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 3]: reserved */+static const sljit_gpr r2 = 2; /* reg_map[1]: 1st argument */+static const sljit_gpr r3 = 3; /* reg_map[2]: 2nd argument */+static const sljit_gpr r4 = 4; /* reg_map[3]: 3rd argument */+static const sljit_gpr r5 = 5; /* reg_map[4]: 4th argument */+static const sljit_gpr r6 = 6; /* reg_map[5]: 5th argument; 1st saved register */+static const sljit_gpr r7 = 7; /* reg_map[6] */+static const sljit_gpr r8 = 8; /* reg_map[7] */+static const sljit_gpr r9 = 9; /* reg_map[8] */+static const sljit_gpr r10 = 10; /* reg_map[9] */+static const sljit_gpr r11 = 11; /* reg_map[10] */+static const sljit_gpr r12 = 12; /* reg_map[11]: GOT */+static const sljit_gpr r13 = 13; /* reg_map[12]: Literal Pool pointer */+static const sljit_gpr r14 = 14; /* reg_map[0]: return address */+static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stack pointer */++/* WARNING: r12 and r13 shouldn't be used as per ABI recommendation */+/* TODO(carenas): r12 might conflict in PIC code, reserve? */+/* TODO(carenas): r13 is usually pointed to "pool" per ABI, using a tmp+ * like we do know might be faster though, reserve?+ */++/* TODO(carenas): should be named TMP_REG[1-2] for consistency */+#define tmp0 r0+#define tmp1 r1++/* When reg cannot be unused. */+#define IS_GPR_REG(reg) ((reg > 0) && (reg) <= SLJIT_SP)++/* Link register. */+static const sljit_gpr link_r = 14; /* r14 */++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = {+ 0, 0, 2, 4, 6, 3, 5, 7, 15, 14, 13, 12, 11, 10, 9, 8, 1+};++#define R0A(r) (r)+#define R4A(r) ((r) << 4)+#define R8A(r) ((r) << 8)+#define R12A(r) ((r) << 12)+#define R16A(r) ((r) << 16)+#define R20A(r) ((r) << 20)+#define R28A(r) ((r) << 28)+#define R32A(r) ((r) << 32)+#define R36A(r) ((r) << 36)++#define R0(r) ((sljit_ins)reg_map[r])++#define F0(r) ((sljit_ins)freg_map[r])+#define F4(r) (R4A((sljit_ins)freg_map[r]))+#define F12(r) (R12A((sljit_ins)freg_map[r]))+#define F20(r) (R20A((sljit_ins)freg_map[r]))+#define F28(r) (R28A((sljit_ins)freg_map[r]))+#define F32(r) (R32A((sljit_ins)freg_map[r]))+#define F36(r) (R36A((sljit_ins)freg_map[r]))++struct sljit_s390x_const {+ struct sljit_const const_; /* must be first */+ sljit_sw init_value; /* required to build literal pool */+};++/* Convert SLJIT register to hardware register. */+static SLJIT_INLINE sljit_gpr gpr(sljit_s32 r)+{+ SLJIT_ASSERT(r >= 0 && r < (sljit_s32)(sizeof(reg_map) / sizeof(reg_map[0])));+ return reg_map[r];+}++static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)+{+ sljit_ins *ibuf = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ibuf);+ *ibuf = ins;++ SLJIT_ASSERT(ins <= 0xffffffffffffL);++ compiler->size++;+ if (ins & 0xffff00000000L)+ compiler->size++;++ if (ins & 0xffffffff0000L)+ compiler->size++;++ return SLJIT_SUCCESS;+}++#define SLJIT_ADD_SUB_NO_COMPARE(status_flags_state) \+ (((status_flags_state) & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) \+ && !((status_flags_state) & SLJIT_CURRENT_FLAGS_COMPARE))++/* Map the given type to a 4-bit condition code mask. */+static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 type) {+ const sljit_u8 cc0 = 1 << 3; /* equal {,to zero} */+ const sljit_u8 cc1 = 1 << 2; /* less than {,zero} */+ const sljit_u8 cc2 = 1 << 1; /* greater than {,zero} */+ const sljit_u8 cc3 = 1 << 0; /* {overflow,NaN} */++ switch (type) {+ case SLJIT_EQUAL:+ if (SLJIT_ADD_SUB_NO_COMPARE(compiler->status_flags_state)) {+ sljit_s32 type = GET_FLAG_TYPE(compiler->status_flags_state);+ if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL)+ return cc0;+ if (type == SLJIT_OVERFLOW)+ return (cc0 | cc3);+ return (cc0 | cc2);+ }+ /* fallthrough */++ case SLJIT_ATOMIC_STORED:+ case SLJIT_F_EQUAL:+ case SLJIT_ORDERED_EQUAL:+ return cc0;++ case SLJIT_NOT_EQUAL:+ if (SLJIT_ADD_SUB_NO_COMPARE(compiler->status_flags_state)) {+ sljit_s32 type = GET_FLAG_TYPE(compiler->status_flags_state);+ if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL)+ return (cc1 | cc2 | cc3);+ if (type == SLJIT_OVERFLOW)+ return (cc1 | cc2);+ return (cc1 | cc3);+ }+ /* fallthrough */++ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ return (cc1 | cc2 | cc3);++ case SLJIT_LESS:+ case SLJIT_ATOMIC_NOT_STORED:+ return cc1;++ case SLJIT_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ return (cc0 | cc2 | cc3);++ case SLJIT_GREATER:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_COMPARE)+ return cc2;+ return cc3;++ case SLJIT_LESS_EQUAL:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_COMPARE)+ return (cc0 | cc1);+ return (cc0 | cc1 | cc2);++ case SLJIT_SIG_LESS:+ case SLJIT_F_LESS:+ case SLJIT_ORDERED_LESS:+ return cc1;++ case SLJIT_NOT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)+ return (cc2 | cc3);+ /* fallthrough */++ case SLJIT_SIG_LESS_EQUAL:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ return (cc0 | cc1);++ case SLJIT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)+ return (cc0 | cc1);+ /* fallthrough */++ case SLJIT_SIG_GREATER:+ case SLJIT_UNORDERED_OR_GREATER:+ /* Overflow is considered greater, see SLJIT_SUB. */+ return cc2 | cc3;++ case SLJIT_SIG_GREATER_EQUAL:+ return (cc0 | cc2 | cc3);++ case SLJIT_OVERFLOW:+ if (compiler->status_flags_state & SLJIT_SET_Z)+ return (cc2 | cc3);+ /* fallthrough */++ case SLJIT_UNORDERED:+ return cc3;++ case SLJIT_NOT_OVERFLOW:+ if (compiler->status_flags_state & SLJIT_SET_Z)+ return (cc0 | cc1);+ /* fallthrough */++ case SLJIT_ORDERED:+ return (cc0 | cc1 | cc2);++ case SLJIT_F_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ return (cc1 | cc2);++ case SLJIT_F_GREATER:+ case SLJIT_ORDERED_GREATER:+ return cc2;++ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ return (cc0 | cc2);++ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ return (cc0 | cc1 | cc3);++ case SLJIT_UNORDERED_OR_EQUAL:+ return (cc0 | cc3);++ case SLJIT_UNORDERED_OR_LESS:+ return (cc1 | cc3);+ }++ SLJIT_UNREACHABLE();+ return (sljit_u8)-1;+}++/* Facility to bit index mappings.+ Note: some facilities share the same bit index. */+typedef sljit_uw facility_bit;+#define STORE_FACILITY_LIST_EXTENDED_FACILITY 7+#define FAST_LONG_DISPLACEMENT_FACILITY 19+#define EXTENDED_IMMEDIATE_FACILITY 21+#define GENERAL_INSTRUCTION_EXTENSION_FACILITY 34+#define DISTINCT_OPERAND_FACILITY 45+#define HIGH_WORD_FACILITY 45+#define POPULATION_COUNT_FACILITY 45+#define LOAD_STORE_ON_CONDITION_1_FACILITY 45+#define MISCELLANEOUS_INSTRUCTION_EXTENSIONS_1_FACILITY 49+#define LOAD_STORE_ON_CONDITION_2_FACILITY 53+#define MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY 58+#define VECTOR_FACILITY 129+#define VECTOR_ENHANCEMENTS_1_FACILITY 135++/* Report whether a facility is known to be present due to the compiler+ settings. This function should always be compiled to a constant+ value given a constant argument. */+static SLJIT_INLINE int have_facility_static(facility_bit x)+{+#if ENABLE_STATIC_FACILITY_DETECTION+ switch (x) {+ case FAST_LONG_DISPLACEMENT_FACILITY:+ return (__ARCH__ >= 6 /* z990 */);+ case EXTENDED_IMMEDIATE_FACILITY:+ case STORE_FACILITY_LIST_EXTENDED_FACILITY:+ return (__ARCH__ >= 7 /* z9-109 */);+ case GENERAL_INSTRUCTION_EXTENSION_FACILITY:+ return (__ARCH__ >= 8 /* z10 */);+ case DISTINCT_OPERAND_FACILITY:+ return (__ARCH__ >= 9 /* z196 */);+ case MISCELLANEOUS_INSTRUCTION_EXTENSIONS_1_FACILITY:+ return (__ARCH__ >= 10 /* zEC12 */);+ case LOAD_STORE_ON_CONDITION_2_FACILITY:+ case VECTOR_FACILITY:+ return (__ARCH__ >= 11 /* z13 */);+ case MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY:+ case VECTOR_ENHANCEMENTS_1_FACILITY:+ return (__ARCH__ >= 12 /* z14 */);+ default:+ SLJIT_UNREACHABLE();+ }+#endif+ return 0;+}++static SLJIT_INLINE unsigned long get_hwcap()+{+ static unsigned long hwcap = 0;+ if (SLJIT_UNLIKELY(!hwcap)) {+ hwcap = getauxval(AT_HWCAP);+ SLJIT_ASSERT(hwcap != 0);+ }+ return hwcap;+}++static SLJIT_INLINE int have_stfle()+{+ if (have_facility_static(STORE_FACILITY_LIST_EXTENDED_FACILITY))+ return 1;++ return (get_hwcap() & HWCAP_S390_STFLE);+}++/* Report whether the given facility is available. This function always+ performs a runtime check. */+static int have_facility_dynamic(facility_bit x)+{+#if ENABLE_DYNAMIC_FACILITY_DETECTION+ static struct {+ sljit_uw bits[4];+ } cpu_features;+ size_t size = sizeof(cpu_features);+ const sljit_uw word_index = x >> 6;+ const sljit_uw bit_index = ((1UL << 63) >> (x & 63));++ SLJIT_ASSERT(x < size * 8);+ if (SLJIT_UNLIKELY(!have_stfle()))+ return 0;++ if (SLJIT_UNLIKELY(cpu_features.bits[0] == 0)) {+ __asm__ __volatile__ (+ "lgr %%r0, %0;"+ "stfle 0(%1);"+ /* outputs */:+ /* inputs */: "d" ((size / 8) - 1), "a" (&cpu_features)+ /* clobbers */: "r0", "cc", "memory"+ );+ SLJIT_ASSERT(cpu_features.bits[0] != 0);+ }+ return (cpu_features.bits[word_index] & bit_index) != 0;+#else+ return 0;+#endif+}++#define HAVE_FACILITY(name, bit) \+static SLJIT_INLINE int name() \+{ \+ static int have = -1; \+ /* Static check first. May allow the function to be optimized away. */ \+ if (have_facility_static(bit)) \+ have = 1; \+ else if (SLJIT_UNLIKELY(have < 0)) \+ have = have_facility_dynamic(bit) ? 1 : 0; \+\+ return have; \+}++HAVE_FACILITY(have_eimm, EXTENDED_IMMEDIATE_FACILITY)+HAVE_FACILITY(have_ldisp, FAST_LONG_DISPLACEMENT_FACILITY)+HAVE_FACILITY(have_genext, GENERAL_INSTRUCTION_EXTENSION_FACILITY)+HAVE_FACILITY(have_lscond1, LOAD_STORE_ON_CONDITION_1_FACILITY)+HAVE_FACILITY(have_lscond2, LOAD_STORE_ON_CONDITION_2_FACILITY)+HAVE_FACILITY(have_misc2, MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY)+#undef HAVE_FACILITY++#define is_u12(d) (0 <= (d) && (d) <= 0x00000fffL)+#define is_u32(d) (0 <= (d) && (d) <= 0xffffffffL)++#define CHECK_SIGNED(v, bitlen) \+ ((v) >= -(1 << ((bitlen) - 1)) && (v) < (1 << ((bitlen) - 1)))++#define is_s8(d) CHECK_SIGNED((d), 8)+#define is_s16(d) CHECK_SIGNED((d), 16)+#define is_s20(d) CHECK_SIGNED((d), 20)+#define is_s32(d) ((d) == (sljit_s32)(d))++static SLJIT_INLINE sljit_ins disp_s20(sljit_s32 d)+{+ sljit_uw dh, dl;++ SLJIT_ASSERT(is_s20(d));++ dh = (d >> 12) & 0xff;+ dl = ((sljit_uw)d << 8) & 0xfff00;+ return (dh | dl) << 8;+}++/* TODO(carenas): variadic macro is not strictly needed */+#define SLJIT_S390X_INSTRUCTION(op, ...) \+static SLJIT_INLINE sljit_ins op(__VA_ARGS__)++/* RR form instructions. */+#define SLJIT_S390X_RR(name, pattern) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src) \+{ \+ return (pattern) | ((dst & 0xf) << 4) | (src & 0xf); \+}++/* AND */+SLJIT_S390X_RR(nr, 0x1400)++/* BRANCH AND SAVE */+SLJIT_S390X_RR(basr, 0x0d00)++/* BRANCH ON CONDITION */+SLJIT_S390X_RR(bcr, 0x0700) /* TODO(mundaym): type for mask? */++/* DIVIDE */+SLJIT_S390X_RR(dr, 0x1d00)++/* EXCLUSIVE OR */+SLJIT_S390X_RR(xr, 0x1700)++/* LOAD */+SLJIT_S390X_RR(lr, 0x1800)++/* LOAD COMPLEMENT */+SLJIT_S390X_RR(lcr, 0x1300)++/* OR */+SLJIT_S390X_RR(or, 0x1600)++#undef SLJIT_S390X_RR++/* RRE form instructions */+#define SLJIT_S390X_RRE(name, pattern) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src) \+{ \+ return (pattern) | R4A(dst) | R0A(src); \+}++/* AND */+SLJIT_S390X_RRE(ngr, 0xb9800000)++/* DIVIDE LOGICAL */+SLJIT_S390X_RRE(dlr, 0xb9970000)+SLJIT_S390X_RRE(dlgr, 0xb9870000)++/* DIVIDE SINGLE */+SLJIT_S390X_RRE(dsgr, 0xb90d0000)++/* EXCLUSIVE OR */+SLJIT_S390X_RRE(xgr, 0xb9820000)++/* LOAD */+SLJIT_S390X_RRE(lgr, 0xb9040000)+SLJIT_S390X_RRE(lgfr, 0xb9140000)++/* LOAD BYTE */+SLJIT_S390X_RRE(lbr, 0xb9260000)+SLJIT_S390X_RRE(lgbr, 0xb9060000)++/* LOAD COMPLEMENT */+SLJIT_S390X_RRE(lcgr, 0xb9030000)++/* LOAD HALFWORD */+SLJIT_S390X_RRE(lhr, 0xb9270000)+SLJIT_S390X_RRE(lghr, 0xb9070000)++/* LOAD LOGICAL */+SLJIT_S390X_RRE(llgfr, 0xb9160000)++/* LOAD LOGICAL CHARACTER */+SLJIT_S390X_RRE(llcr, 0xb9940000)+SLJIT_S390X_RRE(llgcr, 0xb9840000)++/* LOAD LOGICAL HALFWORD */+SLJIT_S390X_RRE(llhr, 0xb9950000)+SLJIT_S390X_RRE(llghr, 0xb9850000)++/* MULTIPLY LOGICAL */+SLJIT_S390X_RRE(mlgr, 0xb9860000)++/* MULTIPLY SINGLE */+SLJIT_S390X_RRE(msgfr, 0xb91c0000)++/* OR */+SLJIT_S390X_RRE(ogr, 0xb9810000)++/* SUBTRACT */+SLJIT_S390X_RRE(sgr, 0xb9090000)++#undef SLJIT_S390X_RRE++/* RI-a form instructions */+#define SLJIT_S390X_RIA(name, pattern, imm_type) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \+{ \+ return (pattern) | R20A(reg) | (imm & 0xffff); \+}++/* ADD HALFWORD IMMEDIATE */+SLJIT_S390X_RIA(aghi, 0xa70b0000, sljit_s16)++/* LOAD HALFWORD IMMEDIATE */+SLJIT_S390X_RIA(lhi, 0xa7080000, sljit_s16)+SLJIT_S390X_RIA(lghi, 0xa7090000, sljit_s16)++/* LOAD LOGICAL IMMEDIATE */+SLJIT_S390X_RIA(llihh, 0xa50c0000, sljit_u16)+SLJIT_S390X_RIA(llihl, 0xa50d0000, sljit_u16)+SLJIT_S390X_RIA(llilh, 0xa50e0000, sljit_u16)+SLJIT_S390X_RIA(llill, 0xa50f0000, sljit_u16)++/* MULTIPLY HALFWORD IMMEDIATE */+SLJIT_S390X_RIA(mhi, 0xa70c0000, sljit_s16)+SLJIT_S390X_RIA(mghi, 0xa70d0000, sljit_s16)++/* OR IMMEDIATE */+SLJIT_S390X_RIA(oilh, 0xa50a0000, sljit_u16)++#undef SLJIT_S390X_RIA++/* RIL-a form instructions (requires extended immediate facility) */+#define SLJIT_S390X_RILA(name, pattern, imm_type) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \+{ \+ SLJIT_ASSERT(have_eimm()); \+ return (pattern) | R36A(reg) | ((sljit_ins)imm & 0xffffffffu); \+}++/* ADD IMMEDIATE */+SLJIT_S390X_RILA(agfi, 0xc20800000000, sljit_s32)++/* ADD IMMEDIATE HIGH */+SLJIT_S390X_RILA(aih, 0xcc0800000000, sljit_s32) /* TODO(mundaym): high-word facility? */++/* AND IMMEDIATE */+SLJIT_S390X_RILA(nihf, 0xc00a00000000, sljit_u32)++/* EXCLUSIVE OR IMMEDIATE */+SLJIT_S390X_RILA(xilf, 0xc00700000000, sljit_u32)++/* INSERT IMMEDIATE */+SLJIT_S390X_RILA(iihf, 0xc00800000000, sljit_u32)+SLJIT_S390X_RILA(iilf, 0xc00900000000, sljit_u32)++/* LOAD IMMEDIATE */+SLJIT_S390X_RILA(lgfi, 0xc00100000000, sljit_s32)++/* LOAD LOGICAL IMMEDIATE */+SLJIT_S390X_RILA(llihf, 0xc00e00000000, sljit_u32)+SLJIT_S390X_RILA(llilf, 0xc00f00000000, sljit_u32)++/* SUBTRACT LOGICAL IMMEDIATE */+SLJIT_S390X_RILA(slfi, 0xc20500000000, sljit_u32)++#undef SLJIT_S390X_RILA++/* RX-a form instructions */+#define SLJIT_S390X_RXA(name, pattern) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b) \+{ \+ SLJIT_ASSERT((d & 0xfff) == d); \+\+ return (pattern) | R20A(r) | R16A(x) | R12A(b) | (sljit_ins)(d & 0xfff); \+}++/* LOAD */+SLJIT_S390X_RXA(l, 0x58000000)++/* LOAD ADDRESS */+SLJIT_S390X_RXA(la, 0x41000000)++/* LOAD HALFWORD */+SLJIT_S390X_RXA(lh, 0x48000000)++/* MULTIPLY SINGLE */+SLJIT_S390X_RXA(ms, 0x71000000)++/* STORE */+SLJIT_S390X_RXA(st, 0x50000000)++/* STORE CHARACTER */+SLJIT_S390X_RXA(stc, 0x42000000)++/* STORE HALFWORD */+SLJIT_S390X_RXA(sth, 0x40000000)++#undef SLJIT_S390X_RXA++/* RXY-a instructions */+#define SLJIT_S390X_RXYA(name, pattern, cond) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b) \+{ \+ SLJIT_ASSERT(cond); \+\+ return (pattern) | R36A(r) | R32A(x) | R28A(b) | disp_s20(d); \+}++/* LOAD */+SLJIT_S390X_RXYA(ly, 0xe30000000058, have_ldisp())+SLJIT_S390X_RXYA(lg, 0xe30000000004, 1)+SLJIT_S390X_RXYA(lgf, 0xe30000000014, 1)++/* LOAD BYTE */+SLJIT_S390X_RXYA(lb, 0xe30000000076, have_ldisp())+SLJIT_S390X_RXYA(lgb, 0xe30000000077, have_ldisp())++/* LOAD HALFWORD */+SLJIT_S390X_RXYA(lhy, 0xe30000000078, have_ldisp())+SLJIT_S390X_RXYA(lgh, 0xe30000000015, 1)++/* LOAD LOGICAL */+SLJIT_S390X_RXYA(llgf, 0xe30000000016, 1)++/* LOAD LOGICAL CHARACTER */+SLJIT_S390X_RXYA(llc, 0xe30000000094, have_eimm())+SLJIT_S390X_RXYA(llgc, 0xe30000000090, 1)++/* LOAD LOGICAL HALFWORD */+SLJIT_S390X_RXYA(llh, 0xe30000000095, have_eimm())+SLJIT_S390X_RXYA(llgh, 0xe30000000091, 1)++/* MULTIPLY SINGLE */+SLJIT_S390X_RXYA(msy, 0xe30000000051, have_ldisp())+SLJIT_S390X_RXYA(msg, 0xe3000000000c, 1)++/* STORE */+SLJIT_S390X_RXYA(sty, 0xe30000000050, have_ldisp())+SLJIT_S390X_RXYA(stg, 0xe30000000024, 1)++/* STORE CHARACTER */+SLJIT_S390X_RXYA(stcy, 0xe30000000072, have_ldisp())++/* STORE HALFWORD */+SLJIT_S390X_RXYA(sthy, 0xe30000000070, have_ldisp())++#undef SLJIT_S390X_RXYA++/* RSY-a instructions */+#define SLJIT_S390X_RSYA(name, pattern, cond) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_s32 d, sljit_gpr b) \+{ \+ SLJIT_ASSERT(cond); \+\+ return (pattern) | R36A(dst) | R32A(src) | R28A(b) | disp_s20(d); \+}++/* LOAD MULTIPLE */+SLJIT_S390X_RSYA(lmg, 0xeb0000000004, 1)++/* SHIFT LEFT LOGICAL */+SLJIT_S390X_RSYA(sllg, 0xeb000000000d, 1)++/* SHIFT RIGHT SINGLE */+SLJIT_S390X_RSYA(srag, 0xeb000000000a, 1)++/* STORE MULTIPLE */+SLJIT_S390X_RSYA(stmg, 0xeb0000000024, 1)++#undef SLJIT_S390X_RSYA++/* RIE-f instructions (require general-instructions-extension facility) */+#define SLJIT_S390X_RIEF(name, pattern) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_u8 start, sljit_u8 end, sljit_u8 rot) \+{ \+ sljit_ins i3, i4, i5; \+\+ SLJIT_ASSERT(have_genext()); \+ i3 = (sljit_ins)start << 24; \+ i4 = (sljit_ins)end << 16; \+ i5 = (sljit_ins)rot << 8; \+\+ return (pattern) | R36A(dst & 0xf) | R32A(src & 0xf) | i3 | i4 | i5; \+}++/* ROTATE THEN AND SELECTED BITS */+/* SLJIT_S390X_RIEF(rnsbg, 0xec0000000054) */++/* ROTATE THEN EXCLUSIVE OR SELECTED BITS */+/* SLJIT_S390X_RIEF(rxsbg, 0xec0000000057) */++/* ROTATE THEN OR SELECTED BITS */+SLJIT_S390X_RIEF(rosbg, 0xec0000000056)++/* ROTATE THEN INSERT SELECTED BITS */+/* SLJIT_S390X_RIEF(risbg, 0xec0000000055) */+/* SLJIT_S390X_RIEF(risbgn, 0xec0000000059) */++/* ROTATE THEN INSERT SELECTED BITS HIGH */+SLJIT_S390X_RIEF(risbhg, 0xec000000005d)++/* ROTATE THEN INSERT SELECTED BITS LOW */+/* SLJIT_S390X_RIEF(risblg, 0xec0000000051) */++#undef SLJIT_S390X_RIEF++/* RRF-c instructions (require load/store-on-condition 1 facility) */+#define SLJIT_S390X_RRFC(name, pattern) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_uw mask) \+{ \+ sljit_ins m3; \+\+ SLJIT_ASSERT(have_lscond1()); \+ m3 = (sljit_ins)(mask & 0xf) << 12; \+\+ return (pattern) | m3 | R4A(dst) | R0A(src); \+}++/* LOAD HALFWORD IMMEDIATE ON CONDITION */+SLJIT_S390X_RRFC(locr, 0xb9f20000)+SLJIT_S390X_RRFC(locgr, 0xb9e20000)++#undef SLJIT_S390X_RRFC++/* RIE-g instructions (require load/store-on-condition 2 facility) */+#define SLJIT_S390X_RIEG(name, pattern) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw imm, sljit_uw mask) \+{ \+ sljit_ins m3, i2; \+\+ SLJIT_ASSERT(have_lscond2()); \+ m3 = (sljit_ins)(mask & 0xf) << 32; \+ i2 = (sljit_ins)(imm & 0xffffL) << 16; \+\+ return (pattern) | R36A(reg) | m3 | i2; \+}++/* LOAD HALFWORD IMMEDIATE ON CONDITION */+SLJIT_S390X_RIEG(lochi, 0xec0000000042)+SLJIT_S390X_RIEG(locghi, 0xec0000000046)++#undef SLJIT_S390X_RIEG++#define SLJIT_S390X_RILB(name, pattern, cond) \+SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw ri) \+{ \+ SLJIT_ASSERT(cond); \+\+ return (pattern) | R36A(reg) | (sljit_ins)(ri & 0xffffffff); \+}++/* BRANCH RELATIVE AND SAVE LONG */+SLJIT_S390X_RILB(brasl, 0xc00500000000, 1)++/* LOAD ADDRESS RELATIVE LONG */+SLJIT_S390X_RILB(larl, 0xc00000000000, 1)++/* LOAD RELATIVE LONG */+SLJIT_S390X_RILB(lgrl, 0xc40800000000, have_genext())++#undef SLJIT_S390X_RILB++SLJIT_S390X_INSTRUCTION(br, sljit_gpr target)+{+ return 0x07f0 | target;+}++SLJIT_S390X_INSTRUCTION(brc, sljit_uw mask, sljit_sw target)+{+ sljit_ins m1 = (sljit_ins)(mask & 0xf) << 20;+ sljit_ins ri2 = (sljit_ins)target & 0xffff;+ return 0xa7040000L | m1 | ri2;+}++SLJIT_S390X_INSTRUCTION(brcl, sljit_uw mask, sljit_sw target)+{+ sljit_ins m1 = (sljit_ins)(mask & 0xf) << 36;+ sljit_ins ri2 = (sljit_ins)target & 0xffffffff;+ return 0xc00400000000L | m1 | ri2;+}++SLJIT_S390X_INSTRUCTION(flogr, sljit_gpr dst, sljit_gpr src)+{+ SLJIT_ASSERT(have_eimm());+ return 0xb9830000 | R8A(dst) | R0A(src);+}++/* INSERT PROGRAM MASK */+SLJIT_S390X_INSTRUCTION(ipm, sljit_gpr dst)+{+ return 0xb2220000 | R4A(dst);+}++/* SET PROGRAM MASK */+SLJIT_S390X_INSTRUCTION(spm, sljit_gpr dst)+{+ return 0x0400 | R4A(dst);+}++/* ROTATE THEN INSERT SELECTED BITS HIGH (ZERO) */+SLJIT_S390X_INSTRUCTION(risbhgz, sljit_gpr dst, sljit_gpr src, sljit_u8 start, sljit_u8 end, sljit_u8 rot)+{+ return risbhg(dst, src, start, 0x8 | end, rot);+}++#undef SLJIT_S390X_INSTRUCTION++static sljit_s32 update_zero_overflow(struct sljit_compiler *compiler, sljit_s32 op, sljit_gpr dst_r)+{+ /* Condition codes: bits 18 and 19.+ Transformation:+ 0 (zero and no overflow) : unchanged+ 1 (non-zero and no overflow) : unchanged+ 2 (zero and overflow) : decreased by 1+ 3 (non-zero and overflow) : decreased by 1 if non-zero */+ FAIL_IF(push_inst(compiler, brc(0xc, 2 + 2 + ((op & SLJIT_32) ? 1 : 2) + 2 + 3 + 1)));+ FAIL_IF(push_inst(compiler, ipm(tmp1)));+ FAIL_IF(push_inst(compiler, (op & SLJIT_32) ? or(dst_r, dst_r) : ogr(dst_r, dst_r)));+ FAIL_IF(push_inst(compiler, brc(0x8, 2 + 3)));+ FAIL_IF(push_inst(compiler, slfi(tmp1, 0x10000000)));+ FAIL_IF(push_inst(compiler, spm(tmp1)));+ return SLJIT_SUCCESS;+}++/* load 64-bit immediate into register without clobbering flags */+static sljit_s32 push_load_imm_inst(struct sljit_compiler *compiler, sljit_gpr target, sljit_sw v)+{+ /* 4 byte instructions */+ if (is_s16(v))+ return push_inst(compiler, lghi(target, (sljit_s16)v));++ if (((sljit_uw)v & ~(sljit_uw)0x000000000000ffff) == 0)+ return push_inst(compiler, llill(target, (sljit_u16)v));++ if (((sljit_uw)v & ~(sljit_uw)0x00000000ffff0000) == 0)+ return push_inst(compiler, llilh(target, (sljit_u16)(v >> 16)));++ if (((sljit_uw)v & ~(sljit_uw)0x0000ffff00000000) == 0)+ return push_inst(compiler, llihl(target, (sljit_u16)(v >> 32)));++ if (((sljit_uw)v & ~(sljit_uw)0xffff000000000000) == 0)+ return push_inst(compiler, llihh(target, (sljit_u16)(v >> 48)));++ if (is_s32(v))+ return push_inst(compiler, lgfi(target, (sljit_s32)v));++ if (((sljit_uw)v >> 32) == 0)+ return push_inst(compiler, llilf(target, (sljit_u32)v));++ if (((sljit_uw)v << 32) == 0)+ return push_inst(compiler, llihf(target, (sljit_u32)((sljit_uw)v >> 32)));++ FAIL_IF(push_inst(compiler, llilf(target, (sljit_u32)v)));+ return push_inst(compiler, iihf(target, (sljit_u32)(v >> 32)));+}++struct addr {+ sljit_gpr base;+ sljit_gpr index;+ sljit_s32 offset;+};++/* transform memory operand into D(X,B) form with a signed 20-bit offset */+static sljit_s32 make_addr_bxy(struct sljit_compiler *compiler,+ struct addr *addr, sljit_s32 mem, sljit_sw off,+ sljit_gpr tmp /* clobbered, must not be r0 */)+{+ sljit_gpr base = r0;+ sljit_gpr index = r0;++ SLJIT_ASSERT(tmp != r0);+ if (mem & REG_MASK)+ base = gpr(mem & REG_MASK);++ if (mem & OFFS_REG_MASK) {+ index = gpr(OFFS_REG(mem));+ if (off != 0) {+ /* shift and put the result into tmp */+ SLJIT_ASSERT(0 <= off && off < 64);+ FAIL_IF(push_inst(compiler, sllg(tmp, index, (sljit_s32)off, 0)));+ index = tmp;+ off = 0; /* clear offset */+ }+ }+ else if (!is_s20(off)) {+ FAIL_IF(push_load_imm_inst(compiler, tmp, off));+ index = tmp;+ off = 0; /* clear offset */+ }+ addr->base = base;+ addr->index = index;+ addr->offset = (sljit_s32)off;+ return SLJIT_SUCCESS;+}++/* transform memory operand into D(X,B) form with an unsigned 12-bit offset */+static sljit_s32 make_addr_bx(struct sljit_compiler *compiler,+ struct addr *addr, sljit_s32 mem, sljit_sw off,+ sljit_gpr tmp /* clobbered, must not be r0 */)+{+ sljit_gpr base = r0;+ sljit_gpr index = r0;++ SLJIT_ASSERT(tmp != r0);+ if (mem & REG_MASK)+ base = gpr(mem & REG_MASK);++ if (mem & OFFS_REG_MASK) {+ index = gpr(OFFS_REG(mem));+ if (off != 0) {+ /* shift and put the result into tmp */+ SLJIT_ASSERT(0 <= off && off < 64);+ FAIL_IF(push_inst(compiler, sllg(tmp, index, (sljit_s32)off, 0)));+ index = tmp;+ off = 0; /* clear offset */+ }+ }+ else if (!is_u12(off)) {+ FAIL_IF(push_load_imm_inst(compiler, tmp, off));+ index = tmp;+ off = 0; /* clear offset */+ }+ addr->base = base;+ addr->index = index;+ addr->offset = (sljit_s32)off;+ return SLJIT_SUCCESS;+}++#define EVAL(op, r, addr) op(r, addr.offset, addr.index, addr.base)+#define WHEN(cond, r, i1, i2, addr) \+ (cond) ? EVAL(i1, r, addr) : EVAL(i2, r, addr)++/* May clobber tmp1. */+static sljit_s32 load_store_op(struct sljit_compiler *compiler, sljit_gpr reg,+ sljit_s32 mem, sljit_sw memw,+ sljit_s32 is_32bit, const sljit_ins* forms)+{+ struct addr addr;++ SLJIT_ASSERT(mem & SLJIT_MEM);++ if (is_32bit && ((mem & OFFS_REG_MASK) || is_u12(memw) || !is_s20(memw))) {+ FAIL_IF(make_addr_bx(compiler, &addr, mem, memw, tmp1));+ return push_inst(compiler, forms[0] | R20A(reg) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset);+ }++ FAIL_IF(make_addr_bxy(compiler, &addr, mem, memw, tmp1));+ return push_inst(compiler, (is_32bit ? forms[1] : forms[2]) | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));+}++static const sljit_ins load_forms[3] = {+ 0x58000000 /* l */,+ 0xe30000000058 /* ly */,+ 0xe30000000004 /* lg */+};++static const sljit_ins store_forms[3] = {+ 0x50000000 /* st */,+ 0xe30000000050 /* sty */,+ 0xe30000000024 /* stg */+};++static const sljit_ins load_halfword_forms[3] = {+ 0x48000000 /* lh */,+ 0xe30000000078 /* lhy */,+ 0xe30000000015 /* lgh */+};++/* May clobber tmp1. */+static SLJIT_INLINE sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst_r,+ sljit_s32 src, sljit_sw srcw,+ sljit_s32 is_32bit)+{+ return load_store_op(compiler, dst_r, src, srcw, is_32bit, load_forms);+}++/* May clobber tmp1. */+static sljit_s32 load_unsigned_word(struct sljit_compiler *compiler, sljit_gpr dst_r,+ sljit_s32 src, sljit_sw srcw,+ sljit_s32 is_32bit)+{+ struct addr addr;+ sljit_ins ins;++ SLJIT_ASSERT(src & SLJIT_MEM);++ FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1));++ ins = is_32bit ? 0xe30000000016 /* llgf */ : 0xe30000000004 /* lg */;+ return push_inst(compiler, ins | R36A(dst_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));+}++/* May clobber tmp1. */+static SLJIT_INLINE sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src_r,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 is_32bit)+{+ return load_store_op(compiler, src_r, dst, dstw, is_32bit, store_forms);+}++#undef WHEN++static sljit_s32 emit_move(struct sljit_compiler *compiler,+ sljit_gpr dst_r,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_gpr src_r;++ SLJIT_ASSERT(!IS_GPR_REG(src) || dst_r != gpr(src & REG_MASK));++ if (src == SLJIT_IMM)+ return push_load_imm_inst(compiler, dst_r, srcw);++ if (src & SLJIT_MEM)+ return load_word(compiler, dst_r, src, srcw, (compiler->mode & SLJIT_32) != 0);++ src_r = gpr(src & REG_MASK);+ return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, src_r) : lgr(dst_r, src_r));+}++static sljit_s32 emit_rr(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_gpr dst_r = tmp0;+ sljit_gpr src_r = tmp1;+ sljit_s32 needs_move = 1;++ if (FAST_IS_REG(dst)) {+ dst_r = gpr(dst);++ if (dst == src1)+ needs_move = 0;+ else if (dst == src2) {+ dst_r = tmp0;+ needs_move = 2;+ }+ }++ if (needs_move)+ FAIL_IF(emit_move(compiler, dst_r, src1, src1w));++ if (FAST_IS_REG(src2))+ src_r = gpr(src2);+ else+ FAIL_IF(emit_move(compiler, tmp1, src2, src2w));++ FAIL_IF(push_inst(compiler, ins | R4A(dst_r) | R0A(src_r)));++ if (needs_move != 2)+ return SLJIT_SUCCESS;++ dst_r = gpr(dst & REG_MASK);+ return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));+}++static sljit_s32 emit_rr1(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w)+{+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;+ sljit_gpr src_r = tmp1;++ if (FAST_IS_REG(src1))+ src_r = gpr(src1);+ else+ FAIL_IF(emit_move(compiler, tmp1, src1, src1w));++ return push_inst(compiler, ins | R4A(dst_r) | R0A(src_r));+}++static sljit_s32 emit_rrf(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;+ sljit_gpr src1_r = tmp0;+ sljit_gpr src2_r = tmp1;++ if (FAST_IS_REG(src1))+ src1_r = gpr(src1);+ else+ FAIL_IF(emit_move(compiler, tmp0, src1, src1w));++ if (FAST_IS_REG(src2))+ src2_r = gpr(src2);+ else+ FAIL_IF(emit_move(compiler, tmp1, src2, src2w));++ return push_inst(compiler, ins | R4A(dst_r) | R0A(src1_r) | R12A(src2_r));+}++typedef enum {+ RI_A,+ RIL_A,+} emit_ril_type;++static sljit_s32 emit_ri(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_sw src2w,+ emit_ril_type type)+{+ sljit_gpr dst_r = tmp0;+ sljit_s32 needs_move = 1;++ if (FAST_IS_REG(dst)) {+ dst_r = gpr(dst);++ if (dst == src1)+ needs_move = 0;+ }++ if (needs_move)+ FAIL_IF(emit_move(compiler, dst_r, src1, src1w));++ if (type == RIL_A)+ return push_inst(compiler, ins | R36A(dst_r) | (src2w & 0xffffffff));+ return push_inst(compiler, ins | R20A(dst_r) | (src2w & 0xffff));+}++static sljit_s32 emit_rie_d(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_sw src2w)+{+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;+ sljit_gpr src_r = tmp0;++ if (!FAST_IS_REG(src1))+ FAIL_IF(emit_move(compiler, tmp0, src1, src1w));+ else+ src_r = gpr(src1 & REG_MASK);++ return push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | (sljit_ins)(src2w & 0xffff) << 16);+}++typedef enum {+ RX_A,+ RXY_A,+} emit_rx_type;++static sljit_s32 emit_rx(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w,+ emit_rx_type type)+{+ sljit_gpr dst_r = tmp0;+ sljit_s32 needs_move = 1;+ sljit_gpr base, index;++ SLJIT_ASSERT(src2 & SLJIT_MEM);++ if (FAST_IS_REG(dst)) {+ dst_r = gpr(dst);++ if (dst == src1)+ needs_move = 0;+ else if (dst == (src2 & REG_MASK) || (dst == OFFS_REG(src2))) {+ dst_r = tmp0;+ needs_move = 2;+ }+ }++ if (needs_move)+ FAIL_IF(emit_move(compiler, dst_r, src1, src1w));++ base = gpr(src2 & REG_MASK);+ index = tmp0;++ if (src2 & OFFS_REG_MASK) {+ index = gpr(OFFS_REG(src2));++ if (src2w != 0) {+ FAIL_IF(push_inst(compiler, sllg(tmp1, index, src2w & 0x3, 0)));+ src2w = 0;+ index = tmp1;+ }+ } else if ((type == RX_A && !is_u12(src2w)) || (type == RXY_A && !is_s20(src2w))) {+ FAIL_IF(push_load_imm_inst(compiler, tmp1, src2w));++ if (src2 & REG_MASK)+ index = tmp1;+ else+ base = tmp1;+ src2w = 0;+ }++ if (type == RX_A)+ ins |= R20A(dst_r) | R16A(index) | R12A(base) | (sljit_ins)src2w;+ else+ ins |= R36A(dst_r) | R32A(index) | R28A(base) | disp_s20((sljit_s32)src2w);++ FAIL_IF(push_inst(compiler, ins));++ if (needs_move != 2)+ return SLJIT_SUCCESS;++ dst_r = gpr(dst);+ return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));+}++static sljit_s32 emit_siy(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw srcw)+{+ sljit_gpr dst_r = tmp1;++ SLJIT_ASSERT(dst & SLJIT_MEM);++ if (dst & OFFS_REG_MASK) {+ sljit_gpr index = tmp1;++ if ((dstw & 0x3) == 0)+ index = gpr(OFFS_REG(dst));+ else+ FAIL_IF(push_inst(compiler, sllg(tmp1, index, dstw & 0x3, 0)));++ FAIL_IF(push_inst(compiler, la(tmp1, 0, dst_r, index)));+ dstw = 0;+ }+ else if (!is_s20(dstw)) {+ FAIL_IF(push_load_imm_inst(compiler, tmp1, dstw));++ if (dst & REG_MASK)+ FAIL_IF(push_inst(compiler, la(tmp1, 0, dst_r, tmp1)));++ dstw = 0;+ }+ else+ dst_r = gpr(dst & REG_MASK);++ return push_inst(compiler, ins | ((sljit_ins)(srcw & 0xff) << 32) | R28A(dst_r) | disp_s20((sljit_s32)dstw));+}++struct ins_forms {+ sljit_ins op_r;+ sljit_ins op_gr;+ sljit_ins op_rk;+ sljit_ins op_grk;+ sljit_ins op;+ sljit_ins op_y;+ sljit_ins op_g;+};++static sljit_s32 emit_commutative(struct sljit_compiler *compiler, const struct ins_forms *forms,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 mode = compiler->mode;+ sljit_ins ins, ins_k;++ if ((src1 | src2) & SLJIT_MEM) {+ sljit_ins ins12, ins20;++ if (mode & SLJIT_32) {+ ins12 = forms->op;+ ins20 = forms->op_y;+ }+ else {+ ins12 = 0;+ ins20 = forms->op_g;+ }++ if (ins12 && ins20) {+ /* Extra instructions needed for address computation can be executed independently. */+ if ((src2 & SLJIT_MEM) && (!(src1 & SLJIT_MEM)+ || ((src1 & OFFS_REG_MASK) ? (src1w & 0x3) == 0 : is_s20(src1w)))) {+ if ((src2 & OFFS_REG_MASK) || is_u12(src2w) || !is_s20(src2w))+ return emit_rx(compiler, ins12, dst, src1, src1w, src2, src2w, RX_A);++ return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);+ }++ if (src1 & SLJIT_MEM) {+ if ((src1 & OFFS_REG_MASK) || is_u12(src1w) || !is_s20(src1w))+ return emit_rx(compiler, ins12, dst, src2, src2w, src1, src1w, RX_A);++ return emit_rx(compiler, ins20, dst, src2, src2w, src1, src1w, RXY_A);+ }+ }+ else if (ins12 || ins20) {+ emit_rx_type rx_type;++ if (ins12) {+ rx_type = RX_A;+ ins = ins12;+ }+ else {+ rx_type = RXY_A;+ ins = ins20;+ }++ if ((src2 & SLJIT_MEM) && (!(src1 & SLJIT_MEM)+ || ((src1 & OFFS_REG_MASK) ? (src1w & 0x3) == 0 : (rx_type == RX_A ? is_u12(src1w) : is_s20(src1w)))))+ return emit_rx(compiler, ins, dst, src1, src1w, src2, src2w, rx_type);++ if (src1 & SLJIT_MEM)+ return emit_rx(compiler, ins, dst, src2, src2w, src1, src1w, rx_type);+ }+ }++ if (mode & SLJIT_32) {+ ins = forms->op_r;+ ins_k = forms->op_rk;+ }+ else {+ ins = forms->op_gr;+ ins_k = forms->op_grk;+ }++ SLJIT_ASSERT(ins != 0 || ins_k != 0);++ if (ins && FAST_IS_REG(dst)) {+ if (dst == src1)+ return emit_rr(compiler, ins, dst, src1, src1w, src2, src2w);++ if (dst == src2)+ return emit_rr(compiler, ins, dst, src2, src2w, src1, src1w);+ }++ if (ins_k == 0)+ return emit_rr(compiler, ins, dst, src1, src1w, src2, src2w);++ return emit_rrf(compiler, ins_k, dst, src1, src1w, src2, src2w);+}++static sljit_s32 emit_non_commutative(struct sljit_compiler *compiler, const struct ins_forms *forms,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 mode = compiler->mode;+ sljit_ins ins;++ if (src2 & SLJIT_MEM) {+ sljit_ins ins12, ins20;++ if (mode & SLJIT_32) {+ ins12 = forms->op;+ ins20 = forms->op_y;+ }+ else {+ ins12 = 0;+ ins20 = forms->op_g;+ }++ if (ins12 && ins20) {+ if ((src2 & OFFS_REG_MASK) || is_u12(src2w) || !is_s20(src2w))+ return emit_rx(compiler, ins12, dst, src1, src1w, src2, src2w, RX_A);++ return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);+ }+ else if (ins12)+ return emit_rx(compiler, ins12, dst, src1, src1w, src2, src2w, RX_A);+ else if (ins20)+ return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);+ }++ ins = (mode & SLJIT_32) ? forms->op_rk : forms->op_grk;++ if (ins == 0 || (FAST_IS_REG(dst) && dst == src1))+ return emit_rr(compiler, (mode & SLJIT_32) ? forms->op_r : forms->op_gr, dst, src1, src1w, src2, src2w);++ return emit_rrf(compiler, ins, dst, src1, src1w, src2, src2w);+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)+{+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ sljit_sw executable_offset;+ sljit_uw ins_size = compiler->size << 1;+ sljit_uw pool_size = 0; /* literal pool */+ sljit_uw pad_size;+ sljit_uw half_count;+ SLJIT_NEXT_DEFINE_TYPES;+ struct sljit_memory_fragment *buf;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_u16 *code;+ sljit_u16 *code_ptr;+ sljit_uw *pool, *pool_ptr;+ sljit_ins ins;+ sljit_sw source, offset;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++ jump = compiler->jumps;+ while (jump != NULL) {+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR | JUMP_MOV_ADDR)) {+ /* encoded: */+ /* brasl %r14, <rel_addr> (or brcl <mask>, <rel_addr>) */+ /* replace with: */+ /* lgrl %r1, <pool_addr> */+ /* bras %r14, %r1 (or bcr <mask>, %r1) */+ pool_size += sizeof(*pool);+ if (!(jump->flags & JUMP_MOV_ADDR))+ ins_size += 2;+ }+ jump = jump->next;+ }++ const_ = compiler->consts;+ while (const_) {+ pool_size += sizeof(*pool);+ const_ = const_->next;+ }++ /* pad code size to 8 bytes so is accessible with half word offsets */+ /* the literal pool needs to be doubleword aligned */+ pad_size = ((ins_size + 7UL) & ~7UL) - ins_size;+ SLJIT_ASSERT(pad_size < 8UL);++ /* allocate target buffer */+ code = (sljit_u16*)allocate_executable_memory(ins_size + pad_size + pool_size, options, exec_allocator_data, &executable_offset);+ PTR_FAIL_WITH_EXEC_IF(code);+ code_ptr = code;++ /* TODO(carenas): pool is optional, and the ABI recommends it to+ * be created before the function code, instead of+ * globally; if generated code is too big could+ * need offsets bigger than 32bit words and asser()+ */+ pool = (sljit_uw *)((sljit_uw)code + ins_size + pad_size);+ pool_ptr = pool;+ buf = compiler->buf;+ half_count = 0;++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ SLJIT_NEXT_INIT_TYPES();+ SLJIT_GET_NEXT_MIN();++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 3);+ do {+ ins = *buf_ptr++;++ if (next_min_addr == half_count) {+ SLJIT_ASSERT(!label || label->size >= half_count);+ SLJIT_ASSERT(!jump || jump->addr >= half_count);+ SLJIT_ASSERT(!const_ || const_->addr >= half_count);++ if (next_min_addr == next_label_size) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr == next_jump_addr) {+ if (SLJIT_UNLIKELY(jump->flags & JUMP_MOV_ADDR)) {+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ jump->addr = (sljit_uw)pool_ptr;++ /* store target into pool */+ offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;+ pool_ptr++;++ SLJIT_ASSERT(!(offset & 1));+ offset >>= 1;+ SLJIT_ASSERT(is_s32(offset));+ ins |= (sljit_ins)offset & 0xffffffff;+ } else if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR)) {+ sljit_ins arg;++ jump->addr = (sljit_uw)pool_ptr;++ /* load address into tmp1 */+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;++ SLJIT_ASSERT(!(offset & 1));+ offset >>= 1;+ SLJIT_ASSERT(is_s32(offset));++ code_ptr[0] = (sljit_u16)(0xc408 | R4A(tmp1) /* lgrl */);+ code_ptr[1] = (sljit_u16)(offset >> 16);+ code_ptr[2] = (sljit_u16)offset;+ code_ptr += 3;+ pool_ptr++;++ /* branch to tmp1 */+ arg = (ins >> 36) & 0xf;+ if (((ins >> 32) & 0xf) == 4) {+ /* brcl -> bcr */+ ins = bcr(arg, tmp1);+ } else {+ SLJIT_ASSERT(((ins >> 32) & 0xf) == 5);+ /* brasl -> basr */+ ins = basr(arg, tmp1);+ }++ /* Adjust half_count. */+ half_count += 2;+ } else+ jump->addr = (sljit_uw)code_ptr;++ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ } else if (next_min_addr == next_const_addr) {+ /* update instruction with relative address of constant */+ source = (sljit_sw)code_ptr;+ offset = (sljit_sw)pool_ptr - source;++ SLJIT_ASSERT(!(offset & 0x1));+ offset >>= 1; /* halfword (not byte) offset */+ SLJIT_ASSERT(is_s32(offset));++ ins |= (sljit_ins)offset & 0xffffffff;++ /* update address */+ const_->addr = (sljit_uw)pool_ptr;++ /* store initial value into pool and update pool address */+ *(pool_ptr++) = (sljit_uw)(((struct sljit_s390x_const*)const_)->init_value);++ /* move to next constant */+ const_ = const_->next;+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);+ }++ SLJIT_GET_NEXT_MIN();+ }++ if (ins & 0xffff00000000L) {+ *code_ptr++ = (sljit_u16)(ins >> 32);+ half_count++;+ }++ if (ins & 0xffffffff0000L) {+ *code_ptr++ = (sljit_u16)(ins >> 16);+ half_count++;+ }++ *code_ptr++ = (sljit_u16)ins;+ half_count++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (next_label_size == half_count) {+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(code + (ins_size >> 1) == code_ptr);+ SLJIT_ASSERT((sljit_u8 *)pool + pool_size == (sljit_u8 *)pool_ptr);++ jump = compiler->jumps;+ while (jump != NULL) {+ offset = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr);++ if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR | JUMP_MOV_ADDR)) {+ /* Store jump target into pool. */+ *(sljit_uw*)(jump->addr) = (sljit_uw)offset;+ } else {+ code_ptr = (sljit_u16*)jump->addr;+ offset -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ /* offset must be halfword aligned */+ SLJIT_ASSERT(!(offset & 1));+ offset >>= 1;+ SLJIT_ASSERT(is_s32(offset)); /* TODO(mundaym): handle arbitrary offsets */++ code_ptr[1] = (sljit_u16)(offset >> 16);+ code_ptr[2] = (sljit_u16)offset;+ }+ jump = jump->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = ins_size;+ if (pool_size)+ compiler->executable_size += (pad_size + pool_size);++ 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);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ return code;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ /* TODO(mundaym): implement all */+ switch (feature_type) {+ case SLJIT_HAS_FPU:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return (SLJIT_IS_FPU_AVAILABLE) != 0;+#else+ return 1;+#endif /* SLJIT_IS_FPU_AVAILABLE */++ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_REV:+ case SLJIT_HAS_ROT:+ case SLJIT_HAS_PREFETCH:+ case SLJIT_HAS_COPY_F32:+ case SLJIT_HAS_COPY_F64:+ case SLJIT_HAS_SIMD:+ case SLJIT_HAS_ATOMIC:+ return 1;++ case SLJIT_HAS_CTZ:+ return 2;++ case SLJIT_HAS_CMOV:+ return have_lscond1() ? 1 : 0;+ }+ return 0;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)+{+ SLJIT_UNUSED_ARG(type);+ return 0;+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);+ sljit_s32 offset, i, tmp;++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ /* Saved registers are stored in callee allocated save area. */+ SLJIT_ASSERT(gpr(SLJIT_FIRST_SAVED_REG) == r6 && gpr(SLJIT_S0) == r13);++ offset = 2 * SSIZE_OF(sw);+ if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) {+ if (saved_arg_count == 0) {+ FAIL_IF(push_inst(compiler, stmg(r6, r14, offset, r15)));+ offset += 9 * SSIZE_OF(sw);+ } else {+ FAIL_IF(push_inst(compiler, stmg(r6, r13 - (sljit_gpr)saved_arg_count, offset, r15)));+ offset += (8 - saved_arg_count) * SSIZE_OF(sw);+ }+ } else {+ if (scratches == SLJIT_FIRST_SAVED_REG) {+ FAIL_IF(push_inst(compiler, stg(r6, offset, 0, r15)));+ offset += SSIZE_OF(sw);+ } else if (scratches > SLJIT_FIRST_SAVED_REG) {+ FAIL_IF(push_inst(compiler, stmg(r6, r6 + (sljit_gpr)(scratches - SLJIT_FIRST_SAVED_REG), offset, r15)));+ offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw);+ }++ if (saved_arg_count == 0) {+ if (saveds == 0) {+ FAIL_IF(push_inst(compiler, stg(r14, offset, 0, r15)));+ offset += SSIZE_OF(sw);+ } else {+ FAIL_IF(push_inst(compiler, stmg(r14 - (sljit_gpr)saveds, r14, offset, r15)));+ offset += (saveds + 1) * SSIZE_OF(sw);+ }+ } else if (saveds > saved_arg_count) {+ if (saveds == saved_arg_count + 1) {+ FAIL_IF(push_inst(compiler, stg(r14 - (sljit_gpr)saveds, offset, 0, r15)));+ offset += SSIZE_OF(sw);+ } else {+ FAIL_IF(push_inst(compiler, stmg(r14 - (sljit_gpr)saveds, r13 - (sljit_gpr)saved_arg_count, offset, r15)));+ offset += (saveds - saved_arg_count) * SSIZE_OF(sw);+ }+ }+ }++ if (saved_arg_count > 0) {+ FAIL_IF(push_inst(compiler, stg(r14, offset, 0, r15)));+ offset += SSIZE_OF(sw);+ }++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ FAIL_IF(push_inst(compiler, 0x60000000 /* std */ | F20(i) | R12A(r15) | (sljit_ins)offset));+ offset += SSIZE_OF(sw);+ }++ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ FAIL_IF(push_inst(compiler, 0x60000000 /* std */ | F20(i) | R12A(r15) | (sljit_ins)offset));+ offset += SSIZE_OF(sw);+ }++ local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf;+ compiler->local_size = local_size;++ if (is_s20(-local_size))+ FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size)));+ else+ FAIL_IF(push_inst(compiler, 0xc20400000000 /* slgfi */ | R36A(r15) | (sljit_ins)local_size));++ if (options & SLJIT_ENTER_REG_ARG)+ return SLJIT_SUCCESS;++ arg_types >>= SLJIT_ARG_SHIFT;+ saved_arg_count = 0;+ tmp = 0;+ while (arg_types > 0) {+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {+ FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S0 - saved_arg_count), gpr(SLJIT_R0 + tmp))));+ saved_arg_count++;+ }+ tmp++;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ compiler->local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_gpr last_reg)+{+ sljit_s32 offset, i, tmp;+ sljit_s32 local_size = compiler->local_size;+ sljit_s32 saveds = compiler->saveds;+ sljit_s32 scratches = compiler->scratches;+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);++ if (is_u12(local_size))+ FAIL_IF(push_inst(compiler, 0x41000000 /* ly */ | R20A(r15) | R12A(r15) | (sljit_ins)local_size));+ else if (is_s20(local_size))+ FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(local_size)));+ else+ FAIL_IF(push_inst(compiler, 0xc20a00000000 /* algfi */ | R36A(r15) | (sljit_ins)local_size));++ offset = 2 * SSIZE_OF(sw);+ if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) {+ if (kept_saveds_count == 0) {+ FAIL_IF(push_inst(compiler, lmg(r6, last_reg, offset, r15)));+ offset += 9 * SSIZE_OF(sw);+ } else {+ FAIL_IF(push_inst(compiler, lmg(r6, r13 - (sljit_gpr)kept_saveds_count, offset, r15)));+ offset += (8 - kept_saveds_count) * SSIZE_OF(sw);+ }+ } else {+ if (scratches == SLJIT_FIRST_SAVED_REG) {+ FAIL_IF(push_inst(compiler, lg(r6, offset, 0, r15)));+ offset += SSIZE_OF(sw);+ } else if (scratches > SLJIT_FIRST_SAVED_REG) {+ FAIL_IF(push_inst(compiler, lmg(r6, r6 + (sljit_gpr)(scratches - SLJIT_FIRST_SAVED_REG), offset, r15)));+ offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw);+ }++ if (kept_saveds_count == 0) {+ if (saveds == 0) {+ if (last_reg == r14)+ FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15)));+ offset += SSIZE_OF(sw);+ } else if (saveds == 1 && last_reg == r13) {+ FAIL_IF(push_inst(compiler, lg(r13, offset, 0, r15)));+ offset += 2 * SSIZE_OF(sw);+ } else {+ FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, last_reg, offset, r15)));+ offset += (saveds + 1) * SSIZE_OF(sw);+ }+ } else if (saveds > kept_saveds_count) {+ if (saveds == kept_saveds_count + 1) {+ FAIL_IF(push_inst(compiler, lg(r14 - (sljit_gpr)saveds, offset, 0, r15)));+ offset += SSIZE_OF(sw);+ } else {+ FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, r13 - (sljit_gpr)kept_saveds_count, offset, r15)));+ offset += (saveds - kept_saveds_count) * SSIZE_OF(sw);+ }+ }+ }++ if (kept_saveds_count > 0) {+ if (last_reg == r14)+ FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15)));+ offset += SSIZE_OF(sw);+ }++ tmp = SLJIT_FS0 - compiler->fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ FAIL_IF(push_inst(compiler, 0x68000000 /* ld */ | F20(i) | R12A(r15) | (sljit_ins)offset));+ offset += SSIZE_OF(sw);+ }++ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {+ FAIL_IF(push_inst(compiler, 0x68000000 /* ld */ | F20(i) | R12A(r15) | (sljit_ins)offset));+ offset += SSIZE_OF(sw);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ FAIL_IF(emit_stack_frame_release(compiler, r14));+ return push_inst(compiler, br(r14)); /* return */+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */));+ src = TMP_REG2;+ srcw = 0;+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src))));+ src = TMP_REG2;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, r13));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+ sljit_gpr arg0 = gpr(SLJIT_R0);+ sljit_gpr arg1 = gpr(SLJIT_R1);++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op) | (op & SLJIT_32);+ switch (op) {+ case SLJIT_BREAKPOINT:+ /* The following invalid instruction is emitted by gdb. */+ return push_inst(compiler, 0x0001 /* 2-byte trap */);+ case SLJIT_NOP:+ return push_inst(compiler, 0x0700 /* 2-byte nop */);+ case SLJIT_LMUL_UW:+ FAIL_IF(push_inst(compiler, mlgr(arg0, arg0)));+ break;+ case SLJIT_LMUL_SW:+ /* signed multiplication from: */+ /* Hacker's Delight, Second Edition: Chapter 8-3. */+ FAIL_IF(push_inst(compiler, srag(tmp0, arg0, 63, 0)));+ FAIL_IF(push_inst(compiler, srag(tmp1, arg1, 63, 0)));+ FAIL_IF(push_inst(compiler, ngr(tmp0, arg1)));+ FAIL_IF(push_inst(compiler, ngr(tmp1, arg0)));++ /* unsigned multiplication */+ FAIL_IF(push_inst(compiler, mlgr(arg0, arg0)));++ FAIL_IF(push_inst(compiler, sgr(arg0, tmp0)));+ FAIL_IF(push_inst(compiler, sgr(arg0, tmp1)));+ break;+ case SLJIT_DIV_U32:+ case SLJIT_DIVMOD_U32:+ FAIL_IF(push_inst(compiler, lhi(tmp0, 0)));+ FAIL_IF(push_inst(compiler, lr(tmp1, arg0)));+ FAIL_IF(push_inst(compiler, dlr(tmp0, arg1)));+ FAIL_IF(push_inst(compiler, lr(arg0, tmp1))); /* quotient */+ if (op == SLJIT_DIVMOD_U32)+ return push_inst(compiler, lr(arg1, tmp0)); /* remainder */++ return SLJIT_SUCCESS;+ case SLJIT_DIV_S32:+ case SLJIT_DIVMOD_S32:+ FAIL_IF(push_inst(compiler, lhi(tmp0, 0)));+ FAIL_IF(push_inst(compiler, lr(tmp1, arg0)));+ FAIL_IF(push_inst(compiler, dr(tmp0, arg1)));+ FAIL_IF(push_inst(compiler, lr(arg0, tmp1))); /* quotient */+ if (op == SLJIT_DIVMOD_S32)+ return push_inst(compiler, lr(arg1, tmp0)); /* remainder */++ return SLJIT_SUCCESS;+ case SLJIT_DIV_UW:+ case SLJIT_DIVMOD_UW:+ FAIL_IF(push_inst(compiler, lghi(tmp0, 0)));+ FAIL_IF(push_inst(compiler, lgr(tmp1, arg0)));+ FAIL_IF(push_inst(compiler, dlgr(tmp0, arg1)));+ FAIL_IF(push_inst(compiler, lgr(arg0, tmp1))); /* quotient */+ if (op == SLJIT_DIVMOD_UW)+ return push_inst(compiler, lgr(arg1, tmp0)); /* remainder */++ return SLJIT_SUCCESS;+ case SLJIT_DIV_SW:+ case SLJIT_DIVMOD_SW:+ FAIL_IF(push_inst(compiler, lgr(tmp1, arg0)));+ FAIL_IF(push_inst(compiler, dsgr(tmp0, arg1)));+ FAIL_IF(push_inst(compiler, lgr(arg0, tmp1))); /* quotient */+ if (op == SLJIT_DIVMOD_SW)+ return push_inst(compiler, lgr(arg1, tmp0)); /* remainder */++ return SLJIT_SUCCESS;+ case SLJIT_ENDBR:+ return SLJIT_SUCCESS;+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ default:+ SLJIT_UNREACHABLE();+ }+ /* swap result registers */+ FAIL_IF(push_inst(compiler, lgr(tmp0, arg0)));+ FAIL_IF(push_inst(compiler, lgr(arg0, arg1)));+ return push_inst(compiler, lgr(arg1, tmp0));+}++static sljit_s32 sljit_emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_gpr dst_r, sljit_gpr src_r)+{+ sljit_s32 is_ctz = (GET_OPCODE(op) == SLJIT_CTZ);++ if ((op & SLJIT_32) && src_r != tmp0) {+ FAIL_IF(push_inst(compiler, 0xb9160000 /* llgfr */ | R4A(tmp0) | R0A(src_r)));+ src_r = tmp0;+ }++ if (is_ctz) {+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */) | R4A(tmp1) | R0A(src_r)));++ if (src_r == tmp0)+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? 0x1400 /* nr */ : 0xb9800000 /* ngr */) | R4A(tmp0) | R0A(tmp1)));+ else+ FAIL_IF(push_inst(compiler, 0xb9e40000 /* ngrk */ | R12A(tmp1) | R4A(tmp0) | R0A(src_r)));++ src_r = tmp0;+ }++ FAIL_IF(push_inst(compiler, 0xb9830000 /* flogr */ | R4A(tmp0) | R0A(src_r)));++ if (is_ctz)+ FAIL_IF(push_inst(compiler, 0xec00000000d9 /* aghik */ | R36A(tmp1) | R32A(tmp0) | ((sljit_ins)(-64 & 0xffff) << 16)));++ if (op & SLJIT_32) {+ if (!is_ctz && dst_r != tmp0)+ return push_inst(compiler, 0xec00000000d9 /* aghik */ | R36A(dst_r) | R32A(tmp0) | ((sljit_ins)(-32 & 0xffff) << 16));++ FAIL_IF(push_inst(compiler, 0xc20800000000 /* agfi */ | R36A(tmp0) | (sljit_u32)-32));+ }++ if (is_ctz)+ FAIL_IF(push_inst(compiler, 0xec0000000057 /* rxsbg */ | R36A(tmp0) | R32A(tmp1) | ((sljit_ins)((op & SLJIT_32) ? 59 : 58) << 24) | (63 << 16) | ((sljit_ins)((op & SLJIT_32) ? 5 : 6) << 8)));++ if (dst_r == tmp0)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ((op & SLJIT_32) ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(tmp0));+}++static sljit_s32 sljit_emit_rev(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ struct addr addr;+ sljit_gpr reg;+ sljit_ins ins;+ sljit_s32 opcode = GET_OPCODE(op);+ sljit_s32 is_16bit = (opcode == SLJIT_REV_U16 || opcode == SLJIT_REV_S16);++ if (dst & SLJIT_MEM) {+ if (src & SLJIT_MEM) {+ FAIL_IF(load_store_op(compiler, tmp0, src, srcw, op & SLJIT_32, is_16bit ? load_halfword_forms : load_forms));+ reg = tmp0;+ } else+ reg = gpr(src);++ FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1));++ if (is_16bit)+ ins = 0xe3000000003f /* strvh */;+ else+ ins = (op & SLJIT_32) ? 0xe3000000003e /* strv */ : 0xe3000000002f /* strvg */;++ return push_inst(compiler, ins | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));+ }++ reg = gpr(dst);++ if (src & SLJIT_MEM) {+ FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1));++ if (is_16bit)+ ins = 0xe3000000001f /* lrvh */;+ else+ ins = (op & SLJIT_32) ? 0xe3000000001e /* lrv */ : 0xe3000000000f /* lrvg */;++ FAIL_IF(push_inst(compiler, ins | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)));++ if (opcode == SLJIT_REV)+ return SLJIT_SUCCESS;++ if (is_16bit) {+ if (op & SLJIT_32)+ ins = (opcode == SLJIT_REV_U16) ? 0xb9950000 /* llhr */ : 0xb9270000 /* lhr */;+ else+ ins = (opcode == SLJIT_REV_U16) ? 0xb9850000 /* llghr */ : 0xb9070000 /* lghr */;+ } else+ ins = (opcode == SLJIT_REV_U32) ? 0xb9160000 /* llgfr */ : 0xb9140000 /* lgfr */;++ return push_inst(compiler, ins | R4A(reg) | R0A(reg));+ }++ ins = (op & SLJIT_32) ? 0xb91f0000 /* lrvr */ : 0xb90f0000 /* lrvgr */;+ FAIL_IF(push_inst(compiler, ins | R4A(reg) | R0A(gpr(src))));++ if (opcode == SLJIT_REV)+ return SLJIT_SUCCESS;++ if (!is_16bit) {+ ins = (opcode == SLJIT_REV_U32) ? 0xb9160000 /* llgfr */ : 0xb9140000 /* lgfr */;+ return push_inst(compiler, ins | R4A(reg) | R0A(reg));+ }++ if (op & SLJIT_32) {+ ins = (opcode == SLJIT_REV_U16) ? 0x88000000 /* srl */ : 0x8a000000 /* sra */;+ return push_inst(compiler, ins | R20A(reg) | 16);+ }++ ins = (opcode == SLJIT_REV_U16) ? 0xeb000000000c /* srlg */ : 0xeb000000000a /* srag */;+ return push_inst(compiler, ins | R36A(reg) | R32A(reg) | (48 << 16));+}++/* LEVAL will be defined later with different parameters as needed */+#define WHEN2(cond, i1, i2) (cond) ? LEVAL(i1) : LEVAL(i2)++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_ins ins;+ struct addr mem;+ sljit_gpr dst_r;+ sljit_gpr src_r;+ sljit_s32 opcode = GET_OPCODE(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 (opcode >= SLJIT_MOV && opcode <= SLJIT_MOV_P) {+ /* LOAD REGISTER */+ if (FAST_IS_REG(dst) && FAST_IS_REG(src)) {+ dst_r = gpr(dst);+ src_r = gpr(src);+ switch (opcode | (op & SLJIT_32)) {+ /* 32-bit */+ case SLJIT_MOV32_U8:+ ins = llcr(dst_r, src_r);+ break;+ case SLJIT_MOV32_S8:+ ins = lbr(dst_r, src_r);+ break;+ case SLJIT_MOV32_U16:+ ins = llhr(dst_r, src_r);+ break;+ case SLJIT_MOV32_S16:+ ins = lhr(dst_r, src_r);+ break;+ case SLJIT_MOV32:+ if (dst_r == src_r)+ return SLJIT_SUCCESS;+ ins = lr(dst_r, src_r);+ break;+ /* 64-bit */+ case SLJIT_MOV_U8:+ ins = llgcr(dst_r, src_r);+ break;+ case SLJIT_MOV_S8:+ ins = lgbr(dst_r, src_r);+ break;+ case SLJIT_MOV_U16:+ ins = llghr(dst_r, src_r);+ break;+ case SLJIT_MOV_S16:+ ins = lghr(dst_r, src_r);+ break;+ case SLJIT_MOV_U32:+ ins = llgfr(dst_r, src_r);+ break;+ case SLJIT_MOV_S32:+ ins = lgfr(dst_r, src_r);+ break;+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ if (dst_r == src_r)+ return SLJIT_SUCCESS;+ ins = lgr(dst_r, src_r);+ break;+ default:+ ins = 0;+ SLJIT_UNREACHABLE();+ break;+ }+ FAIL_IF(push_inst(compiler, ins));+ return SLJIT_SUCCESS;+ }+ /* LOAD IMMEDIATE */+ if (FAST_IS_REG(dst) && src == SLJIT_IMM) {+ switch (opcode) {+ case SLJIT_MOV_U8:+ srcw = (sljit_sw)((sljit_u8)(srcw));+ break;+ case SLJIT_MOV_S8:+ srcw = (sljit_sw)((sljit_s8)(srcw));+ break;+ case SLJIT_MOV_U16:+ srcw = (sljit_sw)((sljit_u16)(srcw));+ break;+ case SLJIT_MOV_S16:+ srcw = (sljit_sw)((sljit_s16)(srcw));+ break;+ case SLJIT_MOV_U32:+ srcw = (sljit_sw)((sljit_u32)(srcw));+ break;+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ srcw = (sljit_sw)((sljit_s32)(srcw));+ break;+ }+ return push_load_imm_inst(compiler, gpr(dst), srcw);+ }+ /* LOAD */+ /* TODO(carenas): avoid reg being defined later */+ #define LEVAL(i) EVAL(i, reg, mem)+ if (FAST_IS_REG(dst) && (src & SLJIT_MEM)) {+ sljit_gpr reg = gpr(dst);++ FAIL_IF(make_addr_bxy(compiler, &mem, src, srcw, tmp1));+ /* TODO(carenas): convert all calls below to LEVAL */+ switch (opcode | (op & SLJIT_32)) {+ case SLJIT_MOV32_U8:+ ins = llc(reg, mem.offset, mem.index, mem.base);+ break;+ case SLJIT_MOV32_S8:+ ins = lb(reg, mem.offset, mem.index, mem.base);+ break;+ case SLJIT_MOV32_U16:+ ins = llh(reg, mem.offset, mem.index, mem.base);+ break;+ case SLJIT_MOV32_S16:+ ins = WHEN2(is_u12(mem.offset), lh, lhy);+ break;+ case SLJIT_MOV32:+ ins = WHEN2(is_u12(mem.offset), l, ly);+ break;+ case SLJIT_MOV_U8:+ ins = LEVAL(llgc);+ break;+ case SLJIT_MOV_S8:+ ins = lgb(reg, mem.offset, mem.index, mem.base);+ break;+ case SLJIT_MOV_U16:+ ins = LEVAL(llgh);+ break;+ case SLJIT_MOV_S16:+ ins = lgh(reg, mem.offset, mem.index, mem.base);+ break;+ case SLJIT_MOV_U32:+ ins = LEVAL(llgf);+ break;+ case SLJIT_MOV_S32:+ ins = lgf(reg, mem.offset, mem.index, mem.base);+ break;+ case SLJIT_MOV_P:+ case SLJIT_MOV:+ ins = lg(reg, mem.offset, mem.index, mem.base);+ break;+ default:+ ins = 0;+ SLJIT_UNREACHABLE();+ break;+ }+ FAIL_IF(push_inst(compiler, ins));+ return SLJIT_SUCCESS;+ }+ /* STORE and STORE IMMEDIATE */+ if ((dst & SLJIT_MEM) && (FAST_IS_REG(src) || src == SLJIT_IMM)) {+ struct addr mem;+ sljit_gpr reg = FAST_IS_REG(src) ? gpr(src) : tmp0;++ if (src == SLJIT_IMM) {+ /* TODO(mundaym): MOVE IMMEDIATE? */+ FAIL_IF(push_load_imm_inst(compiler, reg, srcw));+ }+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));+ switch (opcode) {+ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ return push_inst(compiler,+ WHEN2(is_u12(mem.offset), stc, stcy));+ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ return push_inst(compiler,+ WHEN2(is_u12(mem.offset), sth, sthy));+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ return push_inst(compiler,+ WHEN2(is_u12(mem.offset), st, sty));+ case SLJIT_MOV_P:+ case SLJIT_MOV:+ FAIL_IF(push_inst(compiler, LEVAL(stg)));+ return SLJIT_SUCCESS;+ default:+ SLJIT_UNREACHABLE();+ }+ }+ #undef LEVAL+ /* MOVE CHARACTERS */+ if ((dst & SLJIT_MEM) && (src & SLJIT_MEM)) {+ struct addr mem;+ FAIL_IF(make_addr_bxy(compiler, &mem, src, srcw, tmp1));+ switch (opcode) {+ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ FAIL_IF(push_inst(compiler,+ EVAL(llgc, tmp0, mem)));+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));+ return push_inst(compiler,+ EVAL(stcy, tmp0, mem));+ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ FAIL_IF(push_inst(compiler,+ EVAL(llgh, tmp0, mem)));+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));+ return push_inst(compiler,+ EVAL(sthy, tmp0, mem));+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ FAIL_IF(push_inst(compiler,+ EVAL(ly, tmp0, mem)));+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));+ return push_inst(compiler,+ EVAL(sty, tmp0, mem));+ case SLJIT_MOV_P:+ case SLJIT_MOV:+ FAIL_IF(push_inst(compiler,+ EVAL(lg, tmp0, mem)));+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));+ FAIL_IF(push_inst(compiler,+ EVAL(stg, tmp0, mem)));+ return SLJIT_SUCCESS;+ default:+ SLJIT_UNREACHABLE();+ }+ }+ SLJIT_UNREACHABLE();+ }++ SLJIT_ASSERT(src != SLJIT_IMM);++ dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;+ src_r = FAST_IS_REG(src) ? gpr(src) : tmp0;++ compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z);++ /* TODO(mundaym): optimize loads and stores */+ switch (opcode) {+ case SLJIT_CLZ:+ case SLJIT_CTZ:+ if (src & SLJIT_MEM)+ FAIL_IF(load_unsigned_word(compiler, src_r, src, srcw, op & SLJIT_32));++ FAIL_IF(sljit_emit_clz_ctz(compiler, op, dst_r, src_r));+ break;+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+ op |= SLJIT_32;+ /* fallthrough */+ case SLJIT_REV:+ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ return sljit_emit_rev(compiler, op, dst, dstw, src, srcw);+ default:+ SLJIT_UNREACHABLE();+ }++ if (dst & SLJIT_MEM)+ return store_word(compiler, dst_r, dst, dstw, op & SLJIT_32);++ return SLJIT_SUCCESS;+}++static SLJIT_INLINE int is_commutative(sljit_s32 op)+{+ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ case SLJIT_ADDC:+ case SLJIT_MUL:+ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ return 1;+ }+ return 0;+}++static const struct ins_forms add_forms = {+ 0x1a00, /* ar */+ 0xb9080000, /* agr */+ 0xb9f80000, /* ark */+ 0xb9e80000, /* agrk */+ 0x5a000000, /* a */+ 0xe3000000005a, /* ay */+ 0xe30000000008, /* ag */+};++static const struct ins_forms logical_add_forms = {+ 0x1e00, /* alr */+ 0xb90a0000, /* algr */+ 0xb9fa0000, /* alrk */+ 0xb9ea0000, /* algrk */+ 0x5e000000, /* al */+ 0xe3000000005e, /* aly */+ 0xe3000000000a, /* alg */+};++static sljit_s32 sljit_emit_add(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)+{+ int sets_overflow = (op & VARIABLE_FLAG_MASK) == SLJIT_SET_OVERFLOW;+ int sets_zero_overflow = (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW);+ const struct ins_forms *forms;+ sljit_ins ins;++ if (src2 == SLJIT_IMM) {+ if (!sets_zero_overflow && is_s8(src2w) && (src1 & SLJIT_MEM) && (dst == src1 && dstw == src1w)) {+ if (sets_overflow)+ ins = (op & SLJIT_32) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;+ else+ ins = (op & SLJIT_32) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;+ return emit_siy(compiler, ins, dst, dstw, src2w);+ }++ if (is_s16(src2w)) {+ if (sets_overflow)+ ins = (op & SLJIT_32) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;+ else+ ins = (op & SLJIT_32) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;+ FAIL_IF(emit_rie_d(compiler, ins, dst, src1, src1w, src2w));+ goto done;+ }++ if (!sets_overflow) {+ if ((op & SLJIT_32) || is_u32(src2w)) {+ ins = (op & SLJIT_32) ? 0xc20b00000000 /* alfi */ : 0xc20a00000000 /* algfi */;+ FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));+ goto done;+ }+ if (is_u32(-src2w)) {+ FAIL_IF(emit_ri(compiler, 0xc20400000000 /* slgfi */, dst, src1, src1w, -src2w, RIL_A));+ goto done;+ }+ }+ else if ((op & SLJIT_32) || is_s32(src2w)) {+ ins = (op & SLJIT_32) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;+ FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));+ goto done;+ }+ }++ forms = sets_overflow ? &add_forms : &logical_add_forms;+ FAIL_IF(emit_commutative(compiler, forms, dst, src1, src1w, src2, src2w));++done:+ if (sets_zero_overflow)+ FAIL_IF(update_zero_overflow(compiler, op, FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0));++ if (dst & SLJIT_MEM)+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);++ return SLJIT_SUCCESS;+}++static const struct ins_forms sub_forms = {+ 0x1b00, /* sr */+ 0xb9090000, /* sgr */+ 0xb9f90000, /* srk */+ 0xb9e90000, /* sgrk */+ 0x5b000000, /* s */+ 0xe3000000005b, /* sy */+ 0xe30000000009, /* sg */+};++static const struct ins_forms logical_sub_forms = {+ 0x1f00, /* slr */+ 0xb90b0000, /* slgr */+ 0xb9fb0000, /* slrk */+ 0xb9eb0000, /* slgrk */+ 0x5f000000, /* sl */+ 0xe3000000005f, /* sly */+ 0xe3000000000b, /* slg */+};++static sljit_s32 sljit_emit_sub(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_s32 flag_type = GET_FLAG_TYPE(op);+ int sets_signed = (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_NOT_OVERFLOW);+ int sets_zero_overflow = (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW);+ const struct ins_forms *forms;+ sljit_ins ins;++ if (dst == TMP_REG2 && flag_type <= SLJIT_SIG_LESS_EQUAL) {+ int compare_signed = flag_type >= SLJIT_SIG_LESS;++ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_COMPARE;++ if (src2 == SLJIT_IMM) {+ if (compare_signed || ((op & VARIABLE_FLAG_MASK) == 0 && is_s32(src2w))) {+ if ((op & SLJIT_32) || is_s32(src2w)) {+ ins = (op & SLJIT_32) ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */;+ return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A);+ }+ }+ else {+ if ((op & SLJIT_32) || is_u32(src2w)) {+ ins = (op & SLJIT_32) ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */;+ return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A);+ }+ if (is_s16(src2w))+ return emit_rie_d(compiler, 0xec00000000db /* alghsik */, (sljit_s32)tmp0, src1, src1w, src2w);+ }+ }+ else if (src2 & SLJIT_MEM) {+ if ((op & SLJIT_32) && ((src2 & OFFS_REG_MASK) || is_u12(src2w))) {+ ins = compare_signed ? 0x59000000 /* c */ : 0x55000000 /* cl */;+ return emit_rx(compiler, ins, src1, src1, src1w, src2, src2w, RX_A);+ }++ if (compare_signed)+ ins = (op & SLJIT_32) ? 0xe30000000059 /* cy */ : 0xe30000000020 /* cg */;+ else+ ins = (op & SLJIT_32) ? 0xe30000000055 /* cly */ : 0xe30000000021 /* clg */;+ return emit_rx(compiler, ins, src1, src1, src1w, src2, src2w, RXY_A);+ }++ if (compare_signed)+ ins = (op & SLJIT_32) ? 0x1900 /* cr */ : 0xb9200000 /* cgr */;+ else+ ins = (op & SLJIT_32) ? 0x1500 /* clr */ : 0xb9210000 /* clgr */;+ return emit_rr(compiler, ins, src1, src1, src1w, src2, src2w);+ }++ if (src1 == SLJIT_IMM && src1w == 0 && (flag_type == 0 || sets_signed)) {+ ins = (op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */;+ FAIL_IF(emit_rr1(compiler, ins, dst, src2, src2w));+ goto done;+ }++ if (src2 == SLJIT_IMM) {+ sljit_sw neg_src2w = -src2w;++ if (sets_signed || neg_src2w != 0 || (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == 0) {+ if (!sets_zero_overflow && is_s8(neg_src2w) && (src1 & SLJIT_MEM) && (dst == src1 && dstw == src1w)) {+ if (sets_signed)+ ins = (op & SLJIT_32) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;+ else+ ins = (op & SLJIT_32) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;+ return emit_siy(compiler, ins, dst, dstw, neg_src2w);+ }++ if (is_s16(neg_src2w)) {+ if (sets_signed)+ ins = (op & SLJIT_32) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;+ else+ ins = (op & SLJIT_32) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;+ FAIL_IF(emit_rie_d(compiler, ins, dst, src1, src1w, neg_src2w));+ goto done;+ }+ }++ if (!sets_signed) {+ if ((op & SLJIT_32) || is_u32(src2w)) {+ ins = (op & SLJIT_32) ? 0xc20500000000 /* slfi */ : 0xc20400000000 /* slgfi */;+ FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));+ goto done;+ }+ if (is_u32(neg_src2w)) {+ FAIL_IF(emit_ri(compiler, 0xc20a00000000 /* algfi */, dst, src1, src1w, neg_src2w, RIL_A));+ goto done;+ }+ }+ else if ((op & SLJIT_32) || is_s32(neg_src2w)) {+ ins = (op & SLJIT_32) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;+ FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, neg_src2w, RIL_A));+ goto done;+ }+ }++ forms = sets_signed ? &sub_forms : &logical_sub_forms;+ FAIL_IF(emit_non_commutative(compiler, forms, dst, src1, src1w, src2, src2w));++done:+ if (sets_signed) {+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;++ if ((op & VARIABLE_FLAG_MASK) != SLJIT_SET_OVERFLOW) {+ /* In case of overflow, the sign bit of the two source operands must be different, and+ - the first operand is greater if the sign bit of the result is set+ - the first operand is less if the sign bit of the result is not set+ The -result operation sets the corrent sign, because the result cannot be zero.+ The overflow is considered greater, since the result must be equal to INT_MIN so its sign bit is set. */+ FAIL_IF(push_inst(compiler, brc(0xe, (op & SLJIT_32) ? (2 + 1) : (2 + 2))));+ FAIL_IF(push_inst(compiler, (op & SLJIT_32) ? lcr(tmp1, dst_r) : lcgr(tmp1, dst_r)));+ }+ else if (op & SLJIT_SET_Z)+ FAIL_IF(update_zero_overflow(compiler, op, dst_r));+ }++ if (dst & SLJIT_MEM)+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);++ return SLJIT_SUCCESS;+}++static const struct ins_forms multiply_forms = {+ 0xb2520000, /* msr */+ 0xb90c0000, /* msgr */+ 0xb9fd0000, /* msrkc */+ 0xb9ed0000, /* msgrkc */+ 0x71000000, /* ms */+ 0xe30000000051, /* msy */+ 0xe3000000000c, /* msg */+};++static const struct ins_forms multiply_overflow_forms = {+ 0,+ 0,+ 0xb9fd0000, /* msrkc */+ 0xb9ed0000, /* msgrkc */+ 0,+ 0xe30000000053, /* msc */+ 0xe30000000083, /* msgc */+};++static sljit_s32 sljit_emit_multiply(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_ins ins;++ if (HAS_FLAGS(op)) {+ /* if have_misc2 fails, this operation should be emulated. 32 bit emulation:+ FAIL_IF(push_inst(compiler, lgfr(tmp0, src1_r)));+ FAIL_IF(push_inst(compiler, msgfr(tmp0, src2_r)));+ if (dst_r != tmp0) {+ FAIL_IF(push_inst(compiler, lr(dst_r, tmp0)));+ }+ FAIL_IF(push_inst(compiler, aih(tmp0, 1)));+ FAIL_IF(push_inst(compiler, nihf(tmp0, ~1U)));+ FAIL_IF(push_inst(compiler, ipm(tmp1)));+ FAIL_IF(push_inst(compiler, oilh(tmp1, 0x2000))); */++ return emit_commutative(compiler, &multiply_overflow_forms, dst, src1, src1w, src2, src2w);+ }++ if (src2 == SLJIT_IMM) {+ if (is_s16(src2w)) {+ ins = (op & SLJIT_32) ? 0xa70c0000 /* mhi */ : 0xa70d0000 /* mghi */;+ return emit_ri(compiler, ins, dst, src1, src1w, src2w, RI_A);+ }++ if (is_s32(src2w)) {+ ins = (op & SLJIT_32) ? 0xc20100000000 /* msfi */ : 0xc20000000000 /* msgfi */;+ return emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A);+ }+ }++ return emit_commutative(compiler, &multiply_forms, dst, src1, src1w, src2, src2w);+}++static sljit_s32 sljit_emit_bitwise_imm(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_uw imm, sljit_s32 count16)+{+ sljit_s32 mode = compiler->mode;+ sljit_gpr dst_r = tmp0;+ sljit_s32 needs_move = 1;++ if (IS_GPR_REG(dst)) {+ dst_r = gpr(dst & REG_MASK);+ if (dst == src1)+ needs_move = 0;+ }++ if (needs_move)+ FAIL_IF(emit_move(compiler, dst_r, src1, src1w));++ if (type == SLJIT_AND) {+ if (!(mode & SLJIT_32))+ FAIL_IF(push_inst(compiler, 0xc00a00000000 /* nihf */ | R36A(dst_r) | (imm >> 32)));+ return push_inst(compiler, 0xc00b00000000 /* nilf */ | R36A(dst_r) | (imm & 0xffffffff));+ }+ else if (type == SLJIT_OR) {+ if (count16 >= 3) {+ FAIL_IF(push_inst(compiler, 0xc00c00000000 /* oihf */ | R36A(dst_r) | (imm >> 32)));+ return push_inst(compiler, 0xc00d00000000 /* oilf */ | R36A(dst_r) | (imm & 0xffffffff));+ }++ if (count16 >= 2) {+ if ((imm & 0x00000000ffffffffull) == 0)+ return push_inst(compiler, 0xc00c00000000 /* oihf */ | R36A(dst_r) | (imm >> 32));+ if ((imm & 0xffffffff00000000ull) == 0)+ return push_inst(compiler, 0xc00d00000000 /* oilf */ | R36A(dst_r) | (imm & 0xffffffff));+ }++ if ((imm & 0xffff000000000000ull) != 0)+ FAIL_IF(push_inst(compiler, 0xa5080000 /* oihh */ | R20A(dst_r) | (imm >> 48)));+ if ((imm & 0x0000ffff00000000ull) != 0)+ FAIL_IF(push_inst(compiler, 0xa5090000 /* oihl */ | R20A(dst_r) | ((imm >> 32) & 0xffff)));+ if ((imm & 0x00000000ffff0000ull) != 0)+ FAIL_IF(push_inst(compiler, 0xa50a0000 /* oilh */ | R20A(dst_r) | ((imm >> 16) & 0xffff)));+ if ((imm & 0x000000000000ffffull) != 0 || imm == 0)+ return push_inst(compiler, 0xa50b0000 /* oill */ | R20A(dst_r) | (imm & 0xffff));+ return SLJIT_SUCCESS;+ }++ if ((imm & 0xffffffff00000000ull) != 0)+ FAIL_IF(push_inst(compiler, 0xc00600000000 /* xihf */ | R36A(dst_r) | (imm >> 32)));+ if ((imm & 0x00000000ffffffffull) != 0 || imm == 0)+ return push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(dst_r) | (imm & 0xffffffff));+ return SLJIT_SUCCESS;+}++static const struct ins_forms bitwise_and_forms = {+ 0x1400, /* nr */+ 0xb9800000, /* ngr */+ 0xb9f40000, /* nrk */+ 0xb9e40000, /* ngrk */+ 0x54000000, /* n */+ 0xe30000000054, /* ny */+ 0xe30000000080, /* ng */+};++static const struct ins_forms bitwise_or_forms = {+ 0x1600, /* or */+ 0xb9810000, /* ogr */+ 0xb9f60000, /* ork */+ 0xb9e60000, /* ogrk */+ 0x56000000, /* o */+ 0xe30000000056, /* oy */+ 0xe30000000081, /* og */+};++static const struct ins_forms bitwise_xor_forms = {+ 0x1700, /* xr */+ 0xb9820000, /* xgr */+ 0xb9f70000, /* xrk */+ 0xb9e70000, /* xgrk */+ 0x57000000, /* x */+ 0xe30000000057, /* xy */+ 0xe30000000082, /* xg */+};++static sljit_s32 sljit_emit_bitwise(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 type = GET_OPCODE(op);+ const struct ins_forms *forms;++ if (src2 == SLJIT_IMM && (!(op & SLJIT_SET_Z) || (type == SLJIT_AND && dst == TMP_REG2))) {+ sljit_s32 count16 = 0;+ sljit_uw imm = (sljit_uw)src2w;++ if (op & SLJIT_32)+ imm &= 0xffffffffull;++ if ((imm & 0x000000000000ffffull) != 0 || imm == 0)+ count16++;+ if ((imm & 0x00000000ffff0000ull) != 0)+ count16++;+ if ((imm & 0x0000ffff00000000ull) != 0)+ count16++;+ if ((imm & 0xffff000000000000ull) != 0)+ count16++;++ if (type == SLJIT_AND && dst == TMP_REG2 && count16 == 1) {+ sljit_gpr src_r = tmp1;++ if (FAST_IS_REG(src1))+ src_r = gpr(src1 & REG_MASK);+ else+ FAIL_IF(emit_move(compiler, tmp1, src1, src1w));++ if ((imm & 0x000000000000ffffull) != 0 || imm == 0)+ return push_inst(compiler, 0xa7010000 /* tmll */ | R20A(src_r) | imm);+ if ((imm & 0x00000000ffff0000ull) != 0)+ return push_inst(compiler, 0xa7000000 /* tmlh */ | R20A(src_r) | (imm >> 16));+ if ((imm & 0x0000ffff00000000ull) != 0)+ return push_inst(compiler, 0xa7030000 /* tmhl */ | R20A(src_r) | (imm >> 32));+ return push_inst(compiler, 0xa7020000 /* tmhh */ | R20A(src_r) | (imm >> 48));+ }++ if (!(op & SLJIT_SET_Z))+ return sljit_emit_bitwise_imm(compiler, type, dst, src1, src1w, imm, count16);+ }++ if (type == SLJIT_AND)+ forms = &bitwise_and_forms;+ else if (type == SLJIT_OR)+ forms = &bitwise_or_forms;+ else+ forms = &bitwise_xor_forms;++ return emit_commutative(compiler, forms, dst, src1, src1w, src2, src2w);+}++static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 type = GET_OPCODE(op);+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;+ sljit_gpr src_r = tmp0;+ sljit_gpr base_r = tmp0;+ sljit_ins imm = 0;+ sljit_ins ins;++ if (FAST_IS_REG(src1))+ src_r = gpr(src1);+ else+ FAIL_IF(emit_move(compiler, tmp0, src1, src1w));++ if (src2 != SLJIT_IMM) {+ if (FAST_IS_REG(src2))+ base_r = gpr(src2);+ else {+ FAIL_IF(emit_move(compiler, tmp1, src2, src2w));+ base_r = tmp1;+ }++ if ((op & SLJIT_32) && (type == SLJIT_MSHL || type == SLJIT_MLSHR || type == SLJIT_MASHR)) {+ if (base_r != tmp1) {+ FAIL_IF(push_inst(compiler, 0xec0000000055 /* risbg */ | R36A(tmp1) | R32A(base_r) | (59 << 24) | (1 << 23) | (63 << 16)));+ base_r = tmp1;+ } else+ FAIL_IF(push_inst(compiler, 0xa5070000 /* nill */ | R20A(tmp1) | 0x1f));+ }+ } else+ imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f));++ if ((op & SLJIT_32) && dst_r == src_r) {+ if (type == SLJIT_SHL || type == SLJIT_MSHL)+ ins = 0x89000000 /* sll */;+ else if (type == SLJIT_LSHR || type == SLJIT_MLSHR)+ ins = 0x88000000 /* srl */;+ else+ ins = 0x8a000000 /* sra */;++ FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | R12A(base_r) | imm));+ } else {+ if (type == SLJIT_SHL || type == SLJIT_MSHL)+ ins = (op & SLJIT_32) ? 0xeb00000000df /* sllk */ : 0xeb000000000d /* sllg */;+ else if (type == SLJIT_LSHR || type == SLJIT_MLSHR)+ ins = (op & SLJIT_32) ? 0xeb00000000de /* srlk */ : 0xeb000000000c /* srlg */;+ else+ ins = (op & SLJIT_32) ? 0xeb00000000dc /* srak */ : 0xeb000000000a /* srag */;++ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | R28A(base_r) | (imm << 16)));+ }++ if ((op & SLJIT_SET_Z) && type != SLJIT_ASHR)+ return push_inst(compiler, (op & SLJIT_32) ? or(dst_r, dst_r) : ogr(dst_r, dst_r));++ return SLJIT_SUCCESS;+}++static sljit_s32 sljit_emit_rotate(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;+ sljit_gpr src_r = tmp0;+ sljit_gpr base_r = tmp0;+ sljit_ins imm = 0;+ sljit_ins ins;++ if (FAST_IS_REG(src1))+ src_r = gpr(src1);+ else+ FAIL_IF(emit_move(compiler, tmp0, src1, src1w));++ if (src2 != SLJIT_IMM) {+ if (FAST_IS_REG(src2))+ base_r = gpr(src2);+ else {+ FAIL_IF(emit_move(compiler, tmp1, src2, src2w));+ base_r = tmp1;+ }+ }++ if (GET_OPCODE(op) == SLJIT_ROTR) {+ if (src2 != SLJIT_IMM) {+ ins = (op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */;+ FAIL_IF(push_inst(compiler, ins | R4A(tmp1) | R0A(base_r)));+ base_r = tmp1;+ } else+ src2w = -src2w;+ }++ if (src2 == SLJIT_IMM)+ imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f));++ ins = (op & SLJIT_32) ? 0xeb000000001d /* rll */ : 0xeb000000001c /* rllg */;+ return push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | R28A(base_r) | (imm << 16));+}++static const struct ins_forms addc_forms = {+ 0xb9980000, /* alcr */+ 0xb9880000, /* alcgr */+ 0,+ 0,+ 0,+ 0xe30000000098, /* alc */+ 0xe30000000088, /* alcg */+};++static const struct ins_forms subc_forms = {+ 0xb9990000, /* slbr */+ 0xb9890000, /* slbgr */+ 0,+ 0,+ 0,+ 0xe30000000099, /* slb */+ 0xe30000000089, /* slbg */+};++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, 0, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->mode = op & SLJIT_32;+ compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z);++ if (is_commutative(op) && src1 == SLJIT_IMM && src2 != SLJIT_IMM) {+ src1 ^= src2;+ src2 ^= src1;+ src1 ^= src2;++ src1w ^= src2w;+ src2w ^= src1w;+ src1w ^= src2w;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD;+ return sljit_emit_add(compiler, op, dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_ADDC:+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD;+ FAIL_IF(emit_commutative(compiler, &addc_forms, dst, src1, src1w, src2, src2w));+ if (dst & SLJIT_MEM)+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);+ return SLJIT_SUCCESS;+ case SLJIT_SUB:+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_SUB;+ return sljit_emit_sub(compiler, op, dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_SUBC:+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_SUB;+ FAIL_IF(emit_non_commutative(compiler, &subc_forms, dst, src1, src1w, src2, src2w));+ if (dst & SLJIT_MEM)+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);+ return SLJIT_SUCCESS;+ case SLJIT_MUL:+ FAIL_IF(sljit_emit_multiply(compiler, op, dst, src1, src1w, src2, src2w));+ break;+ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ FAIL_IF(sljit_emit_bitwise(compiler, op, dst, src1, src1w, src2, src2w));+ break;+ case SLJIT_SHL:+ case SLJIT_MSHL:+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ FAIL_IF(sljit_emit_shift(compiler, op, dst, src1, src1w, src2, src2w));+ break;+ case SLJIT_ROTL:+ case SLJIT_ROTR:+ FAIL_IF(sljit_emit_rotate(compiler, op, dst, src1, src1w, src2, src2w));+ break;+ }++ if (dst & SLJIT_MEM)+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_reg = (GET_OPCODE(op) == SLJIT_SUB || GET_OPCODE(op) == SLJIT_AND) ? TMP_REG2 : TMP_REG1;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, dst_reg, 0, src1, src1w, src2, src2w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));++ switch (GET_OPCODE(op)) {+ case SLJIT_MULADD:+ SLJIT_SKIP_CHECKS(compiler);+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), 0 /* tmp0 */, 0, src1, src1w, src2, src2w));+ return push_inst(compiler, ((op & SLJIT_32) ? 0x1a00 /* ar */ : 0xb9080000 /* agr */) | R4A(gpr(dst_reg)) | R0A(tmp0));+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+ sljit_s32 is_right;+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;+ sljit_gpr dst_r = gpr(dst_reg);+ sljit_gpr src1_r = gpr(src1_reg);+ sljit_gpr src2_r = gpr(src2_reg);+ sljit_gpr src3_r = tmp1;+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));++ is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR);++ if (src1_reg == src2_reg) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);+ }++ ADJUST_LOCAL_OFFSET(src3, src3w);++ if (src3 == SLJIT_IMM) {+ src3w &= bit_length - 1;++ if (src3w == 0)+ return SLJIT_SUCCESS;++ if (op & SLJIT_32) {+ if (dst_r == src1_r) {+ ins = is_right ? 0x88000000 /* srl */ : 0x89000000 /* sll */;+ FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | (sljit_ins)src3w));+ } else {+ ins = is_right ? 0xeb00000000de /* srlk */ : 0xeb00000000df /* sllk */;+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | ((sljit_ins)src3w << 16)));+ }+ } else {+ ins = is_right ? 0xeb000000000c /* srlg */ : 0xeb000000000d /* sllg */;+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | ((sljit_ins)src3w << 16)));+ }++ ins = 0xec0000000055 /* risbg */;++ if (is_right) {+ src3w = bit_length - src3w;+ ins |= ((sljit_ins)(64 - bit_length) << 24) | ((sljit_ins)(63 - src3w) << 16) | ((sljit_ins)src3w << 8);+ } else+ ins |= ((sljit_ins)(64 - src3w) << 24) | ((sljit_ins)63 << 16) | ((sljit_ins)(src3w + 64 - bit_length) << 8);++ return push_inst(compiler, ins | R36A(dst_r) | R32A(src2_r));+ }++ if (!(src3 & SLJIT_MEM)) {+ src3_r = gpr(src3);++ if (dst_r == src3_r) {+ FAIL_IF(push_inst(compiler, 0x1800 /* lr */ | R4A(tmp1) | R0A(src3_r)));+ src3_r = tmp1;+ }+ } else+ FAIL_IF(load_word(compiler, tmp1, src3, src3w, op & SLJIT_32));++ if (op & SLJIT_32) {+ if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR) {+ if (src3_r != tmp1) {+ FAIL_IF(push_inst(compiler, 0xec0000000055 /* risbg */ | R36A(tmp1) | R32A(src3_r) | (59 << 24) | (1 << 23) | (63 << 16)));+ src3_r = tmp1;+ } else+ FAIL_IF(push_inst(compiler, 0xa5070000 /* nill */ | R20A(tmp1) | 0x1f));+ }++ if (dst_r == src1_r) {+ ins = is_right ? 0x88000000 /* srl */ : 0x89000000 /* sll */;+ FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | R12A(src3_r)));+ } else {+ ins = is_right ? 0xeb00000000de /* srlk */ : 0xeb00000000df /* sllk */;+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | R28A(src3_r)));+ }++ if (src3_r != tmp1) {+ FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | 0x1f));+ FAIL_IF(push_inst(compiler, 0x1700 /* xr */ | R4A(tmp1) | R0A(src3_r)));+ } else+ FAIL_IF(push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(tmp1) | 0x1f));++ ins = is_right ? 0xeb00000000df /* sllk */ : 0xeb00000000de /* srlk */;+ FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src2_r) | R28A(tmp1) | (0x1 << 16)));++ return push_inst(compiler, 0x1600 /* or */ | R4A(dst_r) | R0A(tmp0));+ }++ ins = is_right ? 0xeb000000000c /* srlg */ : 0xeb000000000d /* sllg */;+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | R28A(src3_r)));++ ins = is_right ? 0xeb000000000d /* sllg */ : 0xeb000000000c /* srlg */;++ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {+ if (src3_r != tmp1)+ FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | 0x3f));++ FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src2_r) | (0x1 << 16)));+ src2_r = tmp0;++ if (src3_r != tmp1)+ FAIL_IF(push_inst(compiler, 0xb9820000 /* xgr */ | R4A(tmp1) | R0A(src3_r)));+ else+ FAIL_IF(push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(tmp1) | 0x3f));+ } else+ FAIL_IF(push_inst(compiler, 0xb9030000 /* lcgr */ | R4A(tmp1) | R0A(src3_r)));++ FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src2_r) | R28A(tmp1)));+ return push_inst(compiler, 0xb9810000 /* ogr */ | R4A(dst_r) | R0A(tmp0));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_gpr src_r;+ struct addr addr;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ src_r = FAST_IS_REG(src) ? gpr(src) : tmp1;+ if (src & SLJIT_MEM)+ FAIL_IF(load_word(compiler, tmp1, src, srcw, 0));++ return push_inst(compiler, br(src_r));+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1));+ return push_inst(compiler, 0xe31000000036 /* pfd */ | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));+ default:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_gpr dst_r = link_r;+ sljit_s32 size;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ switch (op) {+ case SLJIT_FAST_ENTER:+ if (FAST_IS_REG(dst))+ return push_inst(compiler, lgr(gpr(dst), link_r));+ break;+ case SLJIT_GET_RETURN_ADDRESS:+ dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;++ size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 2);+ FAIL_IF(load_word(compiler, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, 0));+ break;+ }++ if (dst & SLJIT_MEM)+ return store_word(compiler, dst_r, dst, dstw, 0);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));++ if (type == SLJIT_GP_REGISTER)+ return (sljit_s32)gpr(reg);++ if (type != SLJIT_FLOAT_REGISTER)+ return -1;++ return (sljit_s32)freg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ memcpy((sljit_u8 *)&ins + sizeof(ins) - size, instruction, size);+ return push_inst(compiler, ins);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define FLOAT_LOAD 0+#define FLOAT_STORE 1++static sljit_s32 float_mem(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ struct addr addr;+ sljit_ins ins;++ SLJIT_ASSERT(mem & SLJIT_MEM);++ if ((mem & OFFS_REG_MASK) || is_u12(memw) || !is_s20(memw)) {+ FAIL_IF(make_addr_bx(compiler, &addr, mem, memw, tmp1));++ if (op & FLOAT_STORE)+ ins = (op & SLJIT_32) ? 0x70000000 /* ste */ : 0x60000000 /* std */;+ else+ ins = (op & SLJIT_32) ? 0x78000000 /* le */ : 0x68000000 /* ld */;++ return push_inst(compiler, ins | F20(reg) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset);+ }++ FAIL_IF(make_addr_bxy(compiler, &addr, mem, memw, tmp1));++ if (op & FLOAT_STORE)+ ins = (op & SLJIT_32) ? 0xed0000000066 /* stey */ : 0xed0000000067 /* stdy */;+ else+ ins = (op & SLJIT_32) ? 0xed0000000064 /* ley */ : 0xed0000000065 /* ldy */;++ return push_inst(compiler, ins | F36(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));+}++static sljit_s32 emit_float(struct sljit_compiler *compiler, sljit_ins ins_r, sljit_ins ins,+ sljit_s32 reg,+ sljit_s32 src, sljit_sw srcw)+{+ struct addr addr;++ if (!(src & SLJIT_MEM))+ return push_inst(compiler, ins_r | F4(reg) | F0(src));++ FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1));+ return push_inst(compiler, ins | F36(reg) | R32A(addr.index) | R28A(addr.base) | ((sljit_ins)addr.offset << 16));+}++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_ins dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;+ sljit_ins ins;++ if (src & SLJIT_MEM) {+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src, srcw));+ src = TMP_FREG1;+ }++ /* M3 is set to 5 */+ if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)+ ins = (op & SLJIT_32) ? 0xb3a85000 /* cgebr */ : 0xb3a95000 /* cgdbr */;+ else+ ins = (op & SLJIT_32) ? 0xb3985000 /* cfebr */ : 0xb3995000 /* cfdbr */;++ FAIL_IF(push_inst(compiler, ins | R4A(dst_r) | F0(src)));++ if (dst & SLJIT_MEM)+ return store_word(compiler, dst_r, dst, dstw, GET_OPCODE(op) >= SLJIT_CONV_S32_FROM_F64);++ return SLJIT_SUCCESS;+}++static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src == SLJIT_IMM) {+ FAIL_IF(push_load_imm_inst(compiler, tmp0, srcw));+ src = (sljit_s32)tmp0;+ }+ else if (src & SLJIT_MEM) {+ FAIL_IF(load_word(compiler, tmp0, src, srcw, ins & 0x100000));+ src = (sljit_s32)tmp0;+ }++ FAIL_IF(push_inst(compiler, ins | F4(dst_r) | R0(src)));++ if (dst & SLJIT_MEM)+ return float_mem(compiler, FLOAT_STORE | ((ins & 0x10000) ? 0 : SLJIT_32), TMP_FREG1, dst, dstw);++ return SLJIT_SUCCESS;+}++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_ins ins;++ if (src == SLJIT_IMM && GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)+ srcw = (sljit_s32)srcw;++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)+ ins = (op & SLJIT_32) ? 0xb3a40000 /* cegbr */ : 0xb3a50000 /* cdgbr */;+ else+ ins = (op & SLJIT_32) ? 0xb3940000 /* cefbr */ : 0xb3950000 /* cdfbr */;++ return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_ins ins;++ if (src == SLJIT_IMM && GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)+ srcw = (sljit_u32)srcw;++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW)+ ins = (op & SLJIT_32) ? 0xb3a00000 /* celgbr */ : 0xb3a10000 /* cdlgbr */;+ else+ ins = (op & SLJIT_32) ? 0xb3900000 /* celfbr */ : 0xb3910000 /* cdlfbr */;++ return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);+}++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 ins_r, ins;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src1, src1w));+ src1 = TMP_FREG1;+ }++ if (op & SLJIT_32) {+ ins_r = 0xb3090000 /* cebr */;+ ins = 0xed0000000009 /* ceb */;+ } else {+ ins_r = 0xb3190000 /* cdbr */;+ ins = 0xed0000000019 /* cdb */;+ }++ return emit_float(compiler, ins_r, ins, src1, src2, src2w);+}++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_s32 dst_r;+ sljit_ins ins;++ CHECK_ERROR();++ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (op == SLJIT_CONV_F64_FROM_F32)+ FAIL_IF(emit_float(compiler, 0xb3040000 /* ldebr */, 0xed0000000004 /* ldeb */, dst_r, src, srcw));+ else {+ if (src & SLJIT_MEM) {+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op == SLJIT_CONV_F32_FROM_F64 ? 0 : (op & SLJIT_32)), dst_r, src, srcw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (FAST_IS_REG(dst)) {+ if (dst == src)+ return SLJIT_SUCCESS;++ ins = (op & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */;+ break;+ }+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), src, dst, dstw);+ case SLJIT_CONV_F64_FROM_F32:+ /* Only SLJIT_CONV_F32_FROM_F64. */+ ins = 0xb3440000 /* ledbr */;+ break;+ case SLJIT_NEG_F64:+ ins = (op & SLJIT_32) ? 0xb3030000 /* lcebr */ : 0xb3130000 /* lcdbr */;+ break;+ default:+ SLJIT_ASSERT(GET_OPCODE(op) == SLJIT_ABS_F64);+ ins = (op & SLJIT_32) ? 0xb3000000 /* lpebr */ : 0xb3100000 /* lpdbr */;+ break;+ }++ FAIL_IF(push_inst(compiler, ins | F4(dst_r) | F0(src)));+ }++ if (dst & SLJIT_MEM)+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);++ return SLJIT_SUCCESS;+}++#define FLOAT_MOV(op, dst_r, src_r) \+ (((op & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */) | F4(dst_r) | F0(src_r))++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_s32 dst_r = TMP_FREG1;+ sljit_ins ins_r, ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ do {+ if (FAST_IS_REG(dst)) {+ dst_r = dst;++ if (dst == src1)+ break;++ if (dst == src2) {+ if (GET_OPCODE(op) == SLJIT_ADD_F64 || GET_OPCODE(op) == SLJIT_MUL_F64) {+ src2 = src1;+ src2w = src1w;+ src1 = dst;+ break;+ }++ FAIL_IF(push_inst(compiler, FLOAT_MOV(op, TMP_FREG1, src2)));+ src2 = TMP_FREG1;+ }+ }++ if (src1 & SLJIT_MEM)+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), dst_r, src1, src1w));+ else+ FAIL_IF(push_inst(compiler, FLOAT_MOV(op, dst_r, src1)));+ } while (0);++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ ins_r = (op & SLJIT_32) ? 0xb30a0000 /* aebr */ : 0xb31a0000 /* adbr */;+ ins = (op & SLJIT_32) ? 0xed000000000a /* aeb */ : 0xed000000001a /* adb */;+ break;+ case SLJIT_SUB_F64:+ ins_r = (op & SLJIT_32) ? 0xb30b0000 /* sebr */ : 0xb31b0000 /* sdbr */;+ ins = (op & SLJIT_32) ? 0xed000000000b /* seb */ : 0xed000000001b /* sdb */;+ break;+ case SLJIT_MUL_F64:+ ins_r = (op & SLJIT_32) ? 0xb3170000 /* meebr */ : 0xb31c0000 /* mdbr */;+ ins = (op & SLJIT_32) ? 0xed0000000017 /* meeb */ : 0xed000000001c /* mdb */;+ break;+ default:+ SLJIT_ASSERT(GET_OPCODE(op) == SLJIT_DIV_F64);+ ins_r = (op & SLJIT_32) ? 0xb30d0000 /* debr */ : 0xb31d0000 /* ddbr */;+ ins = (op & SLJIT_32) ? 0xed000000000d /* deb */ : 0xed000000001d /* ddb */;+ break;+ }++ FAIL_IF(emit_float(compiler, ins_r, ins, dst_r, src2, src2w));++ if (dst & SLJIT_MEM)+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 reg;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (src2 & SLJIT_MEM) {+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src2, src2w));+ src2 = TMP_FREG1;+ }++ if (src1 & SLJIT_MEM) {+ reg = (dst_freg == src2) ? TMP_FREG1 : dst_freg;+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), reg, src1, src1w));+ src1 = reg;+ }++ return push_inst(compiler, 0xb3720000 /* cpsdr */ | F12(src2) | F4(dst_freg) | F0(src1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+ union {+ sljit_s32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++ FAIL_IF(push_load_imm_inst(compiler, tmp1, (sljit_sw)(((sljit_uw)u.imm << 32))));+ return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(tmp1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ union {+ sljit_sw imm;+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ FAIL_IF(push_load_imm_inst(compiler, tmp1, (sljit_sw)u.imm));+ return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(tmp1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_gpr gen_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ gen_r = gpr(reg);++ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {+ if (op & SLJIT_32) {+ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp0) | R32A(gen_r) | (32 << 16)));+ gen_r = tmp0;+ }++ return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(gen_r));+ }++ FAIL_IF(push_inst(compiler, 0xb3cd0000 /* lgdr */ | R4A(gen_r) | F0(freg)));++ if (!(op & SLJIT_32))+ return SLJIT_SUCCESS;++ return push_inst(compiler, 0xeb000000000c /* srlg */ | R36A(gen_r) | R32A(gen_r) | (32 << 16));+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;+ sljit_u8 mask = ((type & 0xff) < SLJIT_JUMP) ? get_cc(compiler, type & 0xff) : 0xf;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ /* record jump */+ jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ jump->addr = compiler->size;++ /* emit jump instruction */+ type &= 0xff;+ if (type >= SLJIT_FAST_CALL)+ PTR_FAIL_IF(push_inst(compiler, brasl(link_r, 0)));+ else+ PTR_FAIL_IF(push_inst(compiler, brcl(mask, 0)));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ SLJIT_UNUSED_ARG(arg_types);+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ if (type & SLJIT_CALL_RETURN) {+ PTR_FAIL_IF(emit_stack_frame_release(compiler, r14));+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, type);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp1;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));++ if (src == SLJIT_IMM) {+ SLJIT_ASSERT(!(srcw & 1)); /* target address must be even */+ FAIL_IF(push_load_imm_inst(compiler, src_r, srcw));+ }+ else if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(load_word(compiler, src_r, src, srcw, 0 /* 64-bit */));+ }++ /* emit jump instruction */+ if (type >= SLJIT_FAST_CALL)+ return push_inst(compiler, basr(link_r, src_r));++ return push_inst(compiler, br(src_r));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(arg_types);++ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ SLJIT_ASSERT(gpr(TMP_REG2) == tmp1);++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */));+ src = TMP_REG2;+ srcw = 0;+ }++ if (type & SLJIT_CALL_RETURN) {+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src))));+ src = TMP_REG2;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, r14));+ type = SLJIT_JUMP;+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+}++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_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;+ sljit_gpr loc_r = tmp1;+ sljit_u8 mask = get_cc(compiler, type);++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));++ switch (GET_OPCODE(op)) {+ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ compiler->status_flags_state = op & SLJIT_SET_Z;++ /* dst is also source operand */+ if (dst & SLJIT_MEM)+ FAIL_IF(load_word(compiler, dst_r, dst, dstw, op & SLJIT_32));++ break;+ case SLJIT_MOV32:+ op |= SLJIT_32;+ /* fallthrough */+ case SLJIT_MOV:+ /* can write straight into destination */+ loc_r = dst_r;+ break;+ default:+ SLJIT_UNREACHABLE();+ }++ /* TODO(mundaym): fold into cmov helper function? */+ #define LEVAL(i) i(loc_r, 1, mask)+ if (have_lscond2()) {+ FAIL_IF(push_load_imm_inst(compiler, loc_r, 0));+ FAIL_IF(push_inst(compiler,+ WHEN2(op & SLJIT_32, lochi, locghi)));+ } else {+ FAIL_IF(push_load_imm_inst(compiler, loc_r, 1));+ FAIL_IF(push_inst(compiler, brc(mask, 2 + 2)));+ FAIL_IF(push_load_imm_inst(compiler, loc_r, 0));+ }+ #undef LEVAL++ /* apply bitwise op and set condition codes */+ switch (GET_OPCODE(op)) {+ #define LEVAL(i) i(dst_r, loc_r)+ case SLJIT_AND:+ FAIL_IF(push_inst(compiler,+ WHEN2(op & SLJIT_32, nr, ngr)));+ break;+ case SLJIT_OR:+ FAIL_IF(push_inst(compiler,+ WHEN2(op & SLJIT_32, or, ogr)));+ break;+ case SLJIT_XOR:+ FAIL_IF(push_inst(compiler,+ WHEN2(op & SLJIT_32, xr, xgr)));+ break;+ #undef LEVAL+ }++ /* store result to memory if required */+ if (dst & SLJIT_MEM)+ return store_word(compiler, dst_r, dst, dstw, (op & SLJIT_32));++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+ sljit_ins mask;+ sljit_gpr src_r;+ sljit_gpr dst_r = gpr(dst_reg);+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (dst_reg != src2_reg) {+ if (src1 == dst_reg) {+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else {+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ FAIL_IF(load_word(compiler, dst_r, src1, src1w, type & SLJIT_32));+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else+ FAIL_IF(push_inst(compiler, ((type & SLJIT_32) ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(gpr(src2_reg))));+ }+ }++ mask = get_cc(compiler, type & ~SLJIT_32);++ if (src1 & SLJIT_MEM) {+ if (src1 & OFFS_REG_MASK) {+ src_r = gpr(OFFS_REG(src1));++ if (src1w != 0) {+ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp1) | R32A(src_r) | ((sljit_ins)(src1w & 0x3) << 16)));+ src_r = tmp1;+ }++ FAIL_IF(push_inst(compiler, 0xb9e80000 /* agrk */ | R12A(src_r) | R4A(tmp1) | R0A(gpr(src1 & REG_MASK))));+ src_r = tmp1;+ src1w = 0;+ } else if (!is_s20(src1w)) {+ FAIL_IF(push_load_imm_inst(compiler, tmp1, src1w));++ if (src1 & REG_MASK)+ FAIL_IF(push_inst(compiler, 0xb9e80000 /* agrk */ | R12A(tmp1) | R4A(tmp1) | R0A(gpr(src1 & REG_MASK))));++ src_r = tmp1;+ src1w = 0;+ } else+ src_r = gpr(src1 & REG_MASK);++ ins = (type & SLJIT_32) ? 0xeb00000000f2 /* loc */ : 0xeb00000000e2 /* locg */;+ return push_inst(compiler, ins | R36A(dst_r) | (mask << 32) | R28A(src_r) | disp_s20((sljit_s32)src1w));+ }++ if (src1 == SLJIT_IMM) {+ if (type & SLJIT_32)+ src1w = (sljit_s32)src1w;++ if (have_lscond2() && is_s16(src1w)) {+ ins = (type & SLJIT_32) ? 0xec0000000042 /* lochi */ : 0xec0000000046 /* locghi */;+ return push_inst(compiler, ins | R36A(dst_r) | (mask << 32) | (sljit_ins)(src1w & 0xffff) << 16);+ }++ FAIL_IF(push_load_imm_inst(compiler, tmp1, src1w));+ src_r = tmp1;+ } else+ src_r = gpr(src1);++ ins = (type & SLJIT_32) ? 0xb9f20000 /* locr */ : 0xb9e20000 /* locgr */;+ return push_inst(compiler, ins | (mask << 12) | R4A(dst_r) | R0A(src_r));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+ sljit_ins ins;+ struct sljit_label *label;+ struct sljit_jump *jump;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ if (dst_freg != src2_freg) {+ if (dst_freg == src1) {+ src1 = src2_freg;+ src1w = 0;+ type ^= 0x1;+ } else {+ ins = (type & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */;+ FAIL_IF(push_inst(compiler, ins | F4(dst_freg) | F0(src2_freg)));+ }+ }++ SLJIT_SKIP_CHECKS(compiler);+ jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);+ FAIL_IF(!jump);++ if (!(src1 & SLJIT_MEM)) {+ ins = (type & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */;+ FAIL_IF(push_inst(compiler, ins | F4(dst_freg) | F0(src1)));+ } else+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (type & SLJIT_32), dst_freg, src1, src1w));++ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ FAIL_IF(!label);++ sljit_set_label(jump, label);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_ins ins, reg1, reg2, base, offs = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (!(reg & REG_PAIR_MASK))+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);++ ADJUST_LOCAL_OFFSET(mem, memw);++ base = gpr(mem & REG_MASK);+ reg1 = gpr(REG_PAIR_FIRST(reg));+ reg2 = gpr(REG_PAIR_SECOND(reg));++ if (mem & OFFS_REG_MASK) {+ memw &= 0x3;+ offs = gpr(OFFS_REG(mem));++ if (memw != 0) {+ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp1) | R32A(offs) | ((sljit_ins)memw << 16)));+ offs = tmp1;+ } else if (!(type & SLJIT_MEM_STORE) && (base == reg1 || base == reg2) && (offs == reg1 || offs == reg2)) {+ FAIL_IF(push_inst(compiler, 0xb9f80000 | R12A(tmp1) | R4A(base) | R0A(offs)));+ base = tmp1;+ offs = 0;+ }++ memw = 0;+ } else if (memw < -0x80000 || memw > 0x7ffff - ((reg2 == reg1 + 1) ? 0 : SSIZE_OF(sw))) {+ FAIL_IF(push_load_imm_inst(compiler, tmp1, memw));++ if (base == 0)+ base = tmp1;+ else+ offs = tmp1;++ memw = 0;+ }++ if (offs == 0 && reg2 == (reg1 + 1)) {+ ins = (type & SLJIT_MEM_STORE) ? 0xeb0000000024 /* stmg */ : 0xeb0000000004 /* lmg */;+ return push_inst(compiler, ins | R36A(reg1) | R32A(reg2) | R28A(base) | disp_s20((sljit_s32)memw));+ }++ ins = ((type & SLJIT_MEM_STORE) ? 0xe30000000024 /* stg */ : 0xe30000000004 /* lg */) | R32A(offs) | R28A(base);++ if (!(type & SLJIT_MEM_STORE) && base == reg1) {+ FAIL_IF(push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw))));+ return push_inst(compiler, ins | R36A(reg1) | disp_s20((sljit_s32)memw));+ }++ FAIL_IF(push_inst(compiler, ins | R36A(reg1) | disp_s20((sljit_s32)memw)));+ return push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw)));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);+ struct addr addr;+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (!(srcdst & SLJIT_MEM)) {+ if (type & SLJIT_SIMD_STORE)+ ins = F36(srcdst) | F32(freg);+ else+ ins = F36(freg) | F32(srcdst);++ return push_inst(compiler, 0xe70000000056 /* vlr */ | ins);+ }++ FAIL_IF(make_addr_bx(compiler, &addr, srcdst, srcdstw, tmp1));+ ins = F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset);++ if (alignment >= 4)+ ins |= 4 << 12;+ else if (alignment == 3)+ ins |= 3 << 12;++ return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? 0xe7000000000e /* vst */ : 0xe70000000006 /* vl */) | ins);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ struct addr addr;+ sljit_gpr reg;+ sljit_sw sign_ext;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (src & SLJIT_MEM) {+ FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1));+ return push_inst(compiler, 0xe70000000005 /* vlrep */ | F36(freg)+ | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset) | ((sljit_ins)elem_size << 12));+ }++ if (type & SLJIT_SIMD_FLOAT) {+ if (src == SLJIT_IMM)+ return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(freg));++ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(freg) | F32(src) | ((sljit_ins)elem_size << 12));+ }++ if (src == SLJIT_IMM) {+ sign_ext = 0x10000;++ switch (elem_size) {+ case 0:+ srcw &= 0xff;+ sign_ext = (sljit_s8)srcw;+ break;+ case 1:+ srcw &= 0xffff;+ sign_ext = (sljit_s16)srcw;+ break;+ case 2:+ if ((sljit_s32)srcw == (sljit_s16)srcw) {+ srcw &= 0xffff;+ sign_ext = (sljit_s16)srcw;+ } else+ srcw &= 0xffffffff;+ break;+ default:+ if (srcw == (sljit_s16)srcw) {+ srcw &= 0xffff;+ sign_ext = (sljit_s16)srcw;+ }+ break;+ }++ if (sign_ext != 0x10000) {+ if (sign_ext == 0 || sign_ext == -1)+ return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(freg)+ | (sign_ext == 0 ? 0 : ((sljit_ins)0xffff << 16)));++ return push_inst(compiler, 0xe70000000045 /* vrepi */ | F36(freg)+ | ((sljit_ins)srcw << 16) | ((sljit_ins)elem_size << 12));+ }++ push_load_imm_inst(compiler, tmp0, srcw);+ reg = tmp0;+ } else+ reg = gpr(src);++ FAIL_IF(push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(freg) | R32A(reg) | ((sljit_ins)elem_size << 12)));+ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(freg) | F32(freg) | ((sljit_ins)elem_size << 12));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ struct addr addr;+ sljit_gpr reg;+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (srcdst & SLJIT_MEM) {+ FAIL_IF(make_addr_bx(compiler, &addr, srcdst, srcdstw, tmp1));+ ins = F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset);+ }++ if (type & SLJIT_SIMD_LANE_ZERO) {+ if ((srcdst & SLJIT_MEM) && lane_index == ((1 << (3 - elem_size)) - 1))+ return push_inst(compiler, 0xe70000000004 /* vllez */ | ins | ((sljit_ins)elem_size << 12));++ if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) {+ FAIL_IF(push_inst(compiler, 0xe70000000056 /* vlr */ | F36(TMP_FREG1) | F32(freg)));+ srcdst = TMP_FREG1;+ srcdstw = 0;+ }++ FAIL_IF(push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(freg)));+ }++ if (srcdst & SLJIT_MEM) {+ switch (elem_size) {+ case 0:+ ins |= 0xe70000000000 /* vleb */;+ break;+ case 1:+ ins |= 0xe70000000001 /* vleh */;+ break;+ case 2:+ ins |= 0xe70000000003 /* vlef */;+ break;+ default:+ ins |= 0xe70000000002 /* vleg */;+ break;+ }++ /* Convert to vsteb - vsteg */+ if (type & SLJIT_SIMD_STORE)+ ins |= 0x8;++ return push_inst(compiler, ins | ((sljit_ins)lane_index << 12));+ }++ if (type & SLJIT_SIMD_FLOAT) {+ if (type & SLJIT_SIMD_STORE)+ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(srcdst) | F32(freg) | ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12));++ if (elem_size == 3) {+ if (lane_index == 0)+ ins = F32(srcdst) | F28(freg) | (1 << 12);+ else+ ins = F32(freg) | F28(srcdst);++ return push_inst(compiler, 0xe70000000084 /* vpdi */ | F36(freg) | ins);+ }++ FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(tmp0) | F32(srcdst) | ((sljit_ins)2 << 12)));+ return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(freg) | R32A(tmp0) | ((sljit_ins)lane_index << 16) | ((sljit_ins)2 << 12));+ }++ if (srcdst == SLJIT_IMM) {+ switch (elem_size) {+ case 0:+ ins = 0xe70000000040 /* vleib */;+ srcdstw &= 0xff;+ break;+ case 1:+ ins = 0xe70000000041 /* vleih */;+ srcdstw &= 0xffff;+ break;+ case 2:+ if ((sljit_s32)srcdstw == (sljit_s16)srcdstw) {+ srcdstw &= 0xffff;+ ins = 0xe70000000043 /* vleif */;+ } else+ srcdstw &= 0xffffffff;+ break;+ default:+ if (srcdstw == (sljit_s16)srcdstw) {+ srcdstw &= 0xffff;+ ins = 0xe70000000042 /* vleig */;+ }+ break;+ }++ if (ins != 0)+ return push_inst(compiler, ins | F36(freg) | ((sljit_ins)srcdstw << 16) | ((sljit_ins)lane_index << 12));++ push_load_imm_inst(compiler, tmp0, srcdstw);+ reg = tmp0;+ } else+ reg = gpr(srcdst);++ ins = ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12);++ if (!(type & SLJIT_SIMD_STORE))+ return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(freg) | R32A(reg) | ins);++ FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(reg) | F32(freg) | ins));++ if (!(type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 3)+ return SLJIT_SUCCESS;++ switch (elem_size) {+ case 0:+ ins = 0xb9060000 /* lgbr */;+ break;+ case 1:+ ins = 0xb9070000 /* lghr */;+ break;+ default:+ ins = 0xb9140000 /* lgfr */;+ break;+ }++ return push_inst(compiler, ins | R4A(reg) | R0A(reg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_s32 src_lane_index)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index));++ if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(freg) | F32(src)+ | ((sljit_ins)src_lane_index << 16) | ((sljit_ins)elem_size << 12));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);+ struct addr addr;+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (src & SLJIT_MEM) {+ FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1));+ ins = F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset);++ switch (elem2_size - elem_size) {+ case 1:+ ins |= 0xe70000000002 /* vleg */;+ break;+ case 2:+ ins |= 0xe70000000003 /* vlef */;+ break;+ default:+ ins |= 0xe70000000001 /* vleh */;+ break;+ }++ FAIL_IF(push_inst(compiler, ins));+ src = freg;+ }++ if (type & SLJIT_SIMD_FLOAT) {+ FAIL_IF(push_inst(compiler, 0xe700000000d5 /* vuplh */ | F36(freg) | F32(src) | (2 << 12)));+ FAIL_IF(push_inst(compiler, 0xe70000000030 /* vesl */ | F36(freg) | F32(freg) | (32 << 16) | (3 << 12)));+ return push_inst(compiler, 0xe700000000c4 /* vfll */ | F36(freg) | F32(freg) | (2 << 12));+ }++ ins = ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0xe700000000d7 /* vuph */ : 0xe700000000d5 /* vuplh */) | F36(freg);++ do {+ FAIL_IF(push_inst(compiler, ins | F32(src) | ((sljit_ins)elem_size << 12)));+ src = freg;+ } while (++elem_size < elem2_size);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_gpr dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw));++ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ switch (elem_size) {+ case 0:+ push_load_imm_inst(compiler, tmp0, (sljit_sw)0x4048505860687078);+ push_load_imm_inst(compiler, tmp1, (sljit_sw)0x0008101820283038);+ FAIL_IF(push_inst(compiler, 0xe70000000062 /* vlvgp */ | F36(TMP_FREG1) | R32A(tmp1) | R28A(tmp0)));+ break;+ case 1:+ push_load_imm_inst(compiler, tmp0, (sljit_sw)0x0010203040506070);+ break;+ case 2:+ push_load_imm_inst(compiler, tmp0, (sljit_sw)0x8080808000204060);+ break;+ default:+ push_load_imm_inst(compiler, tmp0, (sljit_sw)0x8080808080800040);+ break;+ }++ if (elem_size != 0)+ FAIL_IF(push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(TMP_FREG1) | R32A(tmp0) | (1 << 16) | (3 << 12)));++ FAIL_IF(push_inst(compiler, 0xe70000000085 /* vbperm */ | F36(TMP_FREG1) | F32(freg) | F28(TMP_FREG1)));++ dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;+ FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(dst_r) | F32(TMP_FREG1)+ | (elem_size == 0 ? ((3 << 16) | (1 << 12)) : (7 << 16))));++ if (dst_r == tmp0)+ return store_word(compiler, tmp0, dst, dstw, type & SLJIT_32);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins ins = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg));++ if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ switch (SLJIT_SIMD_GET_OPCODE(type)) {+ case SLJIT_SIMD_OP2_AND:+ ins = 0xe70000000068 /* vn */;+ break;+ case SLJIT_SIMD_OP2_OR:+ ins = 0xe7000000006a /* vo */;+ break;+ case SLJIT_SIMD_OP2_XOR:+ ins = 0xe7000000006d /* vx */;+ break;+ }++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ins | F36(dst_freg) | F32(src1_freg) | F28(src2_freg));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 mem_reg)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op1(compiler, op, dst_reg, 0, SLJIT_MEM1(mem_reg), 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src_reg,+ sljit_s32 mem_reg,+ sljit_s32 temp_reg)+{+ sljit_ins mask;+ sljit_gpr tmp_r = gpr(temp_reg);+ sljit_gpr mem_r = gpr(mem_reg);++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV32:+ case SLJIT_MOV_U32:+ return push_inst(compiler, 0xba000000 /* cs */ | R20A(tmp_r) | R16A(gpr(src_reg)) | R12A(mem_r));+ case SLJIT_MOV_U8:+ mask = 0xff;+ break;+ case SLJIT_MOV_U16:+ mask = 0xffff;+ break;+ default:+ return push_inst(compiler, 0xeb0000000030 /* csg */ | R36A(tmp_r) | R32A(gpr(src_reg)) | R28A(mem_r));+ }++ /* tmp0 = (src_reg ^ tmp_r) & mask */+ FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | mask));+ FAIL_IF(push_inst(compiler, 0xb9e70000 /* xgrk */ | R4A(tmp0) | R0A(gpr(src_reg)) | R12A(tmp_r)));+ FAIL_IF(push_inst(compiler, 0xa7090000 /* lghi */ | R20A(tmp_r) | 0xfffc));+ FAIL_IF(push_inst(compiler, 0xb9800000 /* ngr */ | R4A(tmp0) | R0A(tmp1)));++ /* tmp0 = tmp0 << (((mem_r ^ 0x3) & 0x3) << 3) */+ FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | (sljit_ins)((mask == 0xff) ? 0x18 : 0x10)));+ FAIL_IF(push_inst(compiler, 0xb9800000 /* ngr */ | R4A(tmp_r) | R0A(mem_r)));+ FAIL_IF(push_inst(compiler, 0xec0000000057 /* rxsbg */ | R36A(tmp1) | R32A(mem_r) | (59 << 24) | (60 << 16) | (3 << 8)));+ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp0) | R32A(tmp0) | R28A(tmp1)));++ /* Already computed: tmp_r = mem_r & ~0x3 */++ FAIL_IF(push_inst(compiler, 0x58000000 /* l */ | R20A(tmp1) | R12A(tmp_r)));+ FAIL_IF(push_inst(compiler, 0x1700 /* x */ | R4A(tmp0) | R0A(tmp1)));+ return push_inst(compiler, 0xba000000 /* cs */ | R20A(tmp1) | R16A(tmp0) | R12A(tmp_r));+}++/* --------------------------------------------------------------------- */+/* Other instructions */+/* --------------------------------------------------------------------- */++/* On s390x we build a literal pool to hold constants. This has two main+ advantages:++ 1. we only need one instruction in the instruction stream (LGRL)+ 2. we can store 64 bit addresses and use 32 bit offsets++ To retrofit the extra information needed to build the literal pool we+ add a new sljit_s390x_const struct that contains the initial value but+ can still be cast to a sljit_const. */++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_s390x_const *const_;+ sljit_gpr dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));++ const_ = (struct sljit_s390x_const*)ensure_abuf(compiler,+ sizeof(struct sljit_s390x_const));+ PTR_FAIL_IF(!const_);+ set_const((struct sljit_const*)const_, compiler);+ const_->init_value = init_value;++ dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;+ if (have_genext())+ PTR_FAIL_IF(push_inst(compiler, lgrl(dst_r, 0)));+ else {+ PTR_FAIL_IF(push_inst(compiler, larl(tmp1, 0)));+ PTR_FAIL_IF(push_inst(compiler, lg(dst_r, 0, r0, tmp1)));+ }++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, 0 /* always 64-bit */));++ return (struct sljit_const*)const_;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ /* Update the constant pool. */+ sljit_uw *ptr = (sljit_uw *)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);+ *ptr = new_target;+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);+ SLJIT_CACHE_FLUSH(ptr, ptr + 1);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_gpr dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;++ if (have_genext())+ PTR_FAIL_IF(push_inst(compiler, lgrl(dst_r, 0)));+ else {+ PTR_FAIL_IF(push_inst(compiler, larl(tmp1, 0)));+ PTR_FAIL_IF(push_inst(compiler, lg(dst_r, 0, r0, tmp1)));+ }++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, 0));++ return jump; } /* TODO(carenas): EVAL probably should move up or be refactored */
− src/c/pcre2/src/sljit/sljitNativeSPARC_32.c
@@ -1,283 +0,0 @@-/*- * Stack-less Just-In-Time compiler- *- * 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:- *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.- *- * 2. Redistributions in binary form must reproduce the above copyright notice, this list- * of conditions and the following disclaimer in the documentation and/or other materials- * provided with the distribution.- *- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT- * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.- */--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));-- FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((imm >> 10) & 0x3fffff), DR(dst)));- return (imm & 0x3ff) ? push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (imm & 0x3ff), DR(dst)) : SLJIT_SUCCESS;-}--#define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2))--static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_u32 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:- 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_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_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));- }- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- 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_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));- }- SLJIT_ASSERT(dst == src2);- return SLJIT_SUCCESS;-- case SLJIT_NOT:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DRF(dst, flags));-- case SLJIT_CLZ:- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));- 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 | 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) | ((sljit_ins)-2 & DISP_MASK), UNMOVABLE_INS));- return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS);-- case SLJIT_ADD:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));-- case SLJIT_ADDC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;- return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));-- case SLJIT_SUB:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));-- case SLJIT_SUBC:- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;- return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));-- case SLJIT_MUL:- compiler->status_flags_state = 0;- FAIL_IF(push_inst(compiler, SMUL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));- if (!(flags & SET_FLAGS))- return SLJIT_SUCCESS;- FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(dst) | IMM(31), DR(TMP_REG1)));- FAIL_IF(push_inst(compiler, RDY | D(TMP_LINK), DR(TMP_LINK)));- return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_LINK), MOVABLE_INS | SET_FLAGS);-- case SLJIT_AND:- return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));-- case SLJIT_OR:- return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));-- case SLJIT_XOR:- return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));-- case SLJIT_SHL:- FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));- return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);-- case SLJIT_LSHR:- FAIL_IF(push_inst(compiler, SRL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));- return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);-- case SLJIT_ASHR:- FAIL_IF(push_inst(compiler, SRA | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));- return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);- }-- SLJIT_UNREACHABLE();- return SLJIT_SUCCESS;-}--static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)-{- sljit_s32 reg_index = 8;- sljit_s32 word_reg_index = 8;- sljit_s32 float_arg_index = 1;- sljit_s32 double_arg_count = 0;- sljit_u32 float_offset = (16 + 6) * sizeof(sljit_sw);- sljit_s32 types = 0;- sljit_s32 reg = 0;- sljit_s32 move_to_tmp2 = 0;-- if (src)- reg = reg_map[*src & REG_MASK];-- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types) {- types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);-- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- float_arg_index++;- double_arg_count++;- if (reg_index == reg || reg_index + 1 == reg)- move_to_tmp2 = 1;- reg_index += 2;- break;- case SLJIT_ARG_TYPE_F32:- float_arg_index++;- if (reg_index == reg)- move_to_tmp2 = 1;- reg_index++;- break;- default:- if (reg_index != word_reg_index && reg_index == reg)- move_to_tmp2 = 1;- reg_index++;- word_reg_index++;- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- if (move_to_tmp2) {- if (reg < 14)- FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2A(reg), DR(TMP_REG1)));- *src = TMP_REG1;- }-- arg_types = types;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- float_arg_index--;- if (float_arg_index == 4 && double_arg_count == 4) {- /* The address is not doubleword aligned, so two instructions are required to store the double. */- FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM((16 + 7) * sizeof(sljit_sw)), MOVABLE_INS));- FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | (1 << 25) | S1(SLJIT_SP) | IMM((16 + 8) * sizeof(sljit_sw)), MOVABLE_INS));- }- else- FAIL_IF(push_inst(compiler, STDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));- float_offset -= sizeof(sljit_f64);- break;- case SLJIT_ARG_TYPE_F32:- float_arg_index--;- FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));- float_offset -= sizeof(sljit_f64);- break;- default:- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- float_offset = (16 + 6) * sizeof(sljit_sw);-- while (types) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- reg_index -= 2;- if (reg_index < 14) {- if ((reg_index & 0x1) != 0) {- FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));- if (reg_index < 8 + 6 - 1)- FAIL_IF(push_inst(compiler, LDUW | DA(reg_index + 1) | S1(SLJIT_SP) | IMM(float_offset + sizeof(sljit_sw)), reg_index + 1));- }- else- FAIL_IF(push_inst(compiler, LDD | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));- }- float_offset -= sizeof(sljit_f64);- break;- case SLJIT_ARG_TYPE_F32:- reg_index--;- if (reg_index < 8 + 6)- FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));- float_offset -= sizeof(sljit_f64);- break;- default:- reg_index--;- word_reg_index--;-- if (reg_index != word_reg_index) {- if (reg_index < 14)- FAIL_IF(push_inst(compiler, OR | DA(reg_index) | S1(0) | S2A(word_reg_index), reg_index));- else- FAIL_IF(push_inst(compiler, STW | DA(word_reg_index) | S1(SLJIT_SP) | IMM(92), word_reg_index));- }- break;- }-- types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--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_target, sljit_sw executable_offset)-{- sljit_ins *inst = (sljit_ins *)addr;- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);- SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));- inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff);- inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff);- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);- 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_sw executable_offset)-{- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);-}
− src/c/pcre2/src/sljit/sljitNativeSPARC_common.c
@@ -1,1673 +0,0 @@-/*- * Stack-less Just-In-Time compiler- *- * 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:- *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.- *- * 2. Redistributions in binary form must reproduce the above copyright notice, this list- * of conditions and the following disclaimer in the documentation and/or other materials- * provided with the distribution.- *- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT- * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.- */--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_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)-{-#if defined(__SUNPRO_C) && __SUNPRO_C < 0x590- __asm (- /* if (from == to) return */- "cmp %i0, %i1\n"- "be .leave\n"- "nop\n"-- /* loop until from >= to */- ".mainloop:\n"- "flush %i0\n"- "add %i0, 8, %i0\n"- "cmp %i0, %i1\n"- "bcs .mainloop\n"- "nop\n"-- /* The comparison was done above. */- "bne .leave\n"- /* nop is not necessary here, since the- sub operation has no side effect. */- "sub %i0, 4, %i0\n"- "flush %i0\n"- ".leave:"- );-#else- if (SLJIT_UNLIKELY(from == to))- return;-- do {- __asm__ volatile (- "flush %0\n"- : : "r"(from)- );- /* Operates at least on doubleword. */- from += 2;- } while (from < to);-- if (from == to) {- /* Flush the last word. */- from --;- __asm__ volatile (- "flush %0\n"- : : "r"(from)- );- }-#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)-#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)-/* This register is modified by calls, which affects the instruction- in the delay slot if it is used as a source register. */-#define TMP_LINK (SLJIT_NUMBER_OF_REGISTERS + 5)--#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)-#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)--static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {- 0, 8, 9, 10, 11, 23, 22, 21, 20, 19, 18, 17, 16, 29, 28, 27, 26, 25, 24, 14, 1, 12, 13, 15-};--static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {- 0, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30-};--/* --------------------------------------------------------------------- */-/* Instrucion forms */-/* --------------------------------------------------------------------- */--#define D(d) ((sljit_ins)reg_map[d] << 25)-#define FD(d) ((sljit_ins)freg_map[d] << 25)-#define FDN(d) (((sljit_ins)freg_map[d] | 0x1) << 25)-#define DA(d) ((sljit_ins)(d) << 25)-#define S1(s1) ((sljit_ins)reg_map[s1] << 14)-#define FS1(s1) ((sljit_ins)freg_map[s1] << 14)-#define S1A(s1) ((sljit_ins)(s1) << 14)-#define S2(s2) ((sljit_ins)reg_map[s2])-#define FS2(s2) ((sljit_ins)freg_map[s2])-#define FS2N(s2) ((sljit_ins)freg_map[s2] | 0x1)-#define S2A(s2) ((sljit_ins)(s2))-#define IMM_ARG 0x2000-#define DOP(op) ((sljit_ins)(op) << 5)-#define IMM(imm) (((sljit_ins)(imm) & 0x1fff) | IMM_ARG)--#define DR(dr) (reg_map[dr])-#define DRF(dr, flags) ((sljit_s32)(reg_map[dr] | ((flags) & SET_FLAGS)))-#define OPC1(opcode) ((sljit_ins)(opcode) << 30)-#define OPC2(opcode) ((sljit_ins)(opcode) << 22)-#define OPC3(opcode) ((sljit_ins)(opcode) << 19)-#define SET_FLAGS OPC3(0x10)--#define ADD (OPC1(0x2) | OPC3(0x00))-#define ADDC (OPC1(0x2) | OPC3(0x08))-#define AND (OPC1(0x2) | OPC3(0x01))-#define ANDN (OPC1(0x2) | OPC3(0x05))-#define CALL (OPC1(0x1))-#define FABSS (OPC1(0x2) | OPC3(0x34) | DOP(0x09))-#define FADDD (OPC1(0x2) | OPC3(0x34) | DOP(0x42))-#define FADDS (OPC1(0x2) | OPC3(0x34) | DOP(0x41))-#define FCMPD (OPC1(0x2) | OPC3(0x35) | DOP(0x52))-#define FCMPS (OPC1(0x2) | OPC3(0x35) | DOP(0x51))-#define FDIVD (OPC1(0x2) | OPC3(0x34) | DOP(0x4e))-#define FDIVS (OPC1(0x2) | OPC3(0x34) | DOP(0x4d))-#define FDTOI (OPC1(0x2) | OPC3(0x34) | DOP(0xd2))-#define FDTOS (OPC1(0x2) | OPC3(0x34) | DOP(0xc6))-#define FITOD (OPC1(0x2) | OPC3(0x34) | DOP(0xc8))-#define FITOS (OPC1(0x2) | OPC3(0x34) | DOP(0xc4))-#define FMOVS (OPC1(0x2) | OPC3(0x34) | DOP(0x01))-#define FMULD (OPC1(0x2) | OPC3(0x34) | DOP(0x4a))-#define FMULS (OPC1(0x2) | OPC3(0x34) | DOP(0x49))-#define FNEGS (OPC1(0x2) | OPC3(0x34) | DOP(0x05))-#define FSTOD (OPC1(0x2) | OPC3(0x34) | DOP(0xc9))-#define FSTOI (OPC1(0x2) | OPC3(0x34) | DOP(0xd1))-#define FSUBD (OPC1(0x2) | OPC3(0x34) | DOP(0x46))-#define FSUBS (OPC1(0x2) | OPC3(0x34) | DOP(0x45))-#define JMPL (OPC1(0x2) | OPC3(0x38))-#define LDD (OPC1(0x3) | OPC3(0x03))-#define LDDF (OPC1(0x3) | OPC3(0x23))-#define LDF (OPC1(0x3) | OPC3(0x20))-#define LDUW (OPC1(0x3) | OPC3(0x00))-#define NOP (OPC1(0x0) | OPC2(0x04))-#define OR (OPC1(0x2) | OPC3(0x02))-#define ORN (OPC1(0x2) | OPC3(0x06))-#define RDY (OPC1(0x2) | OPC3(0x28) | S1A(0))-#define RESTORE (OPC1(0x2) | OPC3(0x3d))-#define SAVE (OPC1(0x2) | OPC3(0x3c))-#define SETHI (OPC1(0x0) | OPC2(0x04))-#define SLL (OPC1(0x2) | OPC3(0x25))-#define SLLX (OPC1(0x2) | OPC3(0x25) | (1 << 12))-#define SRA (OPC1(0x2) | OPC3(0x27))-#define SRAX (OPC1(0x2) | OPC3(0x27) | (1 << 12))-#define SRL (OPC1(0x2) | OPC3(0x26))-#define SRLX (OPC1(0x2) | OPC3(0x26) | (1 << 12))-#define STD (OPC1(0x3) | OPC3(0x07))-#define STDF (OPC1(0x3) | OPC3(0x27))-#define STF (OPC1(0x3) | OPC3(0x24))-#define STW (OPC1(0x3) | OPC3(0x04))-#define SUB (OPC1(0x2) | OPC3(0x04))-#define SUBC (OPC1(0x2) | OPC3(0x0c))-#define TA (OPC1(0x2) | OPC3(0x3a) | (8 << 25))-#define WRY (OPC1(0x2) | OPC3(0x30) | DA(0))-#define XOR (OPC1(0x2) | OPC3(0x03))-#define XNOR (OPC1(0x2) | OPC3(0x07))--#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)-#define MAX_DISP (0x1fffff)-#define MIN_DISP (-0x200000)-#define DISP_MASK ((sljit_ins)0x3fffff)--#define BICC (OPC1(0x0) | OPC2(0x2))-#define FBFCC (OPC1(0x0) | OPC2(0x6))-#define SLL_W SLL-#define SDIV (OPC1(0x2) | OPC3(0x0f))-#define SMUL (OPC1(0x2) | OPC3(0x0b))-#define UDIV (OPC1(0x2) | OPC3(0x0e))-#define UMUL (OPC1(0x2) | OPC3(0x0a))-#else-#define SLL_W SLLX-#endif--#define SIMM_MAX (0x0fff)-#define SIMM_MIN (-0x1000)--/* dest_reg is the absolute name of the register- Useful for reordering instructions in the 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- || (delay_slot & DST_INS_MASK) == MOVABLE_INS- || (delay_slot & DST_INS_MASK) == ((ins >> 25) & 0x1f));- ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));- FAIL_IF(!ptr);- *ptr = ins;- compiler->size++;- compiler->delay_slot = delay_slot;- return SLJIT_SUCCESS;-}--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;- sljit_ins *inst;- sljit_ins saved_inst;-- if (jump->flags & SLJIT_REWRITABLE_JUMP)- return code_ptr;-- if (jump->flags & JUMP_ADDR)- target_addr = jump->u.target;- else {- SLJIT_ASSERT(jump->flags & JUMP_LABEL);- target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;- }- inst = (sljit_ins*)jump->addr;--#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- if (jump->flags & IS_CALL) {- /* Call is always patchable on sparc 32. */- jump->flags |= PATCH_CALL;- if (jump->flags & IS_MOVABLE) {- inst[0] = inst[-1];- inst[-1] = CALL;- jump->addr -= sizeof(sljit_ins);- return inst;- }- inst[0] = CALL;- inst[1] = NOP;- return inst + 1;- }-#else- /* Both calls and BPr instructions shall not pass this point. */-#error "Implementation required"-#endif-- if (jump->flags & IS_COND)- inst--;-- diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1) - executable_offset) >> 2;-- if (jump->flags & IS_MOVABLE) {- if (diff <= MAX_DISP && diff >= MIN_DISP) {- jump->flags |= PATCH_B;- inst--;- if (jump->flags & IS_COND) {- saved_inst = inst[0];- inst[0] = inst[1] ^ (1 << 28);- inst[1] = saved_inst;- } else {- inst[1] = inst[0];- inst[0] = BICC | DA(0x8);- }- jump->addr = (sljit_uw)inst;- return inst + 1;- }- }-- diff += SSIZE_OF(ins);-- if (diff <= MAX_DISP && diff >= MIN_DISP) {- jump->flags |= PATCH_B;- if (jump->flags & IS_COND)- inst[0] ^= (1 << 28);- else- inst[0] = BICC | DA(0x8);- inst[1] = NOP;- jump->addr = (sljit_uw)inst;- return inst + 1;- }-- return code_ptr;-}--SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)-{- struct sljit_memory_fragment *buf;- sljit_ins *code;- sljit_ins *code_ptr;- sljit_ins *buf_ptr;- sljit_ins *buf_end;- sljit_uw word_count;- sljit_uw next_addr;- sljit_sw executable_offset;- sljit_sw addr;-- struct sljit_label *label;- struct sljit_jump *jump;- struct sljit_const *const_;- struct sljit_put_label *put_label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_generate_code(compiler));- reverse_buf(compiler);-- code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);- PTR_FAIL_WITH_EXEC_IF(code);- buf = compiler->buf;-- code_ptr = code;- word_count = 0;- next_addr = 0;- executable_offset = SLJIT_EXEC_OFFSET(code);-- label = compiler->labels;- jump = compiler->jumps;- const_ = compiler->consts;- put_label = compiler->put_labels;-- do {- buf_ptr = (sljit_ins*)buf->memory;- buf_end = buf_ptr + (buf->used_size >> 2);- do {- *code_ptr = *buf_ptr++;- if (next_addr == word_count) {- SLJIT_ASSERT(!label || label->size >= word_count);- SLJIT_ASSERT(!jump || jump->addr >= word_count);- SLJIT_ASSERT(!const_ || const_->addr >= word_count);- SLJIT_ASSERT(!put_label || put_label->addr >= word_count);-- /* These structures are ordered by their address. */- if (label && label->size == word_count) {- /* Just recording the address. */- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }- if (jump && jump->addr == word_count) {-#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- jump->addr = (sljit_uw)(code_ptr - 3);-#else- jump->addr = (sljit_uw)(code_ptr - 6);-#endif- code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);- jump = jump->next;- }- if (const_ && const_->addr == word_count) {- /* Just recording the address. */- const_->addr = (sljit_uw)code_ptr;- const_ = const_->next;- }- if (put_label && put_label->addr == word_count) {- SLJIT_ASSERT(put_label->label);- put_label->addr = (sljit_uw)code_ptr;- put_label = put_label->next;- }- next_addr = compute_next_addr(label, jump, const_, put_label);- }- code_ptr ++;- word_count ++;- } while (buf_ptr < buf_end);-- buf = buf->next;- } while (buf);-- if (label && label->size == word_count) {- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- }-- SLJIT_ASSERT(!label);- SLJIT_ASSERT(!jump);- SLJIT_ASSERT(!const_);- SLJIT_ASSERT(!put_label);- SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);-- jump = compiler->jumps;- while (jump) {- do {- addr = (sljit_sw)((jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);- buf_ptr = (sljit_ins *)jump->addr;-- if (jump->flags & PATCH_CALL) {- addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;- SLJIT_ASSERT(addr <= 0x1fffffff && addr >= -0x20000000);- buf_ptr[0] = CALL | ((sljit_ins)addr & 0x3fffffff);- break;- }- if (jump->flags & PATCH_B) {- addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;- SLJIT_ASSERT(addr <= MAX_DISP && addr >= MIN_DISP);- buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | ((sljit_ins)addr & DISP_MASK);- break;- }-- /* Set the fields of immediate loads. */-#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));- buf_ptr[0] |= (sljit_ins)(addr >> 10) & 0x3fffff;- buf_ptr[1] |= (sljit_ins)addr & 0x3ff;-#else-#error "Implementation required"-#endif- } while (0);- jump = jump->next;- }-- put_label = compiler->put_labels;- while (put_label) {- addr = (sljit_sw)put_label->label->addr;- buf_ptr = (sljit_ins *)put_label->addr;--#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));- buf_ptr[0] |= (addr >> 10) & 0x3fffff;- buf_ptr[1] |= addr & 0x3ff;-#else-#error "Implementation required"-#endif- put_label = put_label->next;- }-- compiler->error = SLJIT_ERR_COMPILED;- compiler->executable_offset = executable_offset;- compiler->executable_size = (sljit_uw)(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);- SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);- 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_ZERO_REGISTER:- return 1;--#if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)- case SLJIT_HAS_CMOV:- return 1;-#endif-- default:- return 0;- }-}--/* --------------------------------------------------------------------- */-/* Entry, exit */-/* --------------------------------------------------------------------- */--/* Creates an index in data_transfer_insts array. */-#define LOAD_DATA 0x01-#define WORD_DATA 0x00-#define BYTE_DATA 0x02-#define HALF_DATA 0x04-#define INT_DATA 0x06-#define SIGNED_DATA 0x08-/* Separates integer and floating point registers */-#define GPR_REG 0x0f-#define DOUBLE_DATA 0x10-#define SINGLE_DATA 0x12--#define MEM_MASK 0x1f--#define ARG_TEST 0x00020-#define ALT_KEEP_CACHE 0x00040-#define CUMULATIVE_OP 0x00080-#define IMM_OP 0x00100-#define MOVE_OP 0x00200-#define SRC2_IMM 0x00400--#define REG_DEST 0x00800-#define REG2_SOURCE 0x01000-#define SLOW_SRC1 0x02000-#define SLOW_SRC2 0x04000-#define SLOW_DEST 0x08000--/* SET_FLAGS (0x10 << 19) also belong here! */--#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)-#include "sljitNativeSPARC_32.c"-#else-#include "sljitNativeSPARC_64.c"-#endif--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 reg_index, types, tmp;- sljit_u32 float_offset, args_offset;- sljit_s32 saved_arg_index, scratch_arg_index, float_arg_index;-- CHECK_ERROR();- CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7;- compiler->local_size = local_size;-- if (local_size <= -SIMM_MIN) {- FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | IMM(-local_size), UNMOVABLE_INS));- }- else {- FAIL_IF(load_immediate(compiler, TMP_REG1, -local_size));- FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | S2(TMP_REG1), UNMOVABLE_INS));- }-- arg_types >>= SLJIT_ARG_SHIFT;-- types = arg_types;- float_offset = 16 * sizeof(sljit_sw);- reg_index = 24;-- while (types && reg_index < 24 + 6) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (reg_index & 0x1) {- FAIL_IF(push_inst(compiler, STW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));- if (reg_index >= 24 + 6 - 1)- break;- FAIL_IF(push_inst(compiler, STW | DA(reg_index + 1) | S1(SLJIT_SP) | IMM(float_offset + sizeof(sljit_sw)), MOVABLE_INS));- } else- FAIL_IF(push_inst(compiler, STD | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));-- float_offset += sizeof(sljit_f64);- reg_index++;- break;- case SLJIT_ARG_TYPE_F32:- FAIL_IF(push_inst(compiler, STW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));- float_offset += sizeof(sljit_f64);- break;- }-- reg_index++;- types >>= SLJIT_ARG_SHIFT;- }-- args_offset = (16 + 1 + 6) * sizeof(sljit_sw);- float_offset = 16 * sizeof(sljit_sw);- reg_index = 24;- saved_arg_index = 24;- scratch_arg_index = 8 - 1;- float_arg_index = 1;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (reg_index < 24 + 6 - 1) {- FAIL_IF(push_inst(compiler, LDDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));- } else if (reg_index < 24 + 6) {- FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));- FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | (1 << 25) | S1A(30) | IMM(args_offset), MOVABLE_INS));- } else {- FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | S1A(30) | IMM(args_offset), MOVABLE_INS));- FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | (1 << 25) | S1A(30) | IMM(args_offset + sizeof(sljit_sw)), MOVABLE_INS));- }-- float_arg_index++;- float_offset += sizeof(sljit_f64);- reg_index++;- break;- case SLJIT_ARG_TYPE_F32:- if (reg_index < 24 + 6)- FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));- else- FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | S1A(30) | IMM(args_offset), MOVABLE_INS));- float_arg_index++;- float_offset += sizeof(sljit_f64);- break;- default:- scratch_arg_index++;-- if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- tmp = saved_arg_index++;- if (tmp == reg_index)- break;- } else- tmp = scratch_arg_index;-- if (reg_index < 24 + 6)- FAIL_IF(push_inst(compiler, OR | DA(tmp) | S1(0) | S2A(reg_index), tmp));- else- FAIL_IF(push_inst(compiler, LDUW | DA(tmp) | S1A(30) | IMM(args_offset), tmp));- break;- }-- reg_index++;- arg_types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- CHECK_ERROR();- CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7;- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)-{- CHECK_ERROR();- CHECK(check_sljit_emit_return_void(compiler));-- FAIL_IF(push_inst(compiler, JMPL | D(0) | S1A(31) | IMM(8), UNMOVABLE_INS));- return push_inst(compiler, RESTORE | D(SLJIT_R0) | S1(SLJIT_R0) | S2(0), UNMOVABLE_INS);-}--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));-- if (TYPE_CAST_NEEDED(op) || !FAST_IS_REG(src)) {- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));- src = SLJIT_R0;- }-- FAIL_IF(push_inst(compiler, JMPL | D(0) | S1A(31) | IMM(8), UNMOVABLE_INS));- return push_inst(compiler, RESTORE | D(SLJIT_R0) | S1(src) | S2(0), UNMOVABLE_INS);-}--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)-#define ARCH_32_64(a, b) a-#else-#define ARCH_32_64(a, b) b-#endif--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 */,-/* u b l */ OPC1(3) | OPC3(0x01) /* ldub */,-/* u h s */ OPC1(3) | OPC3(0x06) /* sth */,-/* u h l */ OPC1(3) | OPC3(0x02) /* lduh */,-/* u i s */ OPC1(3) | OPC3(0x04) /* stw */,-/* u i l */ OPC1(3) | OPC3(0x00) /* lduw */,--/* s w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */),-/* s w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */),-/* s b s */ OPC1(3) | OPC3(0x05) /* stb */,-/* s b l */ OPC1(3) | OPC3(0x09) /* ldsb */,-/* s h s */ OPC1(3) | OPC3(0x06) /* sth */,-/* s h l */ OPC1(3) | OPC3(0x0a) /* ldsh */,-/* s i s */ OPC1(3) | OPC3(0x04) /* stw */,-/* s i l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x08) /* ldsw */),--/* d s */ OPC1(3) | OPC3(0x27),-/* d l */ OPC1(3) | OPC3(0x23),-/* s s */ OPC1(3) | OPC3(0x24),-/* s l */ OPC1(3) | OPC3(0x20),-};--#undef ARCH_32_64--/* Can perform an operation using at most 1 instruction. */-static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_u32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)-{- SLJIT_ASSERT(arg & SLJIT_MEM);-- if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN)- || ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) {- /* Works for both absoulte and relative addresses (immediate case). */- if (SLJIT_UNLIKELY(flags & ARG_TEST))- return 1;- FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]- | ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg))- | S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)),- ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));- return -1;- }- return 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_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));-- /* Simple operation except for updates. */- if (arg & OFFS_REG_MASK) {- argw &= 0x3;- SLJIT_ASSERT(argw);- next_argw &= 0x3;- if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == next_argw)- return 1;- return 0;- }-- if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))- return 1;- return 0;-}--/* Emit the necessary instructions. See can_cache above. */-static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_u32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)-{- sljit_s32 base, arg2, delay_slot;- sljit_ins dest;-- SLJIT_ASSERT(arg & SLJIT_MEM);- if (!(next_arg & SLJIT_MEM)) {- next_arg = 0;- next_argw = 0;- }-- base = arg & REG_MASK;- if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {- argw &= 0x3;-- /* Using the cache. */- if (((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) && (argw == compiler->cache_argw))- arg2 = TMP_REG3;- else {- if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == (next_argw & 0x3)) {- compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);- compiler->cache_argw = argw;- arg2 = TMP_REG3;- }- else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base && reg != OFFS_REG(arg))- arg2 = reg;- else /* It must be a mov operation, so tmp1 must be free to use. */- arg2 = TMP_REG1;- FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1(OFFS_REG(arg)) | IMM_ARG | (sljit_ins)argw, DR(arg2)));- }- }- else {- /* Using the cache. */- if ((compiler->cache_arg == SLJIT_MEM) && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {- if (argw != compiler->cache_argw) {- FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | S1(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));- compiler->cache_argw = argw;- }- arg2 = TMP_REG3;- } else {- if ((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN) {- compiler->cache_arg = SLJIT_MEM;- compiler->cache_argw = argw;- arg2 = TMP_REG3;- }- else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base)- arg2 = reg;- else /* It must be a mov operation, so tmp1 must be free to use. */- arg2 = TMP_REG1;- FAIL_IF(load_immediate(compiler, arg2, argw));- }- }-- dest = ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg));- delay_slot = ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS;- if (!base)- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(arg2) | IMM(0), delay_slot);- return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot);-}--static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_u32 flags, sljit_s32 reg, sljit_s32 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_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_u32 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_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_u32 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_s32 dst_r = TMP_REG2;- sljit_s32 src1_r;- sljit_sw src2_r = 0;- sljit_s32 sugg_src2_r = TMP_REG2;-- if (!(flags & ALT_KEEP_CACHE)) {- compiler->cache_arg = 0;- compiler->cache_argw = 0;- }-- if (dst != TMP_REG2) {- if (FAST_IS_REG(dst)) {- dst_r = dst;- flags |= REG_DEST;- if (flags & MOVE_OP)- sugg_src2_r = dst_r;- }- 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) {- if (src2w <= SIMM_MAX && src2w >= SIMM_MIN) {- flags |= SRC2_IMM;- src2_r = src2w;- }- }- if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {- if (src1w <= SIMM_MAX && src1w >= SIMM_MIN) {- flags |= SRC2_IMM;- src2_r = src1w;-- /* And swap arguments. */- src1 = src2;- src1w = src2w;- src2 = SLJIT_IMM;- /* src2w = src2_r unneeded. */- }- }- }-- /* Source 1. */- if (FAST_IS_REG(src1))- src1_r = src1;- else if (src1 & SLJIT_IMM) {- if (src1w) {- FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));- src1_r = TMP_REG1;- }- else- src1_r = 0;- }- else {- if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))- FAIL_IF(compiler->error);- else- flags |= SLOW_SRC1;- src1_r = TMP_REG1;- }-- /* Source 2. */- if (FAST_IS_REG(src2)) {- src2_r = src2;- flags |= REG2_SOURCE;- if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)- dst_r = src2_r;- }- else if (src2 & SLJIT_IMM) {- if (!(flags & SRC2_IMM)) {- if (src2w) {- FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));- src2_r = sugg_src2_r;- }- else {- src2_r = 0;- if (flags & MOVE_OP) {- if (dst & SLJIT_MEM)- dst_r = 0;- else- op = SLJIT_MOV;- }- }- }- }- else {- if (getput_arg_fast(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w))- FAIL_IF(compiler->error);- else- flags |= SLOW_SRC2;- src2_r = sugg_src2_r;- }-- if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {- SLJIT_ASSERT(src2_r == TMP_REG2);- if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));- }- else {- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));- }- }- else if (flags & SLOW_SRC1)- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));- else if (flags & SLOW_SRC2)- FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));-- FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));-- if (dst & SLJIT_MEM) {- if (!(flags & SLOW_DEST)) {- getput_arg_fast(compiler, flags, dst_r, dst, dstw);- return compiler->error;- }- return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);- }-- return SLJIT_SUCCESS;-}--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));-- op = GET_OPCODE(op);- switch (op) {- case SLJIT_BREAKPOINT:- return push_inst(compiler, TA, UNMOVABLE_INS);- case SLJIT_NOP:- return push_inst(compiler, NOP, UNMOVABLE_INS);- 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_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_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_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_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_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));-#else-#error "Implementation required"-#endif- case SLJIT_ENDBR:- case SLJIT_SKIP_FRAMES_BEFORE_RETURN:- return SLJIT_SUCCESS;- }-- return SLJIT_SUCCESS;-}--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_u32 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);-- op = GET_OPCODE(op);- switch (op) {- case SLJIT_MOV:-#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:-#endif- case SLJIT_MOV_P:- return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);-- case SLJIT_MOV_U8:- return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);-- case SLJIT_MOV_S8:- return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);-- case SLJIT_MOV_U16:- return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);-- case SLJIT_MOV_S16:- return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);-- case SLJIT_NOT:- case SLJIT_CLZ:- return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);- }-- return SLJIT_SUCCESS;-}--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_u32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;-- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- op = GET_OPCODE(op);- switch (op) {- case SLJIT_ADD:- case SLJIT_ADDC:- case SLJIT_MUL:- case SLJIT_AND:- case SLJIT_OR:- case SLJIT_XOR:- return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_SUB:- case SLJIT_SUBC:- return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);-- case SLJIT_SHL:- case SLJIT_LSHR:- case SLJIT_ASHR:-#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- if (src2 & SLJIT_IMM)- src2w &= 0x1f;-#else- SLJIT_UNREACHABLE();-#endif- return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 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_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- switch (op) {- case SLJIT_FAST_RETURN:- if (FAST_IS_REG(src))- FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK)));- else- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw));-- FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS));- return push_inst(compiler, NOP, UNMOVABLE_INS);- case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:- case SLJIT_PREFETCH_L1:- case SLJIT_PREFETCH_L2:- case SLJIT_PREFETCH_L3:- case SLJIT_PREFETCH_ONCE:- return SLJIT_SUCCESS;- }-- return SLJIT_SUCCESS;-}--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_s32 sljit_get_float_register_index(sljit_s32 reg)-{- CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));- return freg_map[reg];-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_custom(compiler, instruction, size));-- return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);-}--/* --------------------------------------------------------------------- */-/* Floating point operators */-/* --------------------------------------------------------------------- */--#define FLOAT_DATA(op) ((sljit_ins)DOUBLE_DATA | (((sljit_ins)(op) & SLJIT_32) >> 7))-#define SELECT_FOP(op, single, double) ((op & SLJIT_32) ? single : double)-#define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw))--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));- src = TMP_FREG1;- }-- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | FD(TMP_FREG1) | FS2(src), MOVABLE_INS));-- 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);- }-- /* Store the integer value from a VFP register. */- return emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, dst, dstw, 0, 0);-}--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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- if (src & SLJIT_IMM) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- 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;- srcw = 0;- }-- if (FAST_IS_REG(src)) {- FAIL_IF(emit_op_mem2(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));- src = SLJIT_MEM1(SLJIT_SP);- srcw = FLOAT_TMP_MEM_OFFSET;- }-- FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FITOS, FITOD) | FD(dst_r) | FS2(TMP_FREG1), MOVABLE_INS));-- if (dst & SLJIT_MEM)- return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);- return SLJIT_SUCCESS;-}--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));- src1 = TMP_FREG1;- }-- if (src2 & SLJIT_MEM) {- FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));- src2 = TMP_FREG2;- }-- return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | FS1(src1) | FS2(src2), FCC_IS_SET | MOVABLE_INS);-}--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_s32 dst_r;-- CHECK_ERROR();- compiler->cache_arg = 0;- compiler->cache_argw = 0;-- SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);- SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);-- if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)- op ^= SLJIT_32;-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;-- if (src & SLJIT_MEM) {- FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));- src = dst_r;- }-- switch (GET_OPCODE(op)) {- case SLJIT_MOV_F64:- if (src != dst_r) {- if (dst_r != TMP_FREG1) {- FAIL_IF(push_inst(compiler, FMOVS | FD(dst_r) | FS2(src), MOVABLE_INS));- if (!(op & SLJIT_32))- FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));- }- else- dst_r = src;- }- break;- case SLJIT_NEG_F64:- FAIL_IF(push_inst(compiler, FNEGS | FD(dst_r) | FS2(src), MOVABLE_INS));- if (dst_r != src && !(op & SLJIT_32))- FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));- break;- case SLJIT_ABS_F64:- FAIL_IF(push_inst(compiler, FABSS | FD(dst_r) | FS2(src), MOVABLE_INS));- if (dst_r != src && !(op & SLJIT_32))- FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));- break;- case SLJIT_CONV_F64_FROM_F32:- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | FD(dst_r) | FS2(src), MOVABLE_INS));- op ^= SLJIT_32;- break;- }-- if (dst & SLJIT_MEM)- FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0));- return SLJIT_SUCCESS;-}--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_s32 dst_r, flags = 0;-- CHECK_ERROR();- CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- compiler->cache_arg = 0;- compiler->cache_argw = 0;-- dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;-- if (src1 & SLJIT_MEM) {- if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {- FAIL_IF(compiler->error);- src1 = TMP_FREG1;- } else- flags |= SLOW_SRC1;- }-- if (src2 & SLJIT_MEM) {- if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {- FAIL_IF(compiler->error);- src2 = TMP_FREG2;- } 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, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));- }- else {- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));- }- }- else if (flags & SLOW_SRC1)- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));- else if (flags & SLOW_SRC2)- FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));-- if (flags & SLOW_SRC1)- src1 = TMP_FREG1;- if (flags & SLOW_SRC2)- src2 = TMP_FREG2;-- switch (GET_OPCODE(op)) {- case SLJIT_ADD_F64:- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));- break;-- case SLJIT_SUB_F64:- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));- break;-- case SLJIT_MUL_F64:- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));- break;-- case SLJIT_DIV_F64:- FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));- break;- }-- if (dst_r == TMP_FREG2)- FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));-- return SLJIT_SUCCESS;-}--#undef FLOAT_DATA-#undef SELECT_FOP--/* --------------------------------------------------------------------- */-/* Other instructions */-/* --------------------------------------------------------------------- */--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);-- if (FAST_IS_REG(dst))- return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), UNMOVABLE_INS);-- /* Memory. */- FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw));- compiler->delay_slot = UNMOVABLE_INS;- return SLJIT_SUCCESS;-}--/* --------------------------------------------------------------------- */-/* Conditional instructions */-/* --------------------------------------------------------------------- */--SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)-{- struct sljit_label *label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_label(compiler));-- if (compiler->last_label && compiler->last_label->size == compiler->size)- return compiler->last_label;-- label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));- PTR_FAIL_IF(!label);- set_label(label, compiler);- compiler->delay_slot = UNMOVABLE_INS;- return label;-}--static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)-{- switch (type) {- case SLJIT_EQUAL:- case SLJIT_NOT_EQUAL_F64: /* Unordered. */- return DA(0x1);-- case SLJIT_NOT_EQUAL:- case SLJIT_EQUAL_F64:- return DA(0x9);-- case SLJIT_LESS:- case SLJIT_GREATER_F64: /* Unordered. */- case SLJIT_CARRY:- return DA(0x5);-- case SLJIT_GREATER_EQUAL:- case SLJIT_LESS_EQUAL_F64:- case SLJIT_NOT_CARRY:- return DA(0xd);-- case SLJIT_GREATER:- case SLJIT_GREATER_EQUAL_F64: /* Unordered. */- return DA(0xc);-- case SLJIT_LESS_EQUAL:- case SLJIT_LESS_F64:- return DA(0x4);-- case SLJIT_SIG_LESS:- return DA(0x3);-- case SLJIT_SIG_GREATER_EQUAL:- return DA(0xb);-- case SLJIT_SIG_GREATER:- return DA(0xa);-- case SLJIT_SIG_LESS_EQUAL:- return DA(0x2);-- case SLJIT_OVERFLOW:- if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))- return DA(0x9);- /* fallthrough */-- case SLJIT_UNORDERED_F64:- return DA(0x7);-- case SLJIT_NOT_OVERFLOW:- if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))- return DA(0x1);- /* fallthrough */-- case SLJIT_ORDERED_F64:- return DA(0xf);-- default:- SLJIT_UNREACHABLE();- return DA(0x8);- }-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)-{- struct sljit_jump *jump;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_jump(compiler, type));-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);- type &= 0xff;-- 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;-#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- PTR_FAIL_IF(push_inst(compiler, BICC | get_cc(compiler, type ^ 1) | 5, UNMOVABLE_INS));-#else-#error "Implementation required"-#endif- }- else if (type < SLJIT_JUMP) {- jump->flags |= IS_COND;- if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & FCC_IS_SET))- jump->flags |= IS_MOVABLE;-#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)- PTR_FAIL_IF(push_inst(compiler, FBFCC | get_cc(compiler, type ^ 1) | 5, UNMOVABLE_INS));-#else-#error "Implementation required"-#endif- }- else {- if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)- jump->flags |= IS_MOVABLE;- if (type >= SLJIT_FAST_CALL)- jump->flags |= IS_CALL;- }-- PTR_FAIL_IF(emit_const(compiler, TMP_REG1, 0));- PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(TMP_REG1) | IMM(0), UNMOVABLE_INS));- jump->addr = compiler->size;- PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));-- return jump;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types)-{- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));-- PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_jump(compiler, type);-}--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_s32 src_r;-- CHECK_ERROR();- CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- if (FAST_IS_REG(src))- src_r = src;- else if (src & SLJIT_IMM) {- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- FAIL_IF(!jump);- set_jump(jump, compiler, JUMP_ADDR);- jump->u.target = (sljit_uw)srcw;-- if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)- jump->flags |= IS_MOVABLE;- if (type >= SLJIT_FAST_CALL)- jump->flags |= IS_CALL;-- FAIL_IF(emit_const(compiler, TMP_REG1, 0));- src_r = TMP_REG1;- }- else {- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));- src_r = TMP_REG1;- }-- FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS));- if (jump)- jump->addr = compiler->size;- return push_inst(compiler, NOP, UNMOVABLE_INS);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));-- if (src & SLJIT_MEM) {- ADJUST_LOCAL_OFFSET(src, srcw);- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));- src = TMP_REG1;- }-- FAIL_IF(call_with_args(compiler, arg_types, &src));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- return sljit_emit_ijump(compiler, type, src, srcw);-}--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_s32 reg;- sljit_u32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;-- CHECK_ERROR();- CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));- ADJUST_LOCAL_OFFSET(dst, dstw);--#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 && (dst & SLJIT_MEM))- FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));-- type &= 0xff;- if (type < SLJIT_EQUAL_F64)- FAIL_IF(push_inst(compiler, BICC | get_cc(compiler, type) | 3, UNMOVABLE_INS));- else- FAIL_IF(push_inst(compiler, FBFCC | get_cc(compiler, type) | 3, UNMOVABLE_INS));-- 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) {- 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));--#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_s32 dst, sljit_sw dstw, sljit_sw init_value)-{- struct sljit_const *const_;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));- ADJUST_LOCAL_OFFSET(dst, dstw);-- const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));- PTR_FAIL_IF(!const_);- set_const(const_, compiler);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;- PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));- return const_;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- struct sljit_put_label *put_label;- sljit_s32 dst_r;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);-- put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));- PTR_FAIL_IF(!put_label);- set_put_label(put_label, compiler, 0);-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;- PTR_FAIL_IF(emit_const(compiler, dst_r, 0));-- if (dst & SLJIT_MEM)- PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));- return put_label;-}
src/c/pcre2/src/sljit/sljitNativeX86_32.c view
@@ -62,1345 +62,1607 @@ /* Both size flags cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); /* SSE2 and immediate is not possible. */- SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));- SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)- && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)- && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));-- size &= 0xf;- inst_size = size;-- if (flags & (EX86_PREF_F2 | EX86_PREF_F3))- inst_size++;- if (flags & EX86_PREF_66)- inst_size++;-- /* Calculate size of b. */- inst_size += 1; /* mod r/m byte. */- if (b & SLJIT_MEM) {- if (!(b & REG_MASK))- inst_size += sizeof(sljit_sw);- else if (immb != 0 && !(b & OFFS_REG_MASK)) {- /* Immediate operand. */- if (immb <= 127 && immb >= -128)- inst_size += sizeof(sljit_s8);- else- inst_size += sizeof(sljit_sw);- }- else if (reg_map[b & REG_MASK] == 5)- inst_size += sizeof(sljit_s8);-- if ((b & REG_MASK) == SLJIT_SP && !(b & OFFS_REG_MASK))- b |= TO_OFFS_REG(SLJIT_SP);-- if (b & OFFS_REG_MASK)- inst_size += 1; /* SIB byte. */- }-- /* Calculate size of a. */- if (a & SLJIT_IMM) {- if (flags & EX86_BIN_INS) {- if (imma <= 127 && imma >= -128) {- inst_size += 1;- flags |= EX86_BYTE_ARG;- } else- inst_size += 4;- }- else if (flags & EX86_SHIFT_INS) {- imma &= 0x1f;- if (imma != 1) {- inst_size ++;- flags |= EX86_BYTE_ARG;- }- } else if (flags & EX86_BYTE_ARG)- inst_size++;- else if (flags & EX86_HALF_ARG)- inst_size += sizeof(short);- else- inst_size += sizeof(sljit_sw);- }- else- SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);-- inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);- PTR_FAIL_IF(!inst);-- /* Encoding the byte. */- INC_SIZE(inst_size);- if (flags & EX86_PREF_F2)- *inst++ = 0xf2;- if (flags & EX86_PREF_F3)- *inst++ = 0xf3;- if (flags & EX86_PREF_66)- *inst++ = 0x66;-- buf_ptr = inst + size;-- /* Encode mod/rm byte. */- if (!(flags & EX86_SHIFT_INS)) {- if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))- *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;-- if (a & SLJIT_IMM)- *buf_ptr = 0;- else if (!(flags & EX86_SSE2_OP1))- *buf_ptr = U8(reg_map[a] << 3);- else- *buf_ptr = U8(a << 3);- }- else {- if (a & SLJIT_IMM) {- if (imma == 1)- *inst = GROUP_SHIFT_1;- else- *inst = GROUP_SHIFT_N;- } else- *inst = GROUP_SHIFT_CL;- *buf_ptr = 0;- }-- if (!(b & SLJIT_MEM)) {- *buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_map[b] : b));- buf_ptr++;- } else if (b & REG_MASK) {- reg_map_b = reg_map[b & REG_MASK];-- if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP) || reg_map_b == 5) {- if (immb != 0 || reg_map_b == 5) {- if (immb <= 127 && immb >= -128)- *buf_ptr |= 0x40;- else- *buf_ptr |= 0x80;- }-- if (!(b & OFFS_REG_MASK))- *buf_ptr++ |= reg_map_b;- else {- *buf_ptr++ |= 0x04;- *buf_ptr++ = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3));- }-- if (immb != 0 || reg_map_b == 5) {- if (immb <= 127 && immb >= -128)- *buf_ptr++ = U8(immb); /* 8 bit displacement. */- else {- sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */- buf_ptr += sizeof(sljit_sw);- }- }- }- else {- *buf_ptr++ |= 0x04;- *buf_ptr++ = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3) | (immb << 6));- }- }- else {- *buf_ptr++ |= 0x05;- sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */- buf_ptr += sizeof(sljit_sw);- }-- if (a & SLJIT_IMM) {- if (flags & EX86_BYTE_ARG)- *buf_ptr = U8(imma);- else if (flags & EX86_HALF_ARG)- sljit_unaligned_store_s16(buf_ptr, (sljit_s16)imma);- else if (!(flags & EX86_SHIFT_INS))- sljit_unaligned_store_sw(buf_ptr, imma);- }-- return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);-}--/* --------------------------------------------------------------------- */-/* Enter / return */-/* --------------------------------------------------------------------- */--static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset)-{- sljit_uw type = jump->flags >> TYPE_SHIFT;-- if (type == SLJIT_JUMP) {- *code_ptr++ = JMP_i32;- jump->addr++;- }- else if (type >= SLJIT_FAST_CALL) {- *code_ptr++ = CALL_i32;- jump->addr++;- }- else {- *code_ptr++ = GROUP_0F;- *code_ptr++ = get_jump_code(type);- jump->addr += 2;- }-- if (jump->flags & JUMP_LABEL)- jump->flags |= PATCH_MW;- else- sljit_unaligned_store_sw(code_ptr, (sljit_sw)(jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset));- code_ptr += 4;-- return code_ptr;-}--#define ENTER_R2_USED 0x00001-#define ENTER_R2_TO_S 0x00002-#define ENTER_R2_TO_R0 0x00004-#define ENTER_R1_TO_S 0x00008-#define ENTER_TMP_TO_R4 0x00010-#define ENTER_TMP_TO_S 0x00020--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 word_arg_count, saved_arg_count, float_arg_count;- sljit_s32 size, locals_offset, args_size, types, status;- sljit_u8 *inst;-#ifdef _WIN32- sljit_s32 r2_offset = -1;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- /* Emit ENDBR32 at function entry if needed. */- FAIL_IF(emit_endbranch(compiler));-- SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);-- arg_types >>= SLJIT_ARG_SHIFT;- types = arg_types;- word_arg_count = 0;- saved_arg_count = 0;- float_arg_count = 0;- args_size = SSIZE_OF(sw);- status = 0;- while (types) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- float_arg_count++;- FAIL_IF(emit_sse2_load(compiler, 0, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size));- args_size += SSIZE_OF(f64);- break;- case SLJIT_ARG_TYPE_F32:- float_arg_count++;- FAIL_IF(emit_sse2_load(compiler, 1, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size));- args_size += SSIZE_OF(f32);- break;- default:- word_arg_count++;-- if (!(types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- saved_arg_count++;- if (saved_arg_count == 4)- status |= ENTER_TMP_TO_S;- } else {- if (word_arg_count == 4)- status |= ENTER_TMP_TO_R4;-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (word_arg_count == 3)- status |= ENTER_R2_USED;-#endif- }--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (word_arg_count <= 2 && !(options & SLJIT_ENTER_CDECL))- break;-#endif-- args_size += SSIZE_OF(sw);- break;- }- types >>= SLJIT_ARG_SHIFT;- }-- args_size -= SSIZE_OF(sw);- compiler->args_size = args_size;-- /* [esp+0] for saving temporaries and function calls. */- locals_offset = 2 * SSIZE_OF(sw);--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if ((options & SLJIT_ENTER_CDECL) && scratches >= 3)- locals_offset = 4 * SSIZE_OF(sw);-#else- if (scratches >= 3)- locals_offset = 4 * SSIZE_OF(sw);-#endif-- compiler->scratches_offset = locals_offset;-- if (scratches > 3)- locals_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * SSIZE_OF(sw);-- if (saveds > 3)- locals_offset += (saveds - 3) * SSIZE_OF(sw);-- compiler->locals_offset = locals_offset;-- size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3);- inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(size + 1));- FAIL_IF(!inst);-- INC_SIZE((sljit_uw)size);- PUSH_REG(reg_map[TMP_REG1]);- if (saveds > 2 || scratches > 9)- PUSH_REG(reg_map[SLJIT_S2]);- if (saveds > 1 || scratches > 10)- PUSH_REG(reg_map[SLJIT_S1]);- if (saveds > 0 || scratches > 11)- PUSH_REG(reg_map[SLJIT_S0]);-- size *= SSIZE_OF(sw);-- if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S))- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), args_size + size);-- size += SSIZE_OF(sw);--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (!(options & SLJIT_ENTER_CDECL))- size += args_size;-#endif-- local_size = ((locals_offset + local_size + size + 0xf) & ~0xf) - size;- compiler->local_size = local_size;--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (!(options & SLJIT_ENTER_CDECL))- size -= args_size;-#endif-- word_arg_count = 0;- saved_arg_count = 0;- args_size = size;- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- args_size += SSIZE_OF(f64);- break;- case SLJIT_ARG_TYPE_F32:- args_size += SSIZE_OF(f32);- break;- default:- word_arg_count++;--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (!(options & SLJIT_ENTER_CDECL) && word_arg_count <= 2) {- if (word_arg_count == 1) {- if (status & ENTER_R2_USED) {- EMIT_MOV(compiler, (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? SLJIT_R0 : SLJIT_S0, 0, SLJIT_R2, 0);- } else if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- status |= ENTER_R2_TO_S;- saved_arg_count++;- } else- status |= ENTER_R2_TO_R0;- } else if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {- status |= ENTER_R1_TO_S;- saved_arg_count++;- }- break;- }-#endif- if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {- SLJIT_ASSERT(word_arg_count <= 3 || (status & ENTER_TMP_TO_R4));-- if (word_arg_count <= 3) {-#ifdef _WIN32- if (word_arg_count == 3 && local_size > 4 * 4096)- r2_offset = local_size + args_size;- else-#endif- EMIT_MOV(compiler, word_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size);- }- } else {- SLJIT_ASSERT(saved_arg_count <= 3 || (status & ENTER_TMP_TO_S));-- if (saved_arg_count <= 3)- EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size);- saved_arg_count++;- }- args_size += SSIZE_OF(sw);- break;- }- arg_types >>= SLJIT_ARG_SHIFT;- }--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (!(options & SLJIT_ENTER_CDECL)) {- if (status & ENTER_R2_TO_R0)- EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_R2, 0);-- saved_arg_count = 0;- if (status & ENTER_R2_TO_S) {- EMIT_MOV(compiler, SLJIT_S0, 0, SLJIT_R2, 0);- saved_arg_count++;- }-- if (status & ENTER_R1_TO_S)- EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, SLJIT_R1, 0);- }-#endif-- SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0);--#ifdef _WIN32- SLJIT_ASSERT(r2_offset == -1 || local_size > 4 * 4096);-- if (local_size > 4096) {- if (local_size <= 4 * 4096) {- BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096);-- if (local_size > 2 * 4096)- BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);- if (local_size > 3 * 4096)- BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);- }- else {- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_IMM, local_size >> 12);-- BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096);- BINARY_IMM32(SUB, 4096, SLJIT_SP, 0);-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);- FAIL_IF(!inst);-- INC_SIZE(2);- inst[0] = LOOP_i8;- inst[1] = (sljit_u8)-16;- local_size &= 0xfff;- }- }-- if (local_size > 0) {- BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -local_size);- BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);- }-- if (r2_offset != -1)- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), r2_offset);--#else /* !_WIN32 */-- SLJIT_ASSERT(local_size > 0);-- BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);--#endif /* _WIN32 */-- if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S)) {- size = (status & ENTER_TMP_TO_R4) ? compiler->scratches_offset : compiler->locals_offset - SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), size, TMP_REG1, 0);- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)-{- sljit_s32 args_size, locals_offset;-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- sljit_s32 word_arg_count = 0;-#endif-- CHECK_ERROR();- CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));- set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);-- arg_types >>= SLJIT_ARG_SHIFT;- args_size = 0;- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- args_size += SSIZE_OF(f64);- break;- case SLJIT_ARG_TYPE_F32:- args_size += SSIZE_OF(f32);- break;- default:-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (word_arg_count >= 2)- args_size += SSIZE_OF(sw);- word_arg_count++;-#else- args_size += SSIZE_OF(sw);-#endif- break;- }- arg_types >>= SLJIT_ARG_SHIFT;- }-- compiler->args_size = args_size;-- /* [esp+0] for saving temporaries and function calls. */- locals_offset = 2 * SSIZE_OF(sw);--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if ((options & SLJIT_ENTER_CDECL) && scratches >= 3)- locals_offset = 4 * SSIZE_OF(sw);-#else- if (scratches >= 3)- locals_offset = 4 * SSIZE_OF(sw);-#endif-- compiler->scratches_offset = locals_offset;-- if (scratches > 3)- locals_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * SSIZE_OF(sw);-- if (saveds > 3)- locals_offset += (saveds - 3) * SSIZE_OF(sw);-- compiler->locals_offset = locals_offset;-- saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * SSIZE_OF(sw);--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (!(options & SLJIT_ENTER_CDECL))- saveds += args_size;-#endif-- compiler->local_size = ((locals_offset + local_size + saveds + 0xf) & ~0xf) - saveds;- return SLJIT_SUCCESS;-}--static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)-{- sljit_uw size;- sljit_u8 *inst;-- size = (sljit_uw)(1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) +- (compiler->saveds <= 3 ? compiler->saveds : 3));- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);- FAIL_IF(!inst);-- INC_SIZE(size);-- if (compiler->saveds > 0 || compiler->scratches > 11)- POP_REG(reg_map[SLJIT_S0]);- if (compiler->saveds > 1 || compiler->scratches > 10)- POP_REG(reg_map[SLJIT_S1]);- if (compiler->saveds > 2 || compiler->scratches > 9)- POP_REG(reg_map[SLJIT_S2]);- POP_REG(reg_map[TMP_REG1]);-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)-{- sljit_uw size;- sljit_u8 *inst;-- CHECK_ERROR();- CHECK(check_sljit_emit_return_void(compiler));-- SLJIT_ASSERT(compiler->args_size >= 0);- SLJIT_ASSERT(compiler->local_size > 0);-- BINARY_IMM32(ADD, compiler->local_size, SLJIT_SP, 0);-- FAIL_IF(emit_stack_frame_release(compiler));-- size = 1;-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (compiler->args_size > 0 && !(compiler->options & SLJIT_ENTER_CDECL))- size = 3;-#endif- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);- FAIL_IF(!inst);-- INC_SIZE(size);--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (compiler->args_size > 0 && !(compiler->options & SLJIT_ENTER_CDECL)) {- RET_I16(U8(compiler->args_size));- return SLJIT_SUCCESS;- }-#endif-- RET();- return SLJIT_SUCCESS;-}--/* --------------------------------------------------------------------- */-/* Call / return instructions */-/* --------------------------------------------------------------------- */--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)--static sljit_sw c_fast_call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)-{- sljit_sw stack_size = 0;- sljit_s32 word_arg_count = 0;-- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- stack_size += SSIZE_OF(f64);- break;- case SLJIT_ARG_TYPE_F32:- stack_size += SSIZE_OF(f32);- break;- default:- word_arg_count++;- if (word_arg_count > 2)- stack_size += SSIZE_OF(sw);- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- if (word_arg_count_ptr)- *word_arg_count_ptr = word_arg_count;-- return stack_size;-}--static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler,- sljit_s32 arg_types, sljit_sw stack_size, sljit_s32 word_arg_count, sljit_s32 swap_args)-{- sljit_u8 *inst;- sljit_s32 float_arg_count;-- if (stack_size == SSIZE_OF(sw) && word_arg_count == 3) {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- PUSH_REG(reg_map[SLJIT_R2]);- }- else if (stack_size > 0) {- if (word_arg_count >= 4)- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->scratches_offset);-- BINARY_IMM32(SUB, stack_size, SLJIT_SP, 0);-- stack_size = 0;- arg_types >>= SLJIT_ARG_SHIFT;- word_arg_count = 0;- float_arg_count = 0;- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- float_arg_count++;- FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));- stack_size += SSIZE_OF(f64);- break;- case SLJIT_ARG_TYPE_F32:- float_arg_count++;- FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));- stack_size += SSIZE_OF(f32);- break;- default:- word_arg_count++;- if (word_arg_count == 3) {- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, SLJIT_R2, 0);- stack_size += SSIZE_OF(sw);- }- else if (word_arg_count == 4) {- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, TMP_REG1, 0);- stack_size += SSIZE_OF(sw);- }- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }- }-- if (word_arg_count > 0) {- if (swap_args) {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);-- *inst++ = U8(XCHG_EAX_r | reg_map[SLJIT_R2]);- }- else {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);- FAIL_IF(!inst);- INC_SIZE(2);-- *inst++ = MOV_r_rm;- *inst++ = U8(MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0]);- }- }-- return SLJIT_SUCCESS;-}--#endif--static sljit_s32 cdecl_call_get_stack_size(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)-{- sljit_sw stack_size = 0;- sljit_s32 word_arg_count = 0;-- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- stack_size += SSIZE_OF(f64);- break;- case SLJIT_ARG_TYPE_F32:- stack_size += SSIZE_OF(f32);- break;- default:- word_arg_count++;- stack_size += SSIZE_OF(sw);- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- if (word_arg_count_ptr)- *word_arg_count_ptr = word_arg_count;-- if (stack_size <= compiler->scratches_offset)- return 0;-- return ((stack_size - compiler->scratches_offset + 0xf) & ~0xf);-}--static sljit_s32 cdecl_call_with_args(struct sljit_compiler *compiler,- sljit_s32 arg_types, sljit_sw stack_size, sljit_s32 word_arg_count)-{- sljit_s32 float_arg_count = 0;- sljit_u8 *inst;-- if (word_arg_count >= 4)- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->scratches_offset);-- if (stack_size > 0)- BINARY_IMM32(SUB, stack_size, SLJIT_SP, 0);-- stack_size = 0;- word_arg_count = 0;- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types) {- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- float_arg_count++;- FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));- stack_size += SSIZE_OF(f64);- break;- case SLJIT_ARG_TYPE_F32:- float_arg_count++;- FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));- stack_size += SSIZE_OF(f32);- break;- default:- word_arg_count++;- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, (word_arg_count >= 4) ? TMP_REG1 : word_arg_count, 0);- stack_size += SSIZE_OF(sw);- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--static sljit_s32 post_call_with_args(struct sljit_compiler *compiler,- sljit_s32 arg_types, sljit_s32 stack_size)-{- sljit_u8 *inst;- sljit_s32 single;-- if (stack_size > 0)- BINARY_IMM32(ADD, stack_size, SLJIT_SP, 0);-- if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64)- return SLJIT_SUCCESS;-- single = ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32);-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);- FAIL_IF(!inst);- INC_SIZE(3);- inst[0] = single ? FSTPS : FSTPD;- inst[1] = (0x03 << 3) | 0x04;- inst[2] = (0x04 << 3) | reg_map[SLJIT_SP];-- return emit_sse2_load(compiler, single, SLJIT_FR0, SLJIT_MEM1(SLJIT_SP), 0);-}--static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler,- sljit_s32 *extra_space, sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{- sljit_sw args_size, prev_args_size, saved_regs_size;- sljit_sw types, word_arg_count, float_arg_count;- sljit_sw stack_size, prev_stack_size, min_size, offset;- sljit_sw word_arg4_offset;- sljit_u8 r2_offset = 0;-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- sljit_u8 fast_call = (*extra_space & 0xff) == SLJIT_CALL;-#endif- sljit_u8* inst;-- ADJUST_LOCAL_OFFSET(src, srcw);- CHECK_EXTRA_REGS(src, srcw, (void)0);-- saved_regs_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0)- + (compiler->saveds <= 3 ? compiler->saveds : 3)) * SSIZE_OF(sw);-- word_arg_count = 0;- float_arg_count = 0;- arg_types >>= SLJIT_ARG_SHIFT;- types = 0;- args_size = 0;-- while (arg_types != 0) {- types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);-- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- args_size += SSIZE_OF(f64);- float_arg_count++;- break;- case SLJIT_ARG_TYPE_F32:- args_size += SSIZE_OF(f32);- float_arg_count++;- break;- default:- word_arg_count++;-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (!fast_call || word_arg_count > 2)- args_size += SSIZE_OF(sw);-#else- args_size += SSIZE_OF(sw);-#endif- break;- }- arg_types >>= SLJIT_ARG_SHIFT;- }-- if (args_size <= compiler->args_size-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- && (!(compiler->options & SLJIT_ENTER_CDECL) || args_size == 0 || !fast_call)-#endif /* SLJIT_X86_32_FASTCALL */- && 1) {-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- *extra_space = fast_call ? 0 : args_size;- prev_args_size = compiler->args_size;- stack_size = prev_args_size + SSIZE_OF(sw) + saved_regs_size;-#else /* !SLJIT_X86_32_FASTCALL */- *extra_space = 0;- stack_size = args_size + SSIZE_OF(sw) + saved_regs_size;-#endif /* SLJIT_X86_32_FASTCALL */-- offset = stack_size + compiler->local_size;-- if (!(src & SLJIT_IMM) && src != SLJIT_R0) {- if (word_arg_count >= 1) {- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);- r2_offset = sizeof(sljit_sw);- }- EMIT_MOV(compiler, SLJIT_R0, 0, src, srcw);- }--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (!(compiler->options & SLJIT_ENTER_CDECL)) {- if (!fast_call)- offset -= SSIZE_OF(sw);-- if (word_arg_count >= 3) {- word_arg4_offset = SSIZE_OF(sw);-- if (word_arg_count + float_arg_count >= 4) {- word_arg4_offset = SSIZE_OF(sw) + SSIZE_OF(sw);- if ((types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)- word_arg4_offset = SSIZE_OF(sw) + SSIZE_OF(f64);- }-- /* In cdecl mode, at least one more word value must- * be present on the stack before the return address. */- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset - word_arg4_offset, SLJIT_R2, 0);- }-- if (fast_call) {- if (args_size < prev_args_size) {- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset - prev_args_size - SSIZE_OF(sw));- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset - args_size - SSIZE_OF(sw), SLJIT_R2, 0);- }- } else if (prev_args_size > 0) {- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset - prev_args_size);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);- }- }-#endif /* SLJIT_X86_32_FASTCALL */-- while (types != 0) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- offset -= SSIZE_OF(f64);- FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));- float_arg_count--;- break;- case SLJIT_ARG_TYPE_F32:- offset -= SSIZE_OF(f32);- FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));- float_arg_count--;- break;- default:- switch (word_arg_count) {- case 1:-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (fast_call) {- EMIT_MOV(compiler, SLJIT_R2, 0, r2_offset != 0 ? SLJIT_MEM1(SLJIT_SP) : SLJIT_R0, 0);- break;- }-#endif- offset -= SSIZE_OF(sw);- if (r2_offset != 0) {- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);- } else- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0);- break;- case 2:-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (fast_call)- break;-#endif- offset -= SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0);- break;- case 3:- offset -= SSIZE_OF(sw);- break;- case 4:- offset -= SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), compiler->scratches_offset);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);- break;- }- word_arg_count--;- break;- }- types >>= SLJIT_ARG_SHIFT;- }-- BINARY_IMM32(ADD, compiler->local_size, SLJIT_SP, 0);- FAIL_IF(emit_stack_frame_release(compiler));--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (args_size < prev_args_size)- BINARY_IMM32(ADD, prev_args_size - args_size, SLJIT_SP, 0);-#endif-- return SLJIT_SUCCESS;- }-- stack_size = args_size + SSIZE_OF(sw);-- if (word_arg_count >= 1 && !(src & SLJIT_IMM) && src != SLJIT_R0) {- r2_offset = SSIZE_OF(sw);- stack_size += SSIZE_OF(sw);- }-- if (word_arg_count >= 3)- stack_size += SSIZE_OF(sw);-- prev_args_size = 0;-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (!(compiler->options & SLJIT_ENTER_CDECL))- prev_args_size = compiler->args_size;-#endif-- prev_stack_size = prev_args_size + SSIZE_OF(sw) + saved_regs_size;- min_size = prev_stack_size + compiler->local_size;-- word_arg4_offset = compiler->scratches_offset;-- if (stack_size > min_size) {- BINARY_IMM32(SUB, stack_size - min_size, SLJIT_SP, 0);- if (src == SLJIT_MEM1(SLJIT_SP))- srcw += stack_size - min_size;- word_arg4_offset += stack_size - min_size;- }- else- stack_size = min_size;-- if (word_arg_count >= 3) {- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), r2_offset, SLJIT_R2, 0);-- if (word_arg_count >= 4)- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), word_arg4_offset);- }-- if (!(src & SLJIT_IMM) && src != SLJIT_R0) {- if (word_arg_count >= 1) {- SLJIT_ASSERT(r2_offset == sizeof(sljit_sw));- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);- }- EMIT_MOV(compiler, SLJIT_R0, 0, src, srcw);- }-- /* Restore saved registers. */- offset = stack_size - prev_args_size - 2 * SSIZE_OF(sw);- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), offset);-- if (compiler->saveds > 2 || compiler->scratches > 9) {- offset -= SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), offset);- }- if (compiler->saveds > 1 || compiler->scratches > 10) {- offset -= SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_SP), offset);- }- if (compiler->saveds > 0 || compiler->scratches > 11) {- offset -= SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), offset);- }-- /* Copy fourth argument and return address. */-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (fast_call) {- offset = stack_size;- *extra_space = 0;-- if (word_arg_count >= 4 && prev_args_size == 0) {- offset -= SSIZE_OF(sw);- inst = emit_x86_instruction(compiler, 1, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset);- FAIL_IF(!inst);- *inst = XCHG_r_rm;-- SLJIT_ASSERT(args_size != prev_args_size);- } else {- if (word_arg_count >= 4) {- offset -= SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);- }-- if (args_size != prev_args_size)- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), stack_size - prev_args_size - SSIZE_OF(sw));- }-- if (args_size != prev_args_size)- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size - args_size - SSIZE_OF(sw), SLJIT_R2, 0);- } else {-#endif /* SLJIT_X86_32_FASTCALL */- offset = stack_size - SSIZE_OF(sw);- *extra_space = args_size;-- if (word_arg_count >= 4 && prev_args_size == SSIZE_OF(sw)) {- offset -= SSIZE_OF(sw);- inst = emit_x86_instruction(compiler, 1, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset);- FAIL_IF(!inst);- *inst = XCHG_r_rm;-- SLJIT_ASSERT(prev_args_size > 0);- } else {- if (word_arg_count >= 4) {- offset -= SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);- }-- if (prev_args_size > 0)- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), stack_size - prev_args_size - SSIZE_OF(sw));- }-- /* Copy return address. */- if (prev_args_size > 0)- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size - SSIZE_OF(sw), SLJIT_R2, 0);-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- }-#endif /* SLJIT_X86_32_FASTCALL */-- while (types != 0) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- offset -= SSIZE_OF(f64);- FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));- float_arg_count--;- break;- case SLJIT_ARG_TYPE_F32:- offset -= SSIZE_OF(f32);- FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));- float_arg_count--;- break;- default:- switch (word_arg_count) {- case 1:-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (fast_call) {- EMIT_MOV(compiler, SLJIT_R2, 0, r2_offset != 0 ? SLJIT_MEM1(SLJIT_SP) : SLJIT_R0, 0);- break;- }-#endif- offset -= SSIZE_OF(sw);- if (r2_offset != 0) {- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);- } else- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0);- break;- case 2:-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if (fast_call)- break;-#endif- offset -= SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0);- break;- case 3:- offset -= SSIZE_OF(sw);- EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), r2_offset);- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);- break;- }- word_arg_count--;- break;- }- types >>= SLJIT_ARG_SHIFT;- }--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- /* Skip return address. */- if (fast_call)- offset -= SSIZE_OF(sw);-#endif-- SLJIT_ASSERT(offset >= 0);-- if (offset == 0)- return SLJIT_SUCCESS;-- BINARY_IMM32(ADD, offset, SLJIT_SP, 0);- return SLJIT_SUCCESS;-}--static sljit_s32 emit_tail_call_end(struct sljit_compiler *compiler, sljit_s32 extra_space)-{- /* Called when stack consumption cannot be reduced to 0. */- sljit_u8 *inst;-- BINARY_IMM32(ADD, extra_space, SLJIT_SP, 0);-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- RET();-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types)-{- struct sljit_jump *jump;- sljit_sw stack_size = 0;- sljit_s32 word_arg_count;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));-- if (type & SLJIT_CALL_RETURN) {- stack_size = type;- PTR_FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, SLJIT_IMM, 0));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- if (stack_size == 0) {- type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);- return sljit_emit_jump(compiler, type);- }-- jump = sljit_emit_jump(compiler, type);- PTR_FAIL_IF(jump == NULL);-- PTR_FAIL_IF(emit_tail_call_end(compiler, stack_size));- return jump;- }--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- if ((type & 0xff) == SLJIT_CALL) {- stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count);- PTR_FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, 0));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- jump = sljit_emit_jump(compiler, type);- PTR_FAIL_IF(jump == NULL);-- PTR_FAIL_IF(post_call_with_args(compiler, arg_types, 0));- return jump;- }-#endif-- stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count);- PTR_FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count));--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- jump = sljit_emit_jump(compiler, type);- PTR_FAIL_IF(jump == NULL);-- PTR_FAIL_IF(post_call_with_args(compiler, arg_types, stack_size));- return jump;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,- sljit_s32 arg_types,- sljit_s32 src, sljit_sw srcw)-{- sljit_sw stack_size = 0;- sljit_s32 word_arg_count;-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- sljit_s32 swap_args;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));-- if (type & SLJIT_CALL_RETURN) {- stack_size = type;- FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, src, srcw));-- if (!(src & SLJIT_IMM)) {- src = SLJIT_R0;- srcw = 0;- }--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif-- if (stack_size == 0)- return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);-- FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));- return emit_tail_call_end(compiler, stack_size);- }--#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- SLJIT_ASSERT(reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R2] == 1 && SLJIT_R0 == 1 && SLJIT_R2 == 3);-- if ((type & 0xff) == SLJIT_CALL) {- stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count);- swap_args = 0;-- if (word_arg_count > 0) {- if ((src & REG_MASK) == SLJIT_R2 || OFFS_REG(src) == SLJIT_R2) {- swap_args = 1;- if (((src & REG_MASK) | 0x2) == SLJIT_R2)- src ^= 0x2;- if ((OFFS_REG(src) | 0x2) == SLJIT_R2)- src ^= TO_OFFS_REG(0x2);- }- }-- FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, swap_args));-- compiler->scratches_offset += stack_size;- compiler->locals_offset += stack_size;--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif- FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));-- compiler->scratches_offset -= stack_size;- compiler->locals_offset -= stack_size;-- return post_call_with_args(compiler, arg_types, 0);- }-#endif-- stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count);- FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count));-- compiler->scratches_offset += stack_size;- compiler->locals_offset += stack_size;--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif- FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));-- compiler->scratches_offset -= stack_size;- compiler->locals_offset -= stack_size;-- return post_call_with_args(compiler, arg_types, stack_size);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- sljit_u8 *inst;-- CHECK_ERROR();- CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);-- CHECK_EXTRA_REGS(dst, dstw, (void)0);-- if (FAST_IS_REG(dst)) {- /* Unused dest is possible here. */- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);-- INC_SIZE(1);- POP_REG(reg_map[dst]);- return SLJIT_SUCCESS;- }-- /* Memory. */- inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);- FAIL_IF(!inst);- *inst++ = POP_rm;- return SLJIT_SUCCESS;-}--static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)-{- sljit_u8 *inst;-- CHECK_EXTRA_REGS(src, srcw, (void)0);-- if (FAST_IS_REG(src)) {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);- FAIL_IF(!inst);-- INC_SIZE(1 + 1);- PUSH_REG(reg_map[src]);- }- else {- inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);- FAIL_IF(!inst);- *inst++ = GROUP_FF;- *inst |= PUSH_rm;-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- }-- RET();+ SLJIT_ASSERT(a != SLJIT_IMM || !(flags & EX86_SSE2));+ SLJIT_ASSERT(((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))+ & ((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);+ SLJIT_ASSERT((flags & (EX86_VEX_EXT | EX86_REX)) != EX86_VEX_EXT);++ size &= 0xf;+ /* The mod r/m byte is always present. */+ inst_size = size + 1;++ if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))+ inst_size++;++ /* Calculate size of b. */+ if (b & SLJIT_MEM) {+ if (!(b & REG_MASK))+ inst_size += sizeof(sljit_sw);+ else {+ if (immb != 0 && !(b & OFFS_REG_MASK)) {+ /* Immediate operand. */+ if (immb <= 127 && immb >= -128)+ inst_size += sizeof(sljit_s8);+ else+ inst_size += sizeof(sljit_sw);+ } else if (reg_map[b & REG_MASK] == 5) {+ /* Swap registers if possible. */+ if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_map[OFFS_REG(b)] != 5)+ b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK);+ else+ inst_size += sizeof(sljit_s8);+ }++ if (reg_map[b & REG_MASK] == 4 && !(b & OFFS_REG_MASK))+ b |= TO_OFFS_REG(SLJIT_SP);++ if (b & OFFS_REG_MASK)+ inst_size += 1; /* SIB byte. */+ }+ }++ /* Calculate size of a. */+ if (a == SLJIT_IMM) {+ if (flags & EX86_BIN_INS) {+ if (imma <= 127 && imma >= -128) {+ inst_size += 1;+ flags |= EX86_BYTE_ARG;+ } else+ inst_size += 4;+ } else if (flags & EX86_SHIFT_INS) {+ SLJIT_ASSERT(imma <= 0x1f);+ if (imma != 1) {+ inst_size++;+ flags |= EX86_BYTE_ARG;+ }+ } else if (flags & EX86_BYTE_ARG)+ inst_size++;+ else if (flags & EX86_HALF_ARG)+ inst_size += sizeof(short);+ else+ inst_size += sizeof(sljit_sw);+ } else+ SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);+ PTR_FAIL_IF(!inst);++ /* Encoding the byte. */+ INC_SIZE(inst_size);+ if (flags & EX86_PREF_F2)+ *inst++ = 0xf2;+ else if (flags & EX86_PREF_F3)+ *inst++ = 0xf3;+ else if (flags & EX86_PREF_66)+ *inst++ = 0x66;++ buf_ptr = inst + size;++ /* Encode mod/rm byte. */+ if (!(flags & EX86_SHIFT_INS)) {+ if ((flags & EX86_BIN_INS) && a == SLJIT_IMM)+ *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;++ if (a == SLJIT_IMM)+ *buf_ptr = 0;+ else if (!(flags & EX86_SSE2_OP1))+ *buf_ptr = U8(reg_map[a] << 3);+ else+ *buf_ptr = U8(freg_map[a] << 3);+ } else {+ if (a == SLJIT_IMM) {+ if (imma == 1)+ *inst = GROUP_SHIFT_1;+ else+ *inst = GROUP_SHIFT_N;+ } else+ *inst = GROUP_SHIFT_CL;+ *buf_ptr = 0;+ }++ if (!(b & SLJIT_MEM)) {+ *buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_map[b] : freg_map[b]));+ buf_ptr++;+ } else if (b & REG_MASK) {+ reg_map_b = reg_map[b & REG_MASK];++ if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {+ if (immb != 0 || reg_map_b == 5) {+ if (immb <= 127 && immb >= -128)+ *buf_ptr |= 0x40;+ else+ *buf_ptr |= 0x80;+ }++ if (!(b & OFFS_REG_MASK))+ *buf_ptr++ |= reg_map_b;+ else {+ buf_ptr[0] |= 0x04;+ buf_ptr[1] = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3));+ buf_ptr += 2;+ }++ if (immb != 0 || reg_map_b == 5) {+ if (immb <= 127 && immb >= -128)+ *buf_ptr++ = U8(immb); /* 8 bit displacement. */+ else {+ sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */+ buf_ptr += sizeof(sljit_sw);+ }+ }+ } else {+ if (reg_map_b == 5)+ *buf_ptr |= 0x40;++ buf_ptr[0] |= 0x04;+ buf_ptr[1] = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3) | (immb << 6));+ buf_ptr += 2;++ if (reg_map_b == 5)+ *buf_ptr++ = 0;+ }+ } else {+ *buf_ptr++ |= 0x05;+ sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */+ buf_ptr += sizeof(sljit_sw);+ }++ if (a == SLJIT_IMM) {+ if (flags & EX86_BYTE_ARG)+ *buf_ptr = U8(imma);+ else if (flags & EX86_HALF_ARG)+ sljit_unaligned_store_s16(buf_ptr, (sljit_s16)imma);+ else if (!(flags & EX86_SHIFT_INS))+ sljit_unaligned_store_sw(buf_ptr, imma);+ }++ return inst;+}++static sljit_s32 emit_vex_instruction(struct sljit_compiler *compiler, sljit_uw op,+ /* The first and second register operand. */+ sljit_s32 a, sljit_s32 v,+ /* The general operand (not immediate). */+ sljit_s32 b, sljit_sw immb)+{+ sljit_u8 *inst;+ sljit_u8 vex = 0;+ sljit_u8 vex_m = 0;+ sljit_uw size;++ SLJIT_ASSERT(((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))+ & ((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);++ if (op & VEX_OP_0F38)+ vex_m = 0x2;+ else if (op & VEX_OP_0F3A)+ vex_m = 0x3;++ if (op & VEX_W) {+ if (vex_m == 0)+ vex_m = 0x1;++ vex |= 0x80;+ }++ if (op & EX86_PREF_66)+ vex |= 0x1;+ else if (op & EX86_PREF_F2)+ vex |= 0x3;+ else if (op & EX86_PREF_F3)+ vex |= 0x2;++ op &= ~(EX86_PREF_66 | EX86_PREF_F2 | EX86_PREF_F3);++ if (op & VEX_256)+ vex |= 0x4;++ vex = U8(vex | ((((op & VEX_SSE2_OPV) ? freg_map[v] : reg_map[v]) ^ 0xf) << 3));++ size = op & ~(sljit_uw)0xff;+ size |= (vex_m == 0) ? 3 : 4;++ inst = emit_x86_instruction(compiler, size, a, 0, b, immb);+ FAIL_IF(!inst);++ if (vex_m == 0) {+ inst[0] = 0xc5;+ inst[1] = U8(vex | 0x80);+ inst[2] = U8(op);+ return SLJIT_SUCCESS;+ }++ inst[0] = 0xc4;+ inst[1] = U8(vex_m | 0xe0);+ inst[2] = vex;+ inst[3] = U8(op);+ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Enter / return */+/* --------------------------------------------------------------------- */++static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset)+{+ sljit_uw type = jump->flags >> TYPE_SHIFT;++ if (type == SLJIT_JUMP) {+ *code_ptr++ = JMP_i32;+ } else if (type >= SLJIT_FAST_CALL) {+ *code_ptr++ = CALL_i32;+ } else {+ *code_ptr++ = GROUP_0F;+ *code_ptr++ = get_jump_code(type);+ }++ jump->addr = (sljit_uw)code_ptr;++ if (jump->flags & JUMP_ADDR)+ sljit_unaligned_store_sw(code_ptr, (sljit_sw)(jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset));+ else+ jump->flags |= PATCH_MW;+ code_ptr += 4;++ return code_ptr;+}++#define ENTER_TMP_TO_R4 0x00001+#define ENTER_TMP_TO_S 0x00002++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 word_arg_count, saved_arg_count, float_arg_count;+ sljit_s32 size, args_size, types, status;+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(options);+ sljit_u8 *inst;+#ifdef _WIN32+ sljit_s32 r2_offset = -1;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ /* Emit ENDBR32 at function entry if needed. */+ FAIL_IF(emit_endbranch(compiler));++ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);++ arg_types >>= SLJIT_ARG_SHIFT;+ word_arg_count = 0;+ status = 0;++ if (options & SLJIT_ENTER_REG_ARG) {+ args_size = 3 * SSIZE_OF(sw);++ while (arg_types) {+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {+ word_arg_count++;+ if (word_arg_count >= 4)+ status |= ENTER_TMP_TO_R4;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ compiler->args_size = 0;+ } else {+ types = arg_types;+ saved_arg_count = 0;+ float_arg_count = 0;+ args_size = SSIZE_OF(sw);+ while (types) {+ switch (types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ float_arg_count++;+ FAIL_IF(emit_sse2_load(compiler, 0, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size));+ args_size += SSIZE_OF(f64);+ break;+ case SLJIT_ARG_TYPE_F32:+ float_arg_count++;+ FAIL_IF(emit_sse2_load(compiler, 1, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size));+ args_size += SSIZE_OF(f32);+ break;+ default:+ word_arg_count++;++ if (!(types & SLJIT_ARG_TYPE_SCRATCH_REG))+ saved_arg_count++;++ if (word_arg_count == 4) {+ if (types & SLJIT_ARG_TYPE_SCRATCH_REG) {+ status |= ENTER_TMP_TO_R4;+ arg_types &= ~(SLJIT_ARG_FULL_MASK << 3 * SLJIT_ARG_SHIFT);+ } else if (saved_arg_count == 4) {+ status |= ENTER_TMP_TO_S;+ arg_types &= ~(SLJIT_ARG_FULL_MASK << 3 * SLJIT_ARG_SHIFT);+ }+ }++ args_size += SSIZE_OF(sw);+ break;+ }+ types >>= SLJIT_ARG_SHIFT;+ }++ args_size -= SSIZE_OF(sw);+ compiler->args_size = args_size;+ }++ size = (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - kept_saveds_count;+ if (!(options & SLJIT_ENTER_REG_ARG))+ size++;++ if (size != 0) {+ inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(size + 1));+ FAIL_IF(!inst);++ INC_SIZE((sljit_uw)size);++ if (!(options & SLJIT_ENTER_REG_ARG))+ PUSH_REG(reg_map[TMP_REG1]);++ if ((saveds > 2 && kept_saveds_count <= 2) || scratches > 9)+ PUSH_REG(reg_map[SLJIT_S2]);+ if ((saveds > 1 && kept_saveds_count <= 1) || scratches > 10)+ PUSH_REG(reg_map[SLJIT_S1]);+ if ((saveds > 0 && kept_saveds_count == 0) || scratches > 11)+ PUSH_REG(reg_map[SLJIT_S0]);++ size *= SSIZE_OF(sw);+ }++ if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S))+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), args_size + size);++ size += SSIZE_OF(sw);++ local_size = ((SLJIT_LOCALS_OFFSET_BASE + local_size + size + 0xf) & ~0xf) - size;+ compiler->local_size = local_size;++ word_arg_count = 0;+ saved_arg_count = 0;+ args_size = size;+ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ args_size += SSIZE_OF(f64);+ break;+ case SLJIT_ARG_TYPE_F32:+ args_size += SSIZE_OF(f32);+ break;+ default:+ word_arg_count++;+ SLJIT_ASSERT(word_arg_count <= 3 || (word_arg_count == 4 && !(status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S))));++ if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {+#ifdef _WIN32+ if (word_arg_count == 3 && local_size > 4 * 4096)+ r2_offset = local_size + args_size;+ else+#endif+ EMIT_MOV(compiler, word_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size);++ } else {+ EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size);+ saved_arg_count++;+ }++ args_size += SSIZE_OF(sw);+ break;+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0);++#ifdef _WIN32+ SLJIT_ASSERT(r2_offset == -1 || local_size > 4 * 4096);++ if (local_size > 4096) {+ if (local_size <= 4 * 4096) {+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096);++ if (local_size > 2 * 4096)+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);+ if (local_size > 3 * 4096)+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);+ }+ else {+ if (options & SLJIT_ENTER_REG_ARG) {+ SLJIT_ASSERT(r2_offset == -1);++ inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(1 + 1));+ FAIL_IF(!inst);+ INC_SIZE(1);+ PUSH_REG(reg_map[SLJIT_R2]);++ local_size -= SSIZE_OF(sw);+ r2_offset = local_size;+ }++ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_IMM, local_size >> 12);++ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096);+ BINARY_IMM32(SUB, 4096, SLJIT_SP, 0);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);++ INC_SIZE(2);+ inst[0] = LOOP_i8;+ inst[1] = (sljit_u8)-16;+ local_size &= 0xfff;+ }+ }++ if (local_size > 0) {+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -local_size);+ BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);+ }++ if (r2_offset != -1)+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), r2_offset);++#else /* !_WIN32 */++ SLJIT_ASSERT(local_size > 0);++ BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);++#endif /* _WIN32 */++ size = SLJIT_LOCALS_OFFSET_BASE - SSIZE_OF(sw);+ kept_saveds_count = SLJIT_R3 - kept_saveds_count;++ while (saved_arg_count > 3) {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), size, kept_saveds_count, 0);+ kept_saveds_count++;+ size -= SSIZE_OF(sw);+ saved_arg_count--;+ }++ if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S)) {+ if (status & ENTER_TMP_TO_R4)+ size = 2 * SSIZE_OF(sw);++ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), size, TMP_REG1, 0);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 args_size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ arg_types >>= SLJIT_ARG_SHIFT;+ args_size = 0;++ if (!(options & SLJIT_ENTER_REG_ARG)) {+ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ args_size += SSIZE_OF(f64);+ break;+ case SLJIT_ARG_TYPE_F32:+ args_size += SSIZE_OF(f32);+ break;+ default:+ args_size += SSIZE_OF(sw);+ break;+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }+ }++ compiler->args_size = args_size;++ /* [esp+0] for saving temporaries and for function calls. */++ saveds = (1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - SLJIT_KEPT_SAVEDS_COUNT(options)) * SSIZE_OF(sw);++ /* Saving ebp. */+ if (!(options & SLJIT_ENTER_REG_ARG))+ saveds += SSIZE_OF(sw);++ compiler->local_size = ((SLJIT_LOCALS_OFFSET_BASE + local_size + saveds + 0xf) & ~0xf) - saveds;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)+{+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);+ sljit_s32 local_size, saveds;+ sljit_uw size;+ sljit_u8 *inst;++ size = (sljit_uw)((compiler->scratches > 9 ? (compiler->scratches - 9) : 0) ++ (compiler->saveds <= 3 ? compiler->saveds : 3) - kept_saveds_count);++ local_size = compiler->local_size;++ if (!(compiler->options & SLJIT_ENTER_REG_ARG))+ size++;+ else if (is_return_to && size == 0) {+ local_size += SSIZE_OF(sw);+ is_return_to = 0;+ }++ if (local_size > 0)+ BINARY_IMM32(ADD, local_size, SLJIT_SP, 0);++ if (size == 0)+ return SLJIT_SUCCESS;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);++ INC_SIZE(size);++ saveds = compiler->saveds;++ if ((saveds > 0 && kept_saveds_count == 0) || compiler->scratches > 11)+ POP_REG(reg_map[SLJIT_S0]);+ if ((saveds > 1 && kept_saveds_count <= 1) || compiler->scratches > 10)+ POP_REG(reg_map[SLJIT_S1]);+ if ((saveds > 2 && kept_saveds_count <= 2) || compiler->scratches > 9)+ POP_REG(reg_map[SLJIT_S2]);++ if (!(compiler->options & SLJIT_ENTER_REG_ARG))+ POP_REG(reg_map[TMP_REG1]);++ if (is_return_to)+ BINARY_IMM32(ADD, sizeof(sljit_sw), SLJIT_SP, 0);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ SLJIT_ASSERT(compiler->args_size >= 0);+ SLJIT_ASSERT(compiler->local_size > 0);++ FAIL_IF(emit_stack_frame_release(compiler, 0));++ return emit_byte(compiler, RET_near);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 src_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ CHECK_EXTRA_REGS(src, srcw, (void)0);++ src_r = (compiler->options & SLJIT_ENTER_REG_ARG) ? TMP_REG1 : SLJIT_R1;++ EMIT_MOV(compiler, src_r, 0, src, srcw);+ src = src_r;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 1));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}++/* --------------------------------------------------------------------- */+/* Call / return instructions */+/* --------------------------------------------------------------------- */++static sljit_s32 call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)+{+ sljit_sw stack_size = 0;+ sljit_s32 word_arg_count = 0;++ arg_types >>= SLJIT_ARG_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ stack_size += SSIZE_OF(f64);+ break;+ case SLJIT_ARG_TYPE_F32:+ stack_size += SSIZE_OF(f32);+ break;+ default:+ word_arg_count++;+ stack_size += SSIZE_OF(sw);+ break;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ if (word_arg_count_ptr)+ *word_arg_count_ptr = word_arg_count;++ if (stack_size <= 4 * SSIZE_OF(sw))+ return 0;++ return ((stack_size - (4 * SSIZE_OF(sw)) + 0xf) & ~0xf);+}++static sljit_s32 call_with_args(struct sljit_compiler *compiler,+ sljit_s32 arg_types, sljit_sw stack_size, sljit_s32 word_arg_count, sljit_s32 keep_tmp1)+{+ sljit_s32 float_arg_count = 0, arg4_reg = 0, arg_offset;+ sljit_u8 *inst;++ if (word_arg_count >= 4) {+ arg4_reg = SLJIT_R0;++ if (!keep_tmp1) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw));+ arg4_reg = TMP_REG1;+ }+ }++ if (stack_size > 0)+ BINARY_IMM32(SUB, stack_size, SLJIT_SP, 0);++ arg_offset = 0;+ word_arg_count = 0;+ arg_types >>= SLJIT_ARG_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ float_arg_count++;+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), arg_offset, float_arg_count));+ arg_offset += SSIZE_OF(f64);+ break;+ case SLJIT_ARG_TYPE_F32:+ float_arg_count++;+ FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), arg_offset, float_arg_count));+ arg_offset += SSIZE_OF(f32);+ break;+ default:+ word_arg_count++;+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), arg_offset, (word_arg_count >= 4) ? arg4_reg : word_arg_count, 0);++ if (word_arg_count == 1 && arg4_reg == SLJIT_R0)+ EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw) + stack_size);++ arg_offset += SSIZE_OF(sw);+ break;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 post_call_with_args(struct sljit_compiler *compiler,+ sljit_s32 arg_types, sljit_s32 stack_size)+{+ sljit_u8 *inst;+ sljit_s32 single;++ if (stack_size > 0)+ BINARY_IMM32(ADD, stack_size, SLJIT_SP, 0);++ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64)+ return SLJIT_SUCCESS;++ single = ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3);+ inst[0] = single ? FSTPS : FSTPD;+ inst[1] = (0x03 << 3) | 0x04;+ inst[2] = (0x04 << 3) | reg_map[SLJIT_SP];++ return emit_sse2_load(compiler, single, SLJIT_FR0, SLJIT_MEM1(SLJIT_SP), 0);+}++static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler,+ sljit_s32 *extra_space, sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_sw args_size, saved_regs_size;+ sljit_sw types, word_arg_count, float_arg_count;+ sljit_sw stack_size, prev_stack_size, min_size, offset;+ sljit_sw word_arg4_offset;+ sljit_u8 r2_offset = 0;+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);+ sljit_u8* inst;++ ADJUST_LOCAL_OFFSET(src, srcw);+ CHECK_EXTRA_REGS(src, srcw, (void)0);++ saved_regs_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0)+ + (compiler->saveds <= 3 ? compiler->saveds : 3) - kept_saveds_count) * SSIZE_OF(sw);++ word_arg_count = 0;+ float_arg_count = 0;+ arg_types >>= SLJIT_ARG_SHIFT;+ types = 0;+ args_size = 0;++ while (arg_types != 0) {+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);++ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ args_size += SSIZE_OF(f64);+ float_arg_count++;+ break;+ case SLJIT_ARG_TYPE_F32:+ args_size += SSIZE_OF(f32);+ float_arg_count++;+ break;+ default:+ word_arg_count++;+ args_size += SSIZE_OF(sw);+ break;+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ if (args_size <= compiler->args_size) {+ *extra_space = 0;+ stack_size = args_size + SSIZE_OF(sw) + saved_regs_size;++ offset = stack_size + compiler->local_size;++ if (src != SLJIT_IMM && src != SLJIT_R0) {+ if (word_arg_count >= 1) {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);+ r2_offset = sizeof(sljit_sw);+ }+ EMIT_MOV(compiler, SLJIT_R0, 0, src, srcw);+ }++ while (types != 0) {+ switch (types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ offset -= SSIZE_OF(f64);+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));+ float_arg_count--;+ break;+ case SLJIT_ARG_TYPE_F32:+ offset -= SSIZE_OF(f32);+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));+ float_arg_count--;+ break;+ default:+ switch (word_arg_count) {+ case 1:+ offset -= SSIZE_OF(sw);+ if (r2_offset != 0) {+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0);+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);+ } else+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0);+ break;+ case 2:+ offset -= SSIZE_OF(sw);+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0);+ break;+ case 3:+ offset -= SSIZE_OF(sw);+ break;+ case 4:+ offset -= SSIZE_OF(sw);+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw));+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);+ break;+ }+ word_arg_count--;+ break;+ }+ types >>= SLJIT_ARG_SHIFT;+ }++ return emit_stack_frame_release(compiler, 0);+ }++ stack_size = args_size + SSIZE_OF(sw);++ if (word_arg_count >= 1 && src != SLJIT_IMM && src != SLJIT_R0) {+ r2_offset = SSIZE_OF(sw);+ stack_size += SSIZE_OF(sw);+ }++ if (word_arg_count >= 3)+ stack_size += SSIZE_OF(sw);++ prev_stack_size = SSIZE_OF(sw) + saved_regs_size;+ min_size = prev_stack_size + compiler->local_size;++ word_arg4_offset = 2 * SSIZE_OF(sw);++ if (stack_size > min_size) {+ BINARY_IMM32(SUB, stack_size - min_size, SLJIT_SP, 0);+ if (src == SLJIT_MEM1(SLJIT_SP))+ srcw += stack_size - min_size;+ word_arg4_offset += stack_size - min_size;+ }+ else+ stack_size = min_size;++ if (word_arg_count >= 3) {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), r2_offset, SLJIT_R2, 0);++ if (word_arg_count >= 4)+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), word_arg4_offset);+ }++ if (src != SLJIT_IMM && src != SLJIT_R0) {+ if (word_arg_count >= 1) {+ SLJIT_ASSERT(r2_offset == sizeof(sljit_sw));+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);+ }+ EMIT_MOV(compiler, SLJIT_R0, 0, src, srcw);+ }++ /* Restore saved registers. */+ offset = stack_size - 2 * SSIZE_OF(sw);+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), offset);++ if (compiler->saveds > 2 || compiler->scratches > 9) {+ offset -= SSIZE_OF(sw);+ EMIT_MOV(compiler, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), offset);+ }+ if ((compiler->saveds > 1 && kept_saveds_count <= 1) || compiler->scratches > 10) {+ offset -= SSIZE_OF(sw);+ EMIT_MOV(compiler, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_SP), offset);+ }+ if ((compiler->saveds > 0 && kept_saveds_count == 0) || compiler->scratches > 11) {+ offset -= SSIZE_OF(sw);+ EMIT_MOV(compiler, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), offset);+ }++ /* Copy fourth argument and return address. */+ offset = stack_size - SSIZE_OF(sw);+ *extra_space = args_size;++ if (word_arg_count >= 4) {+ offset -= SSIZE_OF(sw);+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);+ }++ while (types != 0) {+ switch (types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ offset -= SSIZE_OF(f64);+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));+ float_arg_count--;+ break;+ case SLJIT_ARG_TYPE_F32:+ offset -= SSIZE_OF(f32);+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));+ float_arg_count--;+ break;+ default:+ switch (word_arg_count) {+ case 1:+ offset -= SSIZE_OF(sw);+ if (r2_offset != 0) {+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0);+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);+ } else+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0);+ break;+ case 2:+ offset -= SSIZE_OF(sw);+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0);+ break;+ case 3:+ offset -= SSIZE_OF(sw);+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), r2_offset);+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);+ break;+ }+ word_arg_count--;+ break;+ }+ types >>= SLJIT_ARG_SHIFT;+ }++ SLJIT_ASSERT(offset >= 0);++ if (offset == 0)+ return SLJIT_SUCCESS;++ BINARY_IMM32(ADD, offset, SLJIT_SP, 0);+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_tail_call_end(struct sljit_compiler *compiler, sljit_s32 extra_space)+{+ /* Called when stack consumption cannot be reduced to 0. */+ sljit_u8 *inst;++ BINARY_IMM32(ADD, extra_space, SLJIT_SP, 0);+ return emit_byte(compiler, RET_near);+}++static sljit_s32 tail_call_reg_arg_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ sljit_s32 word_arg_count = 0;+ sljit_s32 kept_saveds_count, offset;++ arg_types >>= SLJIT_ARG_SHIFT;++ while (arg_types) {+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64)+ word_arg_count++;++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ if (word_arg_count < 4)+ return SLJIT_SUCCESS;++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw));++ kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);+ offset = compiler->local_size + 3 * SSIZE_OF(sw);++ if ((compiler->saveds > 0 && kept_saveds_count == 0) || compiler->scratches > 11)+ offset += SSIZE_OF(sw);+ if ((compiler->saveds > 1 && kept_saveds_count <= 1) || compiler->scratches > 10)+ offset += SSIZE_OF(sw);+ if ((compiler->saveds > 2 && kept_saveds_count <= 2) || compiler->scratches > 9)+ offset += SSIZE_OF(sw);++ return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), offset, TMP_REG1, 0);+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ struct sljit_jump *jump;+ sljit_sw stack_size = 0;+ sljit_s32 word_arg_count;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ if (type & SLJIT_CALL_RETURN) {+ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {+ PTR_FAIL_IF(tail_call_reg_arg_with_args(compiler, arg_types));+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP));+ }++ stack_size = type;+ PTR_FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, SLJIT_IMM, 0));++ SLJIT_SKIP_CHECKS(compiler);++ if (stack_size == 0)+ return sljit_emit_jump(compiler, SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP));++ jump = sljit_emit_jump(compiler, type);+ PTR_FAIL_IF(jump == NULL);++ PTR_FAIL_IF(emit_tail_call_end(compiler, stack_size));+ return jump;+ }++ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, type);+ }++ stack_size = call_get_stack_size(arg_types, &word_arg_count);+ PTR_FAIL_IF(call_with_args(compiler, arg_types, stack_size, word_arg_count, 0));++ SLJIT_SKIP_CHECKS(compiler);+ jump = sljit_emit_jump(compiler, type);+ PTR_FAIL_IF(jump == NULL);++ PTR_FAIL_IF(post_call_with_args(compiler, arg_types, stack_size));+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_sw stack_size = 0;+ sljit_s32 word_arg_count;++ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ if (type & SLJIT_CALL_RETURN) {+ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {+ FAIL_IF(tail_call_reg_arg_with_args(compiler, arg_types));++ if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ CHECK_EXTRA_REGS(src, srcw, (void)0);++ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);+ src = TMP_REG1;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 0));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+ }++ stack_size = type;+ FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, src, srcw));++ if (src != SLJIT_IMM) {+ src = SLJIT_R0;+ srcw = 0;+ }++ SLJIT_SKIP_CHECKS(compiler);++ if (stack_size == 0)+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);++ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));+ return emit_tail_call_end(compiler, stack_size);+ }++ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+ }++ ADJUST_LOCAL_OFFSET(src, srcw);+ CHECK_EXTRA_REGS(src, srcw, (void)0);++ if (src & SLJIT_MEM) {+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);+ src = TMP_REG1;+ srcw = 0;+ }++ stack_size = call_get_stack_size(arg_types, &word_arg_count);+ FAIL_IF(call_with_args(compiler, arg_types, stack_size, word_arg_count, src == TMP_REG1));++ if (stack_size > 0 && src == SLJIT_MEM1(SLJIT_SP))+ srcw += stack_size;++ SLJIT_SKIP_CHECKS(compiler);+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));++ return post_call_with_args(compiler, arg_types, stack_size);+}++static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;++ if (compiler->options & SLJIT_ENTER_REG_ARG) {+ if (src == SLJIT_FR0)+ return SLJIT_SUCCESS;++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);+ }++ if (FAST_IS_REG(src)) {+ FAIL_IF(emit_sse2_store(compiler, op & SLJIT_32, SLJIT_MEM1(SLJIT_SP), 0, src));++ src = SLJIT_MEM1(SLJIT_SP);+ srcw = 0;+ } else {+ ADJUST_LOCAL_OFFSET(src, srcw);+ }++ inst = emit_x86_instruction(compiler, 1 | EX86_SSE2_OP1, 0, 0, src, srcw);+ *inst = (op & SLJIT_32) ? FLDS : FLDL;++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ sljit_u8 *inst;++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++ /* Unused dest is possible here. */+ if (FAST_IS_REG(dst))+ return emit_byte(compiler, U8(POP_r + reg_map[dst]));++ /* Memory. */+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = POP_rm;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)+{+ sljit_u8 *inst;++ CHECK_EXTRA_REGS(src, srcw, (void)0);++ if (FAST_IS_REG(src)) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);+ FAIL_IF(!inst);++ INC_SIZE(1 + 1);+ PUSH_REG(reg_map[src]);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);+ FAIL_IF(!inst);+ inst[0] = GROUP_FF;+ inst[1] |= PUSH_rm;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ }++ RET();+ return SLJIT_SUCCESS;+}++static sljit_s32 sljit_emit_get_return_address(struct sljit_compiler *compiler,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 options = compiler->options;+ sljit_s32 saveds = compiler->saveds;+ sljit_s32 scratches = compiler->scratches;++ saveds = ((scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - SLJIT_KEPT_SAVEDS_COUNT(options)) * SSIZE_OF(sw);++ /* Saving ebp. */+ if (!(options & SLJIT_ENTER_REG_ARG))+ saveds += SSIZE_OF(sw);++ return emit_mov(compiler, dst, dstw, SLJIT_MEM1(SLJIT_SP), compiler->local_size + saveds);+}++/* --------------------------------------------------------------------- */+/* Other operations */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+ sljit_s32 dst = dst_reg;+ sljit_sw dstw = 0;+ sljit_sw src2w = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);+ CHECK_EXTRA_REGS(src1, src1w, (void)0);+ CHECK_EXTRA_REGS(src2_reg, src2w, (void)0);++ type &= ~SLJIT_32;++ if (dst & SLJIT_MEM) {+ if (src1 == SLJIT_IMM || (!(src1 & SLJIT_MEM) && (src2_reg & SLJIT_MEM))) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ src1 = src2_reg;+ src1w = src2w;+ type ^= 0x1;+ } else+ EMIT_MOV(compiler, TMP_REG1, 0, src2_reg, src2w);++ dst_reg = TMP_REG1;+ } else {+ if (dst_reg != src2_reg) {+ if (dst_reg == src1) {+ src1 = src2_reg;+ src1w = src2w;+ type ^= 0x1;+ } else if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ EMIT_MOV(compiler, dst_reg, 0, src1, src1w);+ src1 = src2_reg;+ src1w = src2w;+ type ^= 0x1;+ } else+ EMIT_MOV(compiler, dst_reg, 0, src2_reg, src2w);+ }+ }++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && (src1 != SLJIT_IMM || dst_reg != TMP_REG1)) {+ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ src1 = TMP_REG1;+ src1w = 0;+ }++ FAIL_IF(emit_groupf(compiler, U8(get_jump_code((sljit_uw)type) - 0x40), dst_reg, src1, src1w));+ } else+ FAIL_IF(emit_cmov_generic(compiler, type, dst_reg, src1, src1w));++ if (dst & SLJIT_MEM)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_u8* inst;+ sljit_s32 i, next, reg_idx, offset;+ sljit_u8 regs[2];++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (!(reg & REG_PAIR_MASK))+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);++ ADJUST_LOCAL_OFFSET(mem, memw);++ regs[0] = U8(REG_PAIR_FIRST(reg));+ regs[1] = U8(REG_PAIR_SECOND(reg));++ next = SSIZE_OF(sw);++ if (!(type & SLJIT_MEM_STORE) && (regs[0] == (mem & REG_MASK) || regs[0] == OFFS_REG(mem))) {+ if (regs[1] == (mem & REG_MASK) || regs[1] == OFFS_REG(mem)) {+ /* None of them are virtual register so TMP_REG1 will not be used. */+ EMIT_MOV(compiler, TMP_REG1, 0, OFFS_REG(mem), 0);++ if (regs[1] == OFFS_REG(mem))+ next = -SSIZE_OF(sw);++ mem = (mem & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);+ } else {+ next = -SSIZE_OF(sw);++ if (!(mem & OFFS_REG_MASK))+ memw += SSIZE_OF(sw);+ }+ }++ for (i = 0; i < 2; i++) {+ reg_idx = next > 0 ? i : (i ^ 0x1);+ reg = regs[reg_idx];++ offset = -1;++ if (reg >= SLJIT_R3 && reg <= SLJIT_S3) {+ offset = (2 * SSIZE_OF(sw)) + ((reg) - SLJIT_R3) * SSIZE_OF(sw);+ reg = TMP_REG1;++ if (type & SLJIT_MEM_STORE)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), offset);+ }++ if ((mem & OFFS_REG_MASK) && (reg_idx == 1)) {+ inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(1 + 4));+ FAIL_IF(!inst);++ INC_SIZE(4);++ inst[0] = (type & SLJIT_MEM_STORE) ? MOV_rm_r : MOV_r_rm;+ inst[1] = 0x44 | U8(reg_map[reg] << 3);+ inst[2] = U8(memw << 6) | U8(reg_map[OFFS_REG(mem)] << 3) | reg_map[mem & REG_MASK];+ inst[3] = sizeof(sljit_sw);+ } else if (type & SLJIT_MEM_STORE) {+ EMIT_MOV(compiler, mem, memw, reg, 0);+ } else {+ EMIT_MOV(compiler, reg, 0, mem, memw);+ }++ if (!(mem & OFFS_REG_MASK))+ memw += next;++ if (!(type & SLJIT_MEM_STORE) && offset != -1)+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, TMP_REG1, 0);+ }++ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;+ sljit_u8 *inst, *jump_inst1, *jump_inst2;+ sljit_uw size1, size2;++ /* Binary representation of 0x80000000. */+ static const sljit_f64 f64_high_bit = (sljit_f64)0x80000000ul;++ CHECK_EXTRA_REGS(src, srcw, (void)0);++ if (!(op & SLJIT_32)) {+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);++ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);+ FAIL_IF(!inst);+ inst[1] |= ROL;++ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);+ FAIL_IF(!inst);+ inst[1] |= SHR;++ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_PREF_F2 | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = U8(get_jump_code(SLJIT_NOT_CARRY) - 0x10);++ size1 = compiler->size;+ FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_PREF_F2 | EX86_SSE2, dst_r, SLJIT_MEM0(), (sljit_sw)&f64_high_bit));++ inst[1] = U8(compiler->size - size1);++ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, 0, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+ }++ if (!FAST_IS_REG(src)) {+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);+ src = TMP_REG1;+ }++ BINARY_IMM32(CMP, 0, src, 0);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = JL_i8;+ jump_inst1 = inst;++ size1 = compiler->size;++ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, 0));++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = JMP_i8;+ jump_inst2 = inst;++ size2 = compiler->size;++ jump_inst1[1] = U8(size2 - size1);++ if (src != TMP_REG1)+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);++ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);+ FAIL_IF(!inst);+ inst[1] |= SHR;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = JNC_i8;+ jump_inst1 = inst;++ size1 = compiler->size;++ BINARY_IMM32(OR, 1, TMP_REG1, 0);+ jump_inst1[1] = U8(compiler->size - size1);++ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));+ FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, dst_r, 0));++ jump_inst2[1] = U8(compiler->size - size2);++ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+ sljit_u8 *inst;+ union {+ sljit_s32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++ if (u.imm != 0)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);++ inst[0] = GROUP_66;+ inst[1] = GROUP_0F;++ if (u.imm == 0) {+ inst[2] = PXOR_x_xm;+ inst[3] = U8(freg_map[freg] | (freg_map[freg] << 3) | MOD_REG);+ } else {+ inst[2] = MOVD_x_rm;+ inst[3] = U8(reg_map[TMP_REG1] | (freg_map[freg] << 3) | MOD_REG);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ sljit_u8 *inst;+ union {+ sljit_s32 imm[2];+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ if (u.imm[0] == 0) {+ if (u.imm[1] == 0)+ return emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0);++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[1]);+ } else {+ SLJIT_ASSERT(cpu_feature_list != 0);++ if (!(cpu_feature_list & CPU_FEATURE_SSE41) && u.imm[1] != 0 && u.imm[0] != u.imm[1]) {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, u.imm[0]);+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, u.imm[1]);++ return emit_groupf(compiler, MOVLPD_x_m | EX86_SSE2, freg, SLJIT_MEM1(SLJIT_SP), 0);+ }++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[0]);+ }++ FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, freg, TMP_REG1, 0));++ if (u.imm[1] == 0)+ return SLJIT_SUCCESS;++ if (u.imm[0] == 0) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);++ inst[0] = GROUP_0F;+ inst[1] = SHUFPS_x_xm;+ inst[2] = U8(MOD_REG | (freg_map[freg] << 3) | freg_map[freg]);+ inst[3] = 0x51;+ return SLJIT_SUCCESS;+ }++ if (u.imm[0] != u.imm[1]) {+ SLJIT_ASSERT(cpu_feature_list & CPU_FEATURE_SSE41);+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[1]);++ FAIL_IF(emit_groupf_ext(compiler, PINSRD_x_rm_i8 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2_OP1, freg, TMP_REG1, 0));+ return emit_byte(compiler, 1);+ }++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3);++ inst[0] = GROUP_0F;+ inst[1] = UNPCKLPS_x_xm;+ inst[2] = U8(MOD_REG | (freg_map[freg] << 3) | freg_map[freg]);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_u8 *inst;+ sljit_s32 reg2;+ sljit_sw regw, reg2w;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ regw = 0;+ reg2 = 0;+ reg2w = 0;++ SLJIT_ASSERT(cpu_feature_list != 0);++ if (!(op & SLJIT_32) && (cpu_feature_list & CPU_FEATURE_SSE41)) {+ if (reg & REG_PAIR_MASK) {+ reg2 = REG_PAIR_FIRST(reg);+ reg = REG_PAIR_SECOND(reg);++ CHECK_EXTRA_REGS(reg, regw, (void)0);++ FAIL_IF(emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x)+ | EX86_PREF_66 | EX86_SSE2_OP1, freg, reg, regw));+ } else+ reg2 = reg;++ CHECK_EXTRA_REGS(reg2, reg2w, (void)0);++ FAIL_IF(emit_groupf_ext(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? PINSRD_x_rm_i8 : PEXTRD_rm_x_i8)+ | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2_OP1, freg, reg2, reg2w));+ return emit_byte(compiler, 1);+ }++ if (reg & REG_PAIR_MASK) {+ reg2 = REG_PAIR_SECOND(reg);+ reg = REG_PAIR_FIRST(reg);++ if (reg == reg2)+ reg = 0;++ CHECK_EXTRA_REGS(reg2, reg2w, (void)0);+ }++ CHECK_EXTRA_REGS(reg, regw, (void)0);++ if (op & SLJIT_32)+ return emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x)+ | EX86_PREF_66 | EX86_SSE2_OP1, freg, reg, regw);++ if (op == SLJIT_COPY_FROM_F64) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);+ FAIL_IF(!inst);+ INC_SIZE(5);++ inst[0] = GROUP_66;+ inst[1] = GROUP_0F;+ inst[2] = PSHUFD_x_xm;+ inst[3] = U8(MOD_REG | (TMP_FREG << 3) | freg_map[freg]);+ inst[4] = 1;+ } else if (reg != 0)+ FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, reg, regw));++ if (reg2 != 0)+ FAIL_IF(emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x)+ | EX86_PREF_66 | EX86_SSE2_OP1, freg, reg2, reg2w));++ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3);++ inst[0] = GROUP_0F;+ inst[1] = UNPCKLPS_x_xm;+ inst[2] = U8(MOD_REG | (freg_map[freg] << 3) | freg_map[reg == 0 ? freg : TMP_FREG]);+ } else+ FAIL_IF(emit_groupf(compiler, MOVD_rm_x | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, reg, regw));+ return SLJIT_SUCCESS; }
src/c/pcre2/src/sljit/sljitNativeX86_64.c view
@@ -37,9 +37,9 @@ 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++ = U8(MOV_r_i32 | (reg_map[reg] & 0x7));- sljit_unaligned_store_sw(inst, imm);+ inst[0] = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);+ inst[1] = U8(MOV_r_i32 | reg_lmap[reg]);+ sljit_unaligned_store_sw(inst + 2, imm); return SLJIT_SUCCESS; } @@ -72,7 +72,7 @@ sljit_uw inst_size; /* The immediate operand must be 32 bit. */- SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));+ SLJIT_ASSERT(a != SLJIT_IMM || compiler->mode32 || IS_HALFWORD(imma)); /* Both cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); /* Size flags not allowed for typed instructions. */@@ -80,82 +80,86 @@ /* Both size flags cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); /* SSE2 and immediate is not possible. */- SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));- SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)- && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)- && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));+ SLJIT_ASSERT(a != SLJIT_IMM || !(flags & EX86_SSE2));+ SLJIT_ASSERT(((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))+ & ((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);+ SLJIT_ASSERT((flags & (EX86_VEX_EXT | EX86_REX)) != EX86_VEX_EXT); size &= 0xf;- inst_size = size;+ /* The mod r/m byte is always present. */+ inst_size = size + 1; if (!compiler->mode32 && !(flags & EX86_NO_REXW)) rex |= REX_W; else if (flags & EX86_REX) rex |= REX; - if (flags & (EX86_PREF_F2 | EX86_PREF_F3))- inst_size++;- if (flags & EX86_PREF_66)+ if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) inst_size++; /* Calculate size of b. */- inst_size += 1; /* mod r/m byte. */ if (b & SLJIT_MEM) {- if (!(b & OFFS_REG_MASK)) {- if (NOT_HALFWORD(immb)) {- PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));- immb = 0;- if (b & REG_MASK)- b |= TO_OFFS_REG(TMP_REG2);- else- b |= TMP_REG2;- }- else if (reg_lmap[b & REG_MASK] == 4)- b |= TO_OFFS_REG(SLJIT_SP);+ if (!(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) {+ PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));+ immb = 0;+ if (b & REG_MASK)+ b |= TO_OFFS_REG(TMP_REG2);+ else+ b |= TMP_REG2; } if (!(b & REG_MASK)) 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;-- if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {+ if (immb != 0 && !(b & OFFS_REG_MASK)) { /* Immediate operand. */ if (immb <= 127 && immb >= -128) inst_size += sizeof(sljit_s8); else inst_size += sizeof(sljit_s32);+ } else if (reg_lmap[b & REG_MASK] == 5) {+ /* Swap registers if possible. */+ if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_lmap[OFFS_REG(b)] != 5)+ b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK);+ else+ inst_size += sizeof(sljit_s8); }- else if (reg_lmap[b & REG_MASK] == 5)- inst_size += sizeof(sljit_s8); + if (reg_map[b & REG_MASK] >= 8)+ rex |= REX_B;++ if (reg_lmap[b & REG_MASK] == 4 && !(b & OFFS_REG_MASK))+ b |= TO_OFFS_REG(SLJIT_SP);+ if (b & OFFS_REG_MASK) { inst_size += 1; /* SIB byte. */ if (reg_map[OFFS_REG(b)] >= 8) rex |= REX_X; } }- }- else if (!(flags & EX86_SSE2_OP2)) {+ } else if (!(flags & EX86_SSE2_OP2)) { if (reg_map[b] >= 8) rex |= REX_B;- }- else if (freg_map[b] >= 8)+ } else if (freg_map[b] >= 8) rex |= REX_B; - if (a & SLJIT_IMM) {+ if ((flags & EX86_VEX_EXT) && (rex & 0x3)) {+ SLJIT_ASSERT(size == 2);+ size++;+ inst_size++;+ }++ if (a == SLJIT_IMM) { if (flags & EX86_BIN_INS) { if (imma <= 127 && imma >= -128) { inst_size += 1; flags |= EX86_BYTE_ARG; } else inst_size += 4;- }- else if (flags & EX86_SHIFT_INS) {- imma &= compiler->mode32 ? 0x1f : 0x3f;+ } else if (flags & EX86_SHIFT_INS) {+ SLJIT_ASSERT(imma <= (compiler->mode32 ? 0x1f : 0x3f)); if (imma != 1) {- inst_size ++;+ inst_size++; flags |= EX86_BYTE_ARG; } } else if (flags & EX86_BYTE_ARG)@@ -164,8 +168,7 @@ inst_size += sizeof(short); else inst_size += sizeof(sljit_s32);- }- else {+ } else { SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */ if (!(flags & EX86_SSE2_OP1)) {@@ -182,32 +185,34 @@ inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size); PTR_FAIL_IF(!inst); - /* Encoding the byte. */+ /* Encoding prefixes. */ INC_SIZE(inst_size); if (flags & EX86_PREF_F2) *inst++ = 0xf2;- if (flags & EX86_PREF_F3)+ else if (flags & EX86_PREF_F3) *inst++ = 0xf3;- if (flags & EX86_PREF_66)+ else if (flags & EX86_PREF_66) *inst++ = 0x66;++ /* Rex is always the last prefix. */ if (rex) *inst++ = rex;+ buf_ptr = inst + size; /* Encode mod/rm byte. */ if (!(flags & EX86_SHIFT_INS)) {- if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))+ if ((flags & EX86_BIN_INS) && a == SLJIT_IMM) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; - if (a & SLJIT_IMM)+ if (a == SLJIT_IMM) *buf_ptr = 0; else if (!(flags & EX86_SSE2_OP1)) *buf_ptr = U8(reg_lmap[a] << 3); else *buf_ptr = U8(freg_lmap[a] << 3);- }- else {- if (a & SLJIT_IMM) {+ } else {+ if (a == SLJIT_IMM) { if (imma == 1) *inst = GROUP_SHIFT_1; else@@ -223,7 +228,7 @@ } else if (b & REG_MASK) { reg_lmap_b = reg_lmap[b & REG_MASK]; - if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP) || reg_lmap_b == 5) {+ if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) { if (immb != 0 || reg_lmap_b == 5) { if (immb <= 127 && immb >= -128) *buf_ptr |= 0x40;@@ -234,8 +239,9 @@ if (!(b & OFFS_REG_MASK)) *buf_ptr++ |= reg_lmap_b; else {- *buf_ptr++ |= 0x04;- *buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3));+ buf_ptr[0] |= 0x04;+ buf_ptr[1] = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3));+ buf_ptr += 2; } if (immb != 0 || reg_lmap_b == 5) {@@ -246,20 +252,26 @@ buf_ptr += sizeof(sljit_s32); } }- }- else {- *buf_ptr++ |= 0x04;- *buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));+ } else {+ if (reg_lmap_b == 5)+ *buf_ptr |= 0x40;++ buf_ptr[0] |= 0x04;+ buf_ptr[1] = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));+ buf_ptr += 2;++ if (reg_lmap_b == 5)+ *buf_ptr++ = 0; }- }- else {- *buf_ptr++ |= 0x04;- *buf_ptr++ = 0x25;+ } else {+ buf_ptr[0] |= 0x04;+ buf_ptr[1] = 0x25;+ buf_ptr += 2; sljit_unaligned_store_s32(buf_ptr, (sljit_s32)immb); /* 32 bit displacement. */ buf_ptr += sizeof(sljit_s32); } - if (a & SLJIT_IMM) {+ if (a == SLJIT_IMM) { if (flags & EX86_BYTE_ARG) *buf_ptr = U8(imma); else if (flags & EX86_HALF_ARG)@@ -268,33 +280,106 @@ sljit_unaligned_store_s32(buf_ptr, (sljit_s32)imma); } - return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);+ return inst; } +static sljit_s32 emit_vex_instruction(struct sljit_compiler *compiler, sljit_uw op,+ /* The first and second register operand. */+ sljit_s32 a, sljit_s32 v,+ /* The general operand (not immediate). */+ sljit_s32 b, sljit_sw immb)+{+ sljit_u8 *inst;+ sljit_u8 vex = 0;+ sljit_u8 vex_m = 0;+ sljit_uw size;++ SLJIT_ASSERT(((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))+ & ((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);++ op |= EX86_REX;++ if (op & VEX_OP_0F38)+ vex_m = 0x2;+ else if (op & VEX_OP_0F3A)+ vex_m = 0x3;++ if ((op & VEX_W) || ((op & VEX_AUTO_W) && !compiler->mode32)) {+ if (vex_m == 0)+ vex_m = 0x1;++ vex |= 0x80;+ }++ if (op & EX86_PREF_66)+ vex |= 0x1;+ else if (op & EX86_PREF_F2)+ vex |= 0x3;+ else if (op & EX86_PREF_F3)+ vex |= 0x2;++ op &= ~(EX86_PREF_66 | EX86_PREF_F2 | EX86_PREF_F3);++ if (op & VEX_256)+ vex |= 0x4;++ vex = U8(vex | ((((op & VEX_SSE2_OPV) ? freg_map[v] : reg_map[v]) ^ 0xf) << 3));++ size = op & ~(sljit_uw)0xff;+ size |= (vex_m == 0) ? (EX86_VEX_EXT | 2) : 3;++ inst = emit_x86_instruction(compiler, size, a, 0, b, immb);+ FAIL_IF(!inst);++ SLJIT_ASSERT((inst[-1] & 0xf0) == REX);++ /* If X or B is present in REX prefix. */+ if (vex_m == 0 && inst[-1] & 0x3)+ vex_m = 0x1;++ if (vex_m == 0) {+ vex |= U8(((inst[-1] >> 2) ^ 0x1) << 7);++ inst[-1] = 0xc5;+ inst[0] = vex;+ inst[1] = U8(op);+ return SLJIT_SUCCESS;+ }++ vex_m |= U8((inst[-1] ^ 0x7) << 5);+ inst[-1] = 0xc4;+ inst[0] = vex_m;+ inst[1] = vex;+ inst[2] = U8(op);+ return SLJIT_SUCCESS;+}+ /* --------------------------------------------------------------------- */ /* Enter / return */ /* --------------------------------------------------------------------- */ -static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr)+static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr) { sljit_uw type = jump->flags >> TYPE_SHIFT; - int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff);+ int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && (jump->flags & JUMP_ADDR) && (jump->u.target <= 0xffffffff); /* The relative jump below specialized for this case. */- SLJIT_ASSERT(reg_map[TMP_REG2] >= 8);+ SLJIT_ASSERT(reg_map[TMP_REG2] >= 8 && TMP_REG2 != SLJIT_TMP_DEST_REG); if (type < SLJIT_JUMP) { /* Invert type. */- *code_ptr++ = U8(get_jump_code(type ^ 0x1) - 0x10);- *code_ptr++ = short_addr ? (6 + 3) : (10 + 3);+ code_ptr[0] = U8(get_jump_code(type ^ 0x1) - 0x10);+ code_ptr[1] = short_addr ? (6 + 3) : (10 + 3);+ code_ptr += 2; } - *code_ptr++ = short_addr ? REX_B : (REX_W | REX_B);- *code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2];+ code_ptr[0] = short_addr ? REX_B : (REX_W | REX_B);+ code_ptr[1] = MOV_r_i32 | reg_lmap[TMP_REG2];+ code_ptr += 2; jump->addr = (sljit_uw)code_ptr; - if (jump->flags & JUMP_LABEL)+ if (!(jump->flags & JUMP_ADDR)) jump->flags |= PATCH_MD; else if (short_addr) sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target);@@ -303,70 +388,78 @@ code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw); - *code_ptr++ = REX_B;- *code_ptr++ = GROUP_FF;- *code_ptr++ = U8(MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2]);+ code_ptr[0] = REX_B;+ code_ptr[1] = GROUP_FF;+ code_ptr[2] = U8(MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2]); - return code_ptr;+ return code_ptr + 3; } -static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label)+static sljit_u8* generate_mov_addr_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset) {- if (max_label > HALFWORD_MAX) {- put_label->addr -= put_label->flags;- put_label->flags = PATCH_MD;- return code_ptr;- }+ sljit_uw addr;+ sljit_sw diff;+ SLJIT_UNUSED_ARG(executable_offset); - if (put_label->flags == 0) {- /* Destination is register. */- code_ptr = (sljit_u8*)put_label->addr - 2 - sizeof(sljit_uw);+ SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) <= 10);+ if (jump->flags & JUMP_ADDR)+ addr = jump->u.target;+ else+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + jump->u.label->size; - SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);- SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32);+ if (addr > 0xffffffffl) {+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); - if ((code_ptr[0] & 0x07) != 0) {- code_ptr[0] = U8(code_ptr[0] & ~0x08);- code_ptr += 2 + sizeof(sljit_s32);- }- else {- code_ptr[0] = code_ptr[1];- code_ptr += 1 + sizeof(sljit_s32);+ if (diff <= HALFWORD_MAX && diff >= HALFWORD_MIN) {+ SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) >= 7);+ code_ptr -= SSIZE_OF(s32) - 1;++ SLJIT_ASSERT((code_ptr[-3 - SSIZE_OF(s32)] & 0xf8) == REX_W);+ SLJIT_ASSERT((code_ptr[-2 - SSIZE_OF(s32)] & 0xf8) == MOV_r_i32);++ code_ptr[-3 - SSIZE_OF(s32)] = U8(REX_W | ((code_ptr[-3 - SSIZE_OF(s32)] & 0x1) << 2));+ code_ptr[-1 - SSIZE_OF(s32)] = U8(((code_ptr[-2 - SSIZE_OF(s32)] & 0x7) << 3) | 0x5);+ code_ptr[-2 - SSIZE_OF(s32)] = LEA_r_m;++ jump->flags |= PATCH_MW;+ return code_ptr; } - put_label->addr = (sljit_uw)code_ptr;+ jump->flags |= PATCH_MD; return code_ptr; } - code_ptr -= put_label->flags + (2 + sizeof(sljit_uw));- SLJIT_MEMMOVE(code_ptr, code_ptr + (2 + sizeof(sljit_uw)), put_label->flags);+ code_ptr -= 2 + sizeof(sljit_uw); SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);+ SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32); - if ((code_ptr[1] & 0xf8) == MOV_r_i32) {- code_ptr += 2 + sizeof(sljit_uw);- SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);+ if ((code_ptr[0] & 0x07) != 0) {+ SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) >= 6);+ code_ptr[0] = U8(code_ptr[0] & ~0x08);+ code_ptr += 2 + sizeof(sljit_s32);+ } else {+ SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) >= 5);+ code_ptr[0] = code_ptr[1];+ code_ptr += 1 + sizeof(sljit_s32); } - SLJIT_ASSERT(code_ptr[1] == MOV_rm_r);-- code_ptr[0] = U8(code_ptr[0] & ~0x4);- code_ptr[1] = MOV_rm_i32;- code_ptr[2] = U8(code_ptr[2] & ~(0x7 << 3));-- code_ptr = (sljit_u8*)(put_label->addr - (2 + sizeof(sljit_uw)) + sizeof(sljit_s32));- put_label->addr = (sljit_uw)code_ptr;- put_label->flags = 0; return code_ptr; } +#ifdef _WIN64+typedef struct {+ sljit_sw regs[2];+} sljit_sse2_reg;+#endif /* _WIN64 */+ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_uw size; sljit_s32 word_arg_count = 0;- sljit_s32 saved_arg_count = 0;+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_s32 saved_regs_size, tmp, i; #ifdef _WIN64 sljit_s32 saved_float_regs_size;@@ -379,16 +472,19 @@ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + if (options & SLJIT_ENTER_REG_ARG)+ arg_types = 0;+ /* Emit ENDBR64 at function entry if needed. */ FAIL_IF(emit_endbranch(compiler)); compiler->mode32 = 0; /* Including the return address saved by the call instruction. */- saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); tmp = SLJIT_S0 - saveds;- for (i = SLJIT_S0; i > tmp; i--) {+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) { size = reg_map[i] >= 8 ? 2 : 1; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst);@@ -410,7 +506,7 @@ #ifdef _WIN64 local_size += SLJIT_LOCALS_OFFSET;- saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16);+ saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg); if (saved_float_regs_size > 0) { saved_float_regs_offset = ((local_size + 0xf) & ~0xf);@@ -519,16 +615,12 @@ tmp = SLJIT_FS0 - fsaveds; for (i = SLJIT_FS0; i > tmp; i--) {- inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);- *inst++ = GROUP_0F;- *inst = MOVAPS_xm_x;+ FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset)); saved_float_regs_offset += 16; } for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);- *inst++ = GROUP_0F;- *inst = MOVAPS_xm_x;+ FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset)); saved_float_regs_offset += 16; } }@@ -552,7 +644,7 @@ #ifdef _WIN64 local_size += SLJIT_LOCALS_OFFSET;- saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16);+ saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg); if (saved_float_regs_size > 0) local_size = ((local_size + 0xf) & ~0xf) + saved_float_regs_size;@@ -561,15 +653,15 @@ #endif /* _WIN64 */ /* Including the return address saved by the call instruction. */- saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); compiler->local_size = ((local_size + saved_regs_size + 0xf) & ~0xf) - saved_regs_size; return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_uw size;- sljit_s32 i, tmp;+ sljit_s32 local_size, i, tmp; sljit_u8 *inst; #ifdef _WIN64 sljit_s32 saved_float_regs_offset;@@ -578,7 +670,7 @@ #endif /* _WIN64 */ #ifdef _WIN64- saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16);+ saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg); if (saved_float_regs_offset > 0) { compiler->mode32 = 1;@@ -586,42 +678,29 @@ tmp = SLJIT_FS0 - fsaveds; for (i = SLJIT_FS0; i > tmp; i--) {- inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);- *inst++ = GROUP_0F;- *inst = MOVAPS_x_xm;+ FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset)); saved_float_regs_offset += 16; } for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {- inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);- *inst++ = GROUP_0F;- *inst = MOVAPS_x_xm;+ FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset)); saved_float_regs_offset += 16; }++ compiler->mode32 = 0; } #endif /* _WIN64 */ - 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 = U8(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);- }+ local_size = compiler->local_size;++ if (is_return_to && compiler->scratches < SLJIT_FIRST_SAVED_REG && (compiler->saveds == SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {+ local_size += SSIZE_OF(sw);+ is_return_to = 0; } + if (local_size > 0)+ BINARY_IMM32(ADD, local_size, SLJIT_SP, 0);+ tmp = compiler->scratches; for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) { size = reg_map[i] >= 8 ? 2 : 1;@@ -633,8 +712,8 @@ POP_REG(reg_lmap[i]); } - tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;- for (i = tmp; i <= SLJIT_S0; i++) {+ tmp = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options);+ for (i = SLJIT_S0 + 1 - compiler->saveds; i <= tmp; i++) { size = reg_map[i] >= 8 ? 2 : 1; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst);@@ -644,25 +723,45 @@ POP_REG(reg_lmap[i]); } + if (is_return_to)+ BINARY_IMM32(ADD, sizeof(sljit_sw), SLJIT_SP, 0);+ return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) {- sljit_u8 *inst;- CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler));+ compiler->mode32 = 0; - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- RET();- return SLJIT_SUCCESS;+ FAIL_IF(emit_stack_frame_release(compiler, 0));+ return emit_byte(compiler, RET_near); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));++ compiler->mode32 = 0;++ if ((src & SLJIT_MEM) || (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {+ ADJUST_LOCAL_OFFSET(src, srcw);++ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);+ src = TMP_REG2;+ srcw = 0;+ }++ FAIL_IF(emit_stack_frame_release(compiler, 1));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);+}+ /* --------------------------------------------------------------------- */ /* Call / return instructions */ /* --------------------------------------------------------------------- */@@ -786,17 +885,15 @@ compiler->mode32 = 0; - PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); if (type & SLJIT_CALL_RETURN) {- PTR_FAIL_IF(emit_stack_frame_release(compiler));+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif+ SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, type); } @@ -816,41 +913,31 @@ } if (type & SLJIT_CALL_RETURN) {- if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); src = TMP_REG2; } - FAIL_IF(emit_stack_frame_release(compiler));- type = SLJIT_JUMP;+ FAIL_IF(emit_stack_frame_release(compiler, 0)); } - FAIL_IF(call_with_args(compiler, arg_types, &src));+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ FAIL_IF(call_with_args(compiler, arg_types, &src)); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif+ if (type & SLJIT_CALL_RETURN)+ type = SLJIT_JUMP; + SLJIT_SKIP_CHECKS(compiler); return sljit_emit_ijump(compiler, type, src, srcw); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { sljit_u8 *inst; - CHECK_ERROR();- CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);- if (FAST_IS_REG(dst)) {- if (reg_map[dst] < 8) {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- POP_REG(reg_lmap[dst]);- return SLJIT_SUCCESS;- }+ if (reg_map[dst] < 8)+ return emit_byte(compiler, U8(POP_r + reg_lmap[dst])); inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst);@@ -864,7 +951,7 @@ compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); FAIL_IF(!inst);- *inst++ = POP_rm;+ *inst = POP_rm; return SLJIT_SUCCESS; } @@ -894,8 +981,8 @@ compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); FAIL_IF(!inst);- *inst++ = GROUP_FF;- *inst |= PUSH_rm;+ inst[0] = GROUP_FF;+ inst[1] |= PUSH_rm; inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst);@@ -906,10 +993,140 @@ return SLJIT_SUCCESS; } +static sljit_s32 sljit_emit_get_return_address(struct sljit_compiler *compiler,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 saved_regs_size;++ compiler->mode32 = 0;+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);+ return emit_mov(compiler, dst, dstw, SLJIT_MEM1(SLJIT_SP), compiler->local_size + saved_regs_size);+}+ /* --------------------------------------------------------------------- */-/* Extend input */+/* Other operations */ /* --------------------------------------------------------------------- */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_reg)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ compiler->mode32 = type & SLJIT_32;+ type &= ~SLJIT_32;++ if (dst_reg != src2_reg) {+ if (dst_reg == src1) {+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ EMIT_MOV(compiler, dst_reg, 0, src1, src1w);+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else+ EMIT_MOV(compiler, dst_reg, 0, src2_reg, 0);+ }++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV)) {+ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {+ EMIT_MOV(compiler, TMP_REG2, 0, src1, src1w);+ src1 = TMP_REG2;+ src1w = 0;+ }++ return emit_groupf(compiler, U8(get_jump_code((sljit_uw)type) - 0x40), dst_reg, src1, src1w);+ }++ return emit_cmov_generic(compiler, type, dst_reg, src1, src1w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_u8* inst;+ sljit_s32 i, next, reg_idx;+ sljit_u8 regs[2];++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (!(reg & REG_PAIR_MASK))+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);++ ADJUST_LOCAL_OFFSET(mem, memw);++ compiler->mode32 = 0;++ if ((mem & REG_MASK) == 0) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, memw);++ mem = SLJIT_MEM1(TMP_REG1);+ memw = 0;+ } else if (!(mem & OFFS_REG_MASK) && ((memw < HALFWORD_MIN) || (memw > HALFWORD_MAX - SSIZE_OF(sw)))) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, memw);++ mem = SLJIT_MEM2(mem & REG_MASK, TMP_REG1);+ memw = 0;+ }++ regs[0] = U8(REG_PAIR_FIRST(reg));+ regs[1] = U8(REG_PAIR_SECOND(reg));++ next = SSIZE_OF(sw);++ if (!(type & SLJIT_MEM_STORE) && (regs[0] == (mem & REG_MASK) || regs[0] == OFFS_REG(mem))) {+ if (regs[1] == (mem & REG_MASK) || regs[1] == OFFS_REG(mem)) {+ /* Base and offset cannot be TMP_REG1. */+ EMIT_MOV(compiler, TMP_REG1, 0, OFFS_REG(mem), 0);++ if (regs[1] == OFFS_REG(mem))+ next = -SSIZE_OF(sw);++ mem = (mem & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);+ } else {+ next = -SSIZE_OF(sw);++ if (!(mem & OFFS_REG_MASK))+ memw += SSIZE_OF(sw);+ }+ }++ for (i = 0; i < 2; i++) {+ reg_idx = next > 0 ? i : (i ^ 0x1);+ reg = regs[reg_idx];++ if ((mem & OFFS_REG_MASK) && (reg_idx == 1)) {+ inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(1 + 5));+ FAIL_IF(!inst);++ INC_SIZE(5);++ inst[0] = U8(REX_W | ((reg_map[reg] >= 8) ? REX_R : 0) | ((reg_map[mem & REG_MASK] >= 8) ? REX_B : 0) | ((reg_map[OFFS_REG(mem)] >= 8) ? REX_X : 0));+ inst[1] = (type & SLJIT_MEM_STORE) ? MOV_rm_r : MOV_r_rm;+ inst[2] = 0x44 | U8(reg_lmap[reg] << 3);+ inst[3] = U8(memw << 6) | U8(reg_lmap[OFFS_REG(mem)] << 3) | reg_lmap[mem & REG_MASK];+ inst[4] = sizeof(sljit_sw);+ } else if (type & SLJIT_MEM_STORE) {+ EMIT_MOV(compiler, mem, memw, reg, 0);+ } else {+ EMIT_MOV(compiler, reg, 0, mem, memw);+ }++ if (!(mem & OFFS_REG_MASK))+ memw += next;+ }++ return SLJIT_SUCCESS;+}+ 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)@@ -919,15 +1136,15 @@ compiler->mode32 = 0; - if (src & SLJIT_IMM) {+ 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_s32)srcw, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm_i32;- return SLJIT_SUCCESS;- }- return emit_load_imm64(compiler, dst, srcw);+ if (!sign || ((sljit_u32)srcw <= 0x7fffffff))+ return emit_do_imm32(compiler, reg_map[dst] <= 7 ? 0 : REX_B, U8(MOV_r_i32 | reg_lmap[dst]), srcw);++ 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; } compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);@@ -945,10 +1162,10 @@ if (sign) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw); FAIL_IF(!inst);- *inst++ = MOVSXD_r_rm;+ *inst = MOVSXD_r_rm; } else { compiler->mode32 = 1;- FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));+ EMIT_MOV(compiler, dst_r, 0, src, srcw); compiler->mode32 = 0; } }@@ -960,6 +1177,203 @@ *inst = MOV_rm_r; compiler->mode32 = 0; }++ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;+ sljit_u8 *inst, *jump_inst1, *jump_inst2;+ sljit_uw size1, size2;++ compiler->mode32 = 0;++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {+ if (src != SLJIT_IMM) {+ compiler->mode32 = 1;+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);+ compiler->mode32 = 0;+ } else+ FAIL_IF(emit_do_imm32(compiler, reg_map[TMP_REG1] <= 7 ? 0 : REX_B, U8(MOV_r_i32 | reg_lmap[TMP_REG1]), srcw));++ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));++ compiler->mode32 = 1;++ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+ }++ if (!FAST_IS_REG(src)) {+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);+ src = TMP_REG1;+ }++ BINARY_IMM32(CMP, 0, src, 0);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = JL_i8;+ jump_inst1 = inst;++ size1 = compiler->size;++ compiler->mode32 = 0;+ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, 0));++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = JMP_i8;+ jump_inst2 = inst;++ size2 = compiler->size;++ jump_inst1[1] = U8(size2 - size1);++ if (src != TMP_REG1)+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);++ EMIT_MOV(compiler, TMP_REG2, 0, src, 0);++ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);+ FAIL_IF(!inst);+ inst[1] |= SHR;++ compiler->mode32 = 1;+ BINARY_IMM32(AND, 1, TMP_REG2, 0);++ compiler->mode32 = 0;+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG2, 0);+ FAIL_IF(!inst);+ inst[0] = OR_r_rm;++ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));+ compiler->mode32 = 1;+ FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, dst_r, 0));++ jump_inst2[1] = U8(compiler->size - size2);++ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+}++static sljit_s32 sljit_emit_fset(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_u8 rex, sljit_s32 is_zero)+{+ sljit_u8 *inst;+ sljit_u32 size;++ if (is_zero) {+ rex = freg_map[freg] >= 8 ? (REX_R | REX_B) : 0;+ } else {+ if (freg_map[freg] >= 8)+ rex |= REX_R;+ if (reg_map[TMP_REG1] >= 8)+ rex |= REX_B;+ }++ size = (rex != 0) ? 5 : 4;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);++ *inst++ = GROUP_66;+ if (rex != 0)+ *inst++ = rex;+ inst[0] = GROUP_0F;++ if (is_zero) {+ inst[1] = PXOR_x_xm;+ inst[2] = U8(freg_lmap[freg] | (freg_lmap[freg] << 3) | MOD_REG);+ } else {+ inst[1] = MOVD_x_rm;+ inst[2] = U8(reg_lmap[TMP_REG1] | (freg_lmap[freg] << 3) | MOD_REG);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f32 value)+{+ union {+ sljit_s32 imm;+ sljit_f32 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset32(compiler, freg, value));++ u.value = value;++ if (u.imm != 0) {+ compiler->mode32 = 1;+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm);+ }++ return sljit_emit_fset(compiler, freg, 0, u.imm == 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,+ sljit_s32 freg, sljit_f64 value)+{+ union {+ sljit_sw imm;+ sljit_f64 value;+ } u;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ if (u.imm != 0) {+ compiler->mode32 = 0;+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm);+ }++ return sljit_emit_fset(compiler, freg, REX_W, u.imm == 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 freg, sljit_s32 reg)+{+ sljit_u8 *inst;+ sljit_u32 size;+ sljit_u8 rex = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ if (!(op & SLJIT_32))+ rex = REX_W;++ if (freg_map[freg] >= 8)+ rex |= REX_R;++ if (reg_map[reg] >= 8)+ rex |= REX_B;++ size = (rex != 0) ? 5 : 4;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);++ *inst++ = GROUP_66;+ if (rex != 0)+ *inst++ = rex;+ inst[0] = GROUP_0F;+ inst[1] = GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x;+ inst[2] = U8(reg_lmap[reg] | (freg_lmap[freg] << 3) | MOD_REG); return SLJIT_SUCCESS; }
src/c/pcre2/src/sljit/sljitNativeX86_common.c view
@@ -26,3076 +26,4956 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) {-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)- return "x86" SLJIT_CPUINFO " ABI:fastcall";-#else- return "x86" SLJIT_CPUINFO;-#endif-}--/*- 32b register indexes:- 0 - EAX- 1 - ECX- 2 - EDX- 3 - EBX- 4 - ESP- 5 - EBP- 6 - ESI- 7 - EDI-*/--/*- 64b register indexes:- 0 - RAX- 1 - RCX- 2 - RDX- 3 - RBX- 4 - RSP- 5 - RBP- 6 - RSI- 7 - RDI- 8 - R8 - From now on REX prefix is required- 9 - R9- 10 - R10- 11 - R11- 12 - R12- 13 - R13- 14 - R14- 15 - R15-*/--#define TMP_FREG (0)--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)--/* Last register + 1. */-#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)--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_S3) { \- if (p <= compiler->scratches) \- w = compiler->scratches_offset + ((p) - SLJIT_R3) * SSIZE_OF(sw); \- else \- w = compiler->locals_offset + ((p) - SLJIT_S2) * SSIZE_OF(sw); \- p = SLJIT_MEM1(SLJIT_SP); \- do; \- }--#else /* SLJIT_CONFIG_X86_32 */--/* Last register + 1. */-#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)-#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)--/* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present- Note: avoid to use r12 and r13 for memory addessing- therefore r12 is better to be a higher saved register. */-#ifndef _WIN64-/* 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, 7, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9-};-/* low-map. reg_map & 0x7. */-static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {- 0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1-};-#else-/* 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, 8, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 9, 10-};-/* low-map. reg_map & 0x7. */-static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {- 0, 0, 2, 0, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 1, 2-};-#endif--/* Args: xmm0-xmm3 */-static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {- 4, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15-};-/* low-map. freg_map & 0x7. */-static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {- 4, 0, 1, 2, 3, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7-};--#define REX_W 0x48-#define REX_R 0x44-#define REX_X 0x42-#define REX_B 0x41-#define REX 0x40--#ifndef _WIN64-#define HALFWORD_MAX 0x7fffffffl-#define HALFWORD_MIN -0x80000000l-#else-#define HALFWORD_MAX 0x7fffffffll-#define HALFWORD_MIN -0x80000000ll-#endif--#define IS_HALFWORD(x) ((x) <= HALFWORD_MAX && (x) >= HALFWORD_MIN)-#define NOT_HALFWORD(x) ((x) > HALFWORD_MAX || (x) < HALFWORD_MIN)--#define CHECK_EXTRA_REGS(p, w, do)--#endif /* SLJIT_CONFIG_X86_32 */--#define U8(v) ((sljit_u8)(v))---/* Size flags for emit_x86_instruction: */-#define EX86_BIN_INS 0x0010-#define EX86_SHIFT_INS 0x0020-#define EX86_REX 0x0040-#define EX86_NO_REXW 0x0080-#define EX86_BYTE_ARG 0x0100-#define EX86_HALF_ARG 0x0200-#define EX86_PREF_66 0x0400-#define EX86_PREF_F2 0x0800-#define EX86_PREF_F3 0x1000-#define EX86_SSE2_OP1 0x2000-#define EX86_SSE2_OP2 0x4000-#define EX86_SSE2 (EX86_SSE2_OP1 | EX86_SSE2_OP2)--/* --------------------------------------------------------------------- */-/* Instrucion forms */-/* --------------------------------------------------------------------- */--#define ADD (/* BINARY */ 0 << 3)-#define ADD_EAX_i32 0x05-#define ADD_r_rm 0x03-#define ADD_rm_r 0x01-#define ADDSD_x_xm 0x58-#define ADC (/* BINARY */ 2 << 3)-#define ADC_EAX_i32 0x15-#define ADC_r_rm 0x13-#define ADC_rm_r 0x11-#define AND (/* BINARY */ 4 << 3)-#define AND_EAX_i32 0x25-#define AND_r_rm 0x23-#define AND_rm_r 0x21-#define ANDPD_x_xm 0x54-#define BSR_r_rm (/* GROUP_0F */ 0xbd)-#define CALL_i32 0xe8-#define CALL_rm (/* GROUP_FF */ 2 << 3)-#define CDQ 0x99-#define CMOVE_r_rm (/* GROUP_0F */ 0x44)-#define CMP (/* BINARY */ 7 << 3)-#define CMP_EAX_i32 0x3d-#define CMP_r_rm 0x3b-#define CMP_rm_r 0x39-#define CVTPD2PS_x_xm 0x5a-#define CVTSI2SD_x_rm 0x2a-#define CVTTSD2SI_r_xm 0x2c-#define DIV (/* GROUP_F7 */ 6 << 3)-#define DIVSD_x_xm 0x5e-#define FSTPS 0xd9-#define FSTPD 0xdd-#define INT3 0xcc-#define IDIV (/* GROUP_F7 */ 7 << 3)-#define IMUL (/* GROUP_F7 */ 5 << 3)-#define IMUL_r_rm (/* GROUP_0F */ 0xaf)-#define IMUL_r_rm_i8 0x6b-#define IMUL_r_rm_i32 0x69-#define JE_i8 0x74-#define JNE_i8 0x75-#define JMP_i8 0xeb-#define JMP_i32 0xe9-#define JMP_rm (/* GROUP_FF */ 4 << 3)-#define LEA_r_m 0x8d-#define LOOP_i8 0xe2-#define MOV_r_rm 0x8b-#define MOV_r_i32 0xb8-#define MOV_rm_r 0x89-#define MOV_rm_i32 0xc7-#define MOV_rm8_i8 0xc6-#define MOV_rm8_r8 0x88-#define MOVAPS_x_xm 0x28-#define MOVAPS_xm_x 0x29-#define MOVSD_x_xm 0x10-#define MOVSD_xm_x 0x11-#define MOVSXD_r_rm 0x63-#define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe)-#define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf)-#define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6)-#define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7)-#define MUL (/* GROUP_F7 */ 4 << 3)-#define MULSD_x_xm 0x59-#define NEG_rm (/* GROUP_F7 */ 3 << 3)-#define NOP 0x90-#define NOT_rm (/* GROUP_F7 */ 2 << 3)-#define OR (/* BINARY */ 1 << 3)-#define OR_r_rm 0x0b-#define OR_EAX_i32 0x0d-#define OR_rm_r 0x09-#define OR_rm8_r8 0x08-#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)-#define PUSHF 0x9c-#define RET_near 0xc3-#define RET_i16 0xc2-#define SBB (/* BINARY */ 3 << 3)-#define SBB_EAX_i32 0x1d-#define SBB_r_rm 0x1b-#define SBB_rm_r 0x19-#define SAR (/* SHIFT */ 7 << 3)-#define SHL (/* SHIFT */ 4 << 3)-#define SHR (/* SHIFT */ 5 << 3)-#define SUB (/* BINARY */ 5 << 3)-#define SUB_EAX_i32 0x2d-#define SUB_r_rm 0x2b-#define SUB_rm_r 0x29-#define SUBSD_x_xm 0x5c-#define TEST_EAX_i32 0xa9-#define TEST_rm_r 0x85-#define UCOMISD_x_xm 0x2e-#define UNPCKLPD_x_xm 0x14-#define XCHG_EAX_r 0x90-#define XCHG_r_rm 0x87-#define XOR (/* BINARY */ 6 << 3)-#define XOR_EAX_i32 0x35-#define XOR_r_rm 0x33-#define XOR_rm_r 0x31-#define XORPD_x_xm 0x57--#define GROUP_0F 0x0f-#define GROUP_F7 0xf7-#define GROUP_FF 0xff-#define GROUP_BINARY_81 0x81-#define GROUP_BINARY_83 0x83-#define GROUP_SHIFT_1 0xd1-#define GROUP_SHIFT_N 0xc1-#define GROUP_SHIFT_CL 0xd3--#define MOD_REG 0xc0-#define MOD_DISP8 0x40--#define INC_SIZE(s) (*inst++ = U8(s), compiler->size += (s))--#define PUSH_REG(r) (*inst++ = U8(PUSH_r + (r)))-#define POP_REG(r) (*inst++ = U8(POP_r + (r)))-#define RET() (*inst++ = RET_near)-#define RET_I16(n) (*inst++ = RET_i16, *inst++ = U8(n), *inst++ = 0)--/* Multithreading does not affect these static variables, since they store- 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_s32 cpu_has_sse2 = -1;-#endif-static sljit_s32 cpu_has_cmov = -1;--#ifdef _WIN32_WCE-#include <cmnintrin.h>-#elif defined(_MSC_VER) && _MSC_VER >= 1400-#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_u32 features;--#if defined(_MSC_VER) && _MSC_VER >= 1400-- int CPUInfo[4];- __cpuid(CPUInfo, 1);- features = (sljit_u32)CPUInfo[3];--#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C)-- /* AT&T syntax. */- __asm__ (- "movl $0x1, %%eax\n"-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- /* On x86-32, there is no red zone, so this- should work (no need for a local variable). */- "push %%ebx\n"-#endif- "cpuid\n"-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- "pop %%ebx\n"-#endif- "movl %%edx, %0\n"- : "=g" (features)- :-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- : "%eax", "%ecx", "%edx"-#else- : "%rax", "%rbx", "%rcx", "%rdx"-#endif- );--#else /* _MSC_VER && _MSC_VER >= 1400 */-- /* Intel syntax. */- __asm {- mov eax, 1- cpuid- mov features, edx- }--#endif /* _MSC_VER && _MSC_VER >= 1400 */--#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)- cpu_has_sse2 = (features >> 26) & 0x1;-#endif- cpu_has_cmov = (features >> 15) & 0x1;-}--static sljit_u8 get_jump_code(sljit_uw type)-{- switch (type) {- case SLJIT_EQUAL:- case SLJIT_EQUAL_F64:- return 0x84 /* je */;-- case SLJIT_NOT_EQUAL:- case SLJIT_NOT_EQUAL_F64:- return 0x85 /* jne */;-- case SLJIT_LESS:- case SLJIT_CARRY:- case SLJIT_LESS_F64:- return 0x82 /* jc */;-- case SLJIT_GREATER_EQUAL:- case SLJIT_NOT_CARRY:- case SLJIT_GREATER_EQUAL_F64:- return 0x83 /* jae */;-- case SLJIT_GREATER:- case SLJIT_GREATER_F64:- return 0x87 /* jnbe */;-- case SLJIT_LESS_EQUAL:- case SLJIT_LESS_EQUAL_F64:- return 0x86 /* jbe */;-- case SLJIT_SIG_LESS:- return 0x8c /* jl */;-- case SLJIT_SIG_GREATER_EQUAL:- return 0x8d /* jnl */;-- case SLJIT_SIG_GREATER:- return 0x8f /* jnle */;-- case SLJIT_SIG_LESS_EQUAL:- return 0x8e /* jle */;-- case SLJIT_OVERFLOW:- return 0x80 /* jo */;-- case SLJIT_NOT_OVERFLOW:- return 0x81 /* jno */;-- case SLJIT_UNORDERED_F64:- return 0x8a /* jp */;-- case SLJIT_ORDERED_F64:- return 0x8b /* jpo */;- }- return 0;-}--#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_sw executable_offset);-#else-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr);-static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label);-#endif--static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)-{- sljit_uw type = jump->flags >> TYPE_SHIFT;- 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 - (sljit_uw)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)- if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN)- return generate_far_jump_code(jump, code_ptr);-#endif-- if (type == SLJIT_JUMP) {- if (short_jump)- *code_ptr++ = JMP_i8;- else- *code_ptr++ = JMP_i32;- jump->addr++;- }- else if (type >= SLJIT_FAST_CALL) {- short_jump = 0;- *code_ptr++ = CALL_i32;- jump->addr++;- }- else if (short_jump) {- *code_ptr++ = U8(get_jump_code(type) - 0x10);- jump->addr++;- }- else {- *code_ptr++ = GROUP_0F;- *code_ptr++ = get_jump_code(type);- jump->addr += 2;- }-- if (short_jump) {- jump->flags |= PATCH_MB;- code_ptr += sizeof(sljit_s8);- } else {- jump->flags |= PATCH_MW;- code_ptr += sizeof(sljit_s32);- }-- return code_ptr;-}--SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)-{- struct sljit_memory_fragment *buf;- sljit_u8 *code;- sljit_u8 *code_ptr;- sljit_u8 *buf_ptr;- sljit_u8 *buf_end;- sljit_u8 len;- sljit_sw executable_offset;- sljit_uw jump_addr;-- struct sljit_label *label;- struct sljit_jump *jump;- struct sljit_const *const_;- struct sljit_put_label *put_label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_generate_code(compiler));- reverse_buf(compiler);-- /* Second code generation pass. */- code = (sljit_u8*)SLJIT_MALLOC_EXEC(compiler->size, compiler->exec_allocator_data);- PTR_FAIL_WITH_EXEC_IF(code);- buf = compiler->buf;-- code_ptr = code;- label = compiler->labels;- jump = compiler->jumps;- const_ = compiler->consts;- put_label = compiler->put_labels;- executable_offset = SLJIT_EXEC_OFFSET(code);-- do {- buf_ptr = buf->memory;- buf_end = buf_ptr + buf->used_size;- do {- len = *buf_ptr++;- if (len > 0) {- /* The code is already generated. */- SLJIT_MEMCPY(code_ptr, buf_ptr, len);- code_ptr += len;- buf_ptr += len;- }- else {- switch (*buf_ptr) {- case 0:- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);- label->size = (sljit_uw)(code_ptr - code);- label = label->next;- break;- case 1:- jump->addr = (sljit_uw)code_ptr;- if (!(jump->flags & SLJIT_REWRITABLE_JUMP))- code_ptr = generate_near_jump_code(jump, code_ptr, code, executable_offset);- else {-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- code_ptr = generate_far_jump_code(jump, code_ptr, executable_offset);-#else- code_ptr = generate_far_jump_code(jump, code_ptr);-#endif- }- jump = jump->next;- break;- case 2:- const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);- const_ = const_->next;- break;- default:- SLJIT_ASSERT(*buf_ptr == 3);- SLJIT_ASSERT(put_label->label);- put_label->addr = (sljit_uw)code_ptr;-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- code_ptr = generate_put_label_code(put_label, code_ptr, (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size);-#endif- put_label = put_label->next;- break;- }- buf_ptr++;- }- } while (buf_ptr < buf_end);- SLJIT_ASSERT(buf_ptr == buf_end);- buf = buf->next;- } while (buf);-- SLJIT_ASSERT(!label);- SLJIT_ASSERT(!jump);- SLJIT_ASSERT(!const_);- SLJIT_ASSERT(!put_label);- SLJIT_ASSERT(code_ptr <= code + compiler->size);-- jump = compiler->jumps;- while (jump) {- jump_addr = jump->addr + (sljit_uw)executable_offset;-- if (jump->flags & PATCH_MB) {- 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 = 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_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_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_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_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_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump->u.label->addr);-#endif-- jump = jump->next;- }-- put_label = compiler->put_labels;- while (put_label) {-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr);-#else- if (put_label->flags & PATCH_MD) {- SLJIT_ASSERT(put_label->label->addr > HALFWORD_MAX);- sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr);- }- else {- SLJIT_ASSERT(put_label->label->addr <= HALFWORD_MAX);- sljit_unaligned_store_s32((void*)(put_label->addr - sizeof(sljit_s32)), (sljit_s32)put_label->label->addr);- }-#endif-- put_label = put_label->next;- }-- compiler->error = SLJIT_ERR_COMPILED;- compiler->executable_offset = executable_offset;- compiler->executable_size = (sljit_uw)(code_ptr - code);-- code = (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);-- SLJIT_UPDATE_WX_FLAGS(code, (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset), 1);- return (void*)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 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 */--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- case SLJIT_HAS_VIRTUAL_REGISTERS:- return 1;-#endif-- case SLJIT_HAS_CLZ:- case SLJIT_HAS_CMOV:- if (cpu_has_cmov == -1)- get_cpu_features();- return cpu_has_cmov;-- case SLJIT_HAS_PREFETCH:- return 1;-- 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- return 1;-#endif-- default:- return 0;- }-}--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--#define BINARY_OPCODE(opcode) (((opcode ## _EAX_i32) << 24) | ((opcode ## _r_rm) << 16) | ((opcode ## _rm_r) << 8) | (opcode))--#define BINARY_IMM32(op_imm, immw, arg, argw) \- do { \- inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \- FAIL_IF(!inst); \- *(inst + 1) |= (op_imm); \- } while (0)--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)--#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \- do { \- if (IS_HALFWORD(immw) || compiler->mode32) { \- BINARY_IMM32(op_imm, immw, arg, argw); \- } \- else { \- 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); \- } \- } while (0)--#define BINARY_EAX_IMM(op_eax_imm, immw) \- FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw))--#else /* !SLJIT_CONFIG_X86_64 */--#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \- BINARY_IMM32(op_imm, immw, arg, argw)--#define BINARY_EAX_IMM(op_eax_imm, immw) \- FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw))--#endif /* SLJIT_CONFIG_X86_64 */--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));--static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,- sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src);--static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,- sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw);--static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w);--static SLJIT_INLINE sljit_s32 emit_endbranch(struct sljit_compiler *compiler)-{-#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)- /* Emit endbr32/endbr64 when CET is enabled. */- sljit_u8 *inst;- inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);- FAIL_IF(!inst);- INC_SIZE(4);- *inst++ = 0xf3;- *inst++ = 0x0f;- *inst++ = 0x1e;-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- *inst = 0xfb;-#else- *inst = 0xfa;-#endif-#else /* !SLJIT_CONFIG_X86_CET */- SLJIT_UNUSED_ARG(compiler);-#endif /* SLJIT_CONFIG_X86_CET */- return SLJIT_SUCCESS;-}--#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)--static SLJIT_INLINE sljit_s32 emit_rdssp(struct sljit_compiler *compiler, sljit_s32 reg)-{- sljit_u8 *inst;- sljit_s32 size;--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- size = 5;-#else- size = 4;-#endif-- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);- FAIL_IF(!inst);- INC_SIZE(size);- *inst++ = 0xf3;-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);-#endif- *inst++ = 0x0f;- *inst++ = 0x1e;- *inst = (0x3 << 6) | (0x1 << 3) | (reg_map[reg] & 0x7);- return SLJIT_SUCCESS;-}--static SLJIT_INLINE sljit_s32 emit_incssp(struct sljit_compiler *compiler, sljit_s32 reg)-{- sljit_u8 *inst;- sljit_s32 size;--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- size = 5;-#else- size = 4;-#endif-- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);- FAIL_IF(!inst);- INC_SIZE(size);- *inst++ = 0xf3;-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);-#endif- *inst++ = 0x0f;- *inst++ = 0xae;- *inst = (0x3 << 6) | (0x5 << 3) | (reg_map[reg] & 0x7);- return SLJIT_SUCCESS;-}--#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */--static SLJIT_INLINE sljit_s32 cpu_has_shadow_stack(void)-{-#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)- return _get_ssp() != 0;-#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */- return 0;-#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */-}--static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compiler,- sljit_s32 src, sljit_sw srcw)-{-#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)- sljit_u8 *inst, *jz_after_cmp_inst;- sljit_uw size_jz_after_cmp_inst;-- sljit_uw size_before_rdssp_inst = compiler->size;-- /* Generate "RDSSP TMP_REG1". */- FAIL_IF(emit_rdssp(compiler, TMP_REG1));-- /* Load return address on shadow stack into TMP_REG1. */-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- SLJIT_ASSERT(reg_map[TMP_REG1] == 5);-- /* Hand code unsupported "mov 0x0(%ebp),%ebp". */- inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);- FAIL_IF(!inst);- INC_SIZE(3);- *inst++ = 0x8b;- *inst++ = 0x6d;- *inst = 0;-#else /* !SLJIT_CONFIG_X86_32 */- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), 0);-#endif /* SLJIT_CONFIG_X86_32 */-- /* Compare return address against TMP_REG1. */- FAIL_IF(emit_cmp_binary (compiler, TMP_REG1, 0, src, srcw));-- /* Generate JZ to skip shadow stack ajdustment when shadow- stack matches normal stack. */- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);- FAIL_IF(!inst);- INC_SIZE(2);- *inst++ = get_jump_code(SLJIT_EQUAL) - 0x10;- size_jz_after_cmp_inst = compiler->size;- jz_after_cmp_inst = inst;--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- /* REX_W is not necessary. */- compiler->mode32 = 1;-#endif- /* Load 1 into TMP_REG1. */- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1);-- /* Generate "INCSSP TMP_REG1". */- FAIL_IF(emit_incssp(compiler, TMP_REG1));-- /* Jump back to "RDSSP TMP_REG1" to check shadow stack again. */- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);- FAIL_IF(!inst);- INC_SIZE(2);- *inst++ = JMP_i8;- *inst = size_before_rdssp_inst - compiler->size;-- *jz_after_cmp_inst = compiler->size - size_jz_after_cmp_inst;-#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */- SLJIT_UNUSED_ARG(compiler);- SLJIT_UNUSED_ARG(src);- SLJIT_UNUSED_ARG(srcw);-#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */- return SLJIT_SUCCESS;-}--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)-#include "sljitNativeX86_32.c"-#else-#include "sljitNativeX86_64.c"-#endif--static sljit_s32 emit_mov(struct sljit_compiler *compiler,- sljit_s32 dst, sljit_sw dstw,- sljit_s32 src, sljit_sw srcw)-{- sljit_u8* inst;-- if (FAST_IS_REG(src)) {- inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm_r;- return SLJIT_SUCCESS;- }- if (src & SLJIT_IMM) {- if (FAST_IS_REG(dst)) {-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);-#else- if (!compiler->mode32) {- if (NOT_HALFWORD(srcw))- return emit_load_imm64(compiler, dst, srcw);- }- else- return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, U8(MOV_r_i32 | reg_lmap[dst]), srcw);-#endif- }-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if (!compiler->mode32 && NOT_HALFWORD(srcw)) {- /* 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;- }-#endif- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm_i32;- return SLJIT_SUCCESS;- }- if (FAST_IS_REG(dst)) {- inst = emit_x86_instruction(compiler, 1, dst, 0, src, srcw);- FAIL_IF(!inst);- *inst = MOV_r_rm;- return SLJIT_SUCCESS;- }-- /* 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;- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm_r;- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)-{- sljit_u8 *inst;-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- sljit_uw size;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_op0(compiler, op));-- switch (GET_OPCODE(op)) {- case SLJIT_BREAKPOINT:- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- *inst = INT3;- break;- case SLJIT_NOP:- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- *inst = NOP;- break;- 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_ASSERT(- reg_map[SLJIT_R0] == 0- && reg_map[SLJIT_R1] == 2- && reg_map[TMP_REG1] > 7);-#else- SLJIT_ASSERT(- reg_map[SLJIT_R0] == 0- && reg_map[SLJIT_R1] < 7- && reg_map[TMP_REG1] == 2);-#endif- compiler->mode32 = op & SLJIT_32;-#endif- 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_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);-#else- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);-#endif- FAIL_IF(!inst);- *inst = XOR_r_rm;- }-- 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_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- *inst = CDQ;-#else- if (compiler->mode32) {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- *inst = CDQ;- } else {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);- FAIL_IF(!inst);- INC_SIZE(2);- *inst++ = REX_W;- *inst = CDQ;- }-#endif- }--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);- FAIL_IF(!inst);- INC_SIZE(2);- *inst++ = GROUP_F7;- *inst = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);-#else-#ifdef _WIN64- size = (!compiler->mode32 || op >= SLJIT_DIVMOD_UW) ? 3 : 2;-#else- size = (!compiler->mode32) ? 3 : 2;-#endif- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);- FAIL_IF(!inst);- INC_SIZE(size);-#ifdef _WIN64- if (!compiler->mode32)- *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_DIVMOD_UW) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);-#else- if (!compiler->mode32)- *inst++ = REX_W;- *inst++ = GROUP_F7;- *inst = MOD_REG | reg_map[SLJIT_R1];-#endif-#endif- switch (op) {- case SLJIT_LMUL_UW:- *inst |= MUL;- break;- case SLJIT_LMUL_SW:- *inst |= IMUL;- break;- case SLJIT_DIVMOD_UW:- case SLJIT_DIV_UW:- *inst |= DIV;- break;- 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_DIVMOD_SW)- EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);-#else- if (op >= SLJIT_DIV_UW)- EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);-#endif- break;- case SLJIT_ENDBR:- return emit_endbranch(compiler);- case SLJIT_SKIP_FRAMES_BEFORE_RETURN:- return skip_frames_before_return(compiler);- }-- return SLJIT_SUCCESS;-}--#define ENCODE_PREFIX(prefix) \- do { \- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); \- FAIL_IF(!inst); \- INC_SIZE(1); \- *inst = U8(prefix); \- } while (0)--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_u8* inst;- sljit_s32 dst_r;-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- sljit_s32 work_r;-#endif--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = 0;-#endif-- if (src & SLJIT_IMM) {- if (FAST_IS_REG(dst)) {-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);-#else- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);- FAIL_IF(!inst);- *inst = MOV_rm_i32;- return SLJIT_SUCCESS;-#endif- }- inst = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm8_i8;- return SLJIT_SUCCESS;- }-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;-- if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) {-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- if (reg_map[src] >= 4) {- SLJIT_ASSERT(dst_r == TMP_REG1);- EMIT_MOV(compiler, TMP_REG1, 0, src, 0);- } else- dst_r = src;-#else- dst_r = src;-#endif- }-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- else if (FAST_IS_REG(src) && reg_map[src] >= 4) {- /* src, dst are registers. */- SLJIT_ASSERT(FAST_IS_REG(dst));- if (reg_map[dst] < 4) {- if (dst != src)- EMIT_MOV(compiler, dst, 0, src, 0);- inst = emit_x86_instruction(compiler, 2, dst, 0, dst, 0);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8;- }- else {- if (dst != src)- EMIT_MOV(compiler, dst, 0, src, 0);- if (sign) {- /* shl reg, 24 */- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);- FAIL_IF(!inst);- *inst |= SHL;- /* sar reg, 24 */- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);- FAIL_IF(!inst);- *inst |= SAR;- }- else {- inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0xff, dst, 0);- FAIL_IF(!inst);- *(inst + 1) |= AND;- }- }- return SLJIT_SUCCESS;- }-#endif- else {- /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */- inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8;- }-- if (dst & SLJIT_MEM) {-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- if (dst_r == TMP_REG1) {- /* Find a non-used register, whose reg_map[src] < 4. */- if ((dst & REG_MASK) == SLJIT_R0) {- if ((dst & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_R1))- work_r = SLJIT_R2;- else- work_r = SLJIT_R1;- }- else {- if ((dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R0))- work_r = SLJIT_R0;- else if ((dst & REG_MASK) == SLJIT_R1)- work_r = SLJIT_R2;- else- work_r = SLJIT_R1;- }-- if (work_r == SLJIT_R0) {- ENCODE_PREFIX(XCHG_EAX_r | reg_map[TMP_REG1]);- }- else {- inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);- FAIL_IF(!inst);- *inst = XCHG_r_rm;- }-- inst = emit_x86_instruction(compiler, 1, work_r, 0, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm8_r8;-- if (work_r == SLJIT_R0) {- ENCODE_PREFIX(XCHG_EAX_r | reg_map[TMP_REG1]);- }- else {- inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);- FAIL_IF(!inst);- *inst = XCHG_r_rm;- }- }- else {- inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm8_r8;- }-#else- inst = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm8_r8;-#endif- }-- return SLJIT_SUCCESS;-}--static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw)-{- sljit_u8* inst;--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = 1;-#endif-- inst = emit_x86_instruction(compiler, 2, 0, 0, src, srcw);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst++ = PREFETCH;-- if (op == SLJIT_PREFETCH_L1)- *inst |= (1 << 3);- else if (op == SLJIT_PREFETCH_L2)- *inst |= (2 << 3);- else if (op == SLJIT_PREFETCH_L3)- *inst |= (3 << 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)) {-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);-#else- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);- FAIL_IF(!inst);- *inst = MOV_rm_i32;- return SLJIT_SUCCESS;-#endif- }- inst = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm_i32;- return SLJIT_SUCCESS;- }-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;-- if ((dst & SLJIT_MEM) && FAST_IS_REG(src))- dst_r = src;- else {- inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = sign ? MOVSX_r_rm16 : MOVZX_r_rm16;- }-- if (dst & SLJIT_MEM) {- inst = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw);- FAIL_IF(!inst);- *inst = MOV_rm_r;- }-- return SLJIT_SUCCESS;-}--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_u8* inst;-- if (dst == src && dstw == srcw) {- /* Same input and output */- inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);- FAIL_IF(!inst);- *inst++ = GROUP_F7;- *inst |= opcode;- return SLJIT_SUCCESS;- }-- if (FAST_IS_REG(dst)) {- EMIT_MOV(compiler, dst, 0, src, srcw);- 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);- *inst++ = GROUP_F7;- *inst |= opcode;- EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);- return SLJIT_SUCCESS;-}--static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler,- sljit_s32 dst, sljit_sw dstw,- sljit_s32 src, sljit_sw srcw)-{- sljit_u8* inst;-- if (FAST_IS_REG(dst)) {- EMIT_MOV(compiler, dst, 0, src, srcw);- inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);- FAIL_IF(!inst);- *inst++ = GROUP_F7;- *inst |= NOT_rm;- inst = emit_x86_instruction(compiler, 1, dst, 0, dst, 0);- FAIL_IF(!inst);- *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);- *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;- EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);- return SLJIT_SUCCESS;-}--#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_u8* inst;- sljit_s32 dst_r;-- SLJIT_UNUSED_ARG(op_flags);-- 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 (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- inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), (sljit_sw)&emit_clz_arg);-- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = CMOVE_r_rm;- }- else- FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, 32 + 31));-- inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);-#else- if (cpu_has_cmov) {- EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_32) ? (64 + 63) : (32 + 31));-- 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_32) ? (64 + 63) : (32 + 31)));-- inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_32) ? 63 : 31, dst_r, 0);-#endif-- FAIL_IF(!inst);- *(inst + 1) |= XOR;-- if (dst & SLJIT_MEM)- EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);- return SLJIT_SUCCESS;-}--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_s32 op_flags = GET_ALL_FLAGS(op);-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- sljit_s32 dst_is_ereg = 0;-#endif-- CHECK_ERROR();- CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src, srcw);-- CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);- CHECK_EXTRA_REGS(src, srcw, (void)0);-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = op_flags & SLJIT_32;-#endif-- op = GET_OPCODE(op);-- if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = 0;-#endif-- 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_flags & SLJIT_32) {- if (src & SLJIT_MEM) {- if (op == SLJIT_MOV_S32)- op = SLJIT_MOV_U32;- }- else if (src & SLJIT_IMM) {- if (op == SLJIT_MOV_U32)- op = SLJIT_MOV_S32;- }- }-#endif-- if (src & SLJIT_IMM) {- switch (op) {- case SLJIT_MOV_U8:- srcw = (sljit_u8)srcw;- break;- case SLJIT_MOV_S8:- srcw = (sljit_s8)srcw;- break;- case SLJIT_MOV_U16:- srcw = (sljit_u16)srcw;- break;- case SLJIT_MOV_S16:- srcw = (sljit_s16)srcw;- break;-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- case SLJIT_MOV_U32:- srcw = (sljit_u32)srcw;- break;- case SLJIT_MOV_S32:- srcw = (sljit_s32)srcw;- break;-#endif- }-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- if (SLJIT_UNLIKELY(dst_is_ereg))- return emit_mov(compiler, dst, dstw, src, srcw);-#endif- }--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- 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;- }-#endif-- switch (op) {- case SLJIT_MOV:- case SLJIT_MOV_P:-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- case SLJIT_MOV32:-#endif- EMIT_MOV(compiler, dst, dstw, src, srcw);- break;- case SLJIT_MOV_U8:- FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, srcw));- break;- case SLJIT_MOV_S8:- FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, srcw));- break;- case SLJIT_MOV_U16:- FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, srcw));- break;- 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_U32:- FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, srcw));- break;- case SLJIT_MOV_S32:- FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, srcw));- break;- case SLJIT_MOV32:- compiler->mode32 = 1;- EMIT_MOV(compiler, dst, dstw, src, srcw);- compiler->mode32 = 0;- break;-#endif- }--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1)- return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0);-#endif- return SLJIT_SUCCESS;- }-- switch (op) {- case SLJIT_NOT:- 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_CLZ:- return emit_clz(compiler, op_flags, dst, dstw, src, srcw);- }-- return SLJIT_SUCCESS;-}--static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,- sljit_u32 op_types,- sljit_s32 dst, sljit_sw dstw,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_u8* inst;- sljit_u8 op_eax_imm = U8(op_types >> 24);- sljit_u8 op_rm = U8((op_types >> 16) & 0xff);- sljit_u8 op_mr = U8((op_types >> 8) & 0xff);- sljit_u8 op_imm = U8(op_types & 0xff);-- if (dst == src1 && dstw == src1w) {- if (src2 & SLJIT_IMM) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {-#else- if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {-#endif- BINARY_EAX_IMM(op_eax_imm, src2w);- }- else {- BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);- }- }- else if (FAST_IS_REG(dst)) {- inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);- FAIL_IF(!inst);- *inst = op_rm;- }- else if (FAST_IS_REG(src2)) {- /* Special exception for sljit_emit_op_flags. */- inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);- FAIL_IF(!inst);- *inst = op_mr;- }- else {- EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);- FAIL_IF(!inst);- *inst = op_mr;- }- return SLJIT_SUCCESS;- }-- /* Only for cumulative operations. */- if (dst == src2 && dstw == src2w) {- if (src1 & SLJIT_IMM) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {-#else- if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128)) {-#endif- BINARY_EAX_IMM(op_eax_imm, src1w);- }- else {- BINARY_IMM(op_imm, op_mr, src1w, dst, dstw);- }- }- else if (FAST_IS_REG(dst)) {- inst = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w);- FAIL_IF(!inst);- *inst = op_rm;- }- else if (FAST_IS_REG(src1)) {- inst = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw);- FAIL_IF(!inst);- *inst = op_mr;- }- else {- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);- FAIL_IF(!inst);- *inst = op_mr;- }- return SLJIT_SUCCESS;- }-- /* General version. */- if (FAST_IS_REG(dst)) {- EMIT_MOV(compiler, dst, 0, src1, src1w);- if (src2 & SLJIT_IMM) {- BINARY_IMM(op_imm, op_mr, src2w, dst, 0);- }- else {- inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);- FAIL_IF(!inst);- *inst = op_rm;- }- }- else {- /* This version requires less memory writing. */- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);- if (src2 & SLJIT_IMM) {- BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);- }- else {- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);- FAIL_IF(!inst);- *inst = op_rm;- }- EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);- }-- return SLJIT_SUCCESS;-}--static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,- sljit_u32 op_types,- sljit_s32 dst, sljit_sw dstw,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_u8* inst;- sljit_u8 op_eax_imm = U8(op_types >> 24);- sljit_u8 op_rm = U8((op_types >> 16) & 0xff);- sljit_u8 op_mr = U8((op_types >> 8) & 0xff);- sljit_u8 op_imm = U8(op_types & 0xff);-- if (dst == src1 && dstw == src1w) {- if (src2 & SLJIT_IMM) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {-#else- if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {-#endif- BINARY_EAX_IMM(op_eax_imm, src2w);- }- else {- BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);- }- }- else if (FAST_IS_REG(dst)) {- inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);- FAIL_IF(!inst);- *inst = op_rm;- }- else if (FAST_IS_REG(src2)) {- inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);- FAIL_IF(!inst);- *inst = op_mr;- }- else {- EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);- FAIL_IF(!inst);- *inst = op_mr;- }- return SLJIT_SUCCESS;- }-- /* General version. */- if (FAST_IS_REG(dst) && dst != src2) {- EMIT_MOV(compiler, dst, 0, src1, src1w);- if (src2 & SLJIT_IMM) {- BINARY_IMM(op_imm, op_mr, src2w, dst, 0);- }- else {- inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);- FAIL_IF(!inst);- *inst = op_rm;- }- }- else {- /* This version requires less memory writing. */- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);- if (src2 & SLJIT_IMM) {- BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);- }- else {- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);- FAIL_IF(!inst);- *inst = op_rm;- }- EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);- }-- return SLJIT_SUCCESS;-}--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_u8* inst;- sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;-- /* Register destination. */- if (dst_r == src1 && !(src2 & SLJIT_IMM)) {- inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = IMUL_r_rm;- }- else if (dst_r == src2 && !(src1 & SLJIT_IMM)) {- inst = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = IMUL_r_rm;- }- else if (src1 & SLJIT_IMM) {- if (src2 & SLJIT_IMM) {- EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, src2w);- src2 = dst_r;- src2w = 0;- }-- if (src1w <= 127 && src1w >= -128) {- inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);- FAIL_IF(!inst);- *inst = IMUL_r_rm_i8;- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- *inst = U8(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_u8*)ensure_buf(compiler, 1 + 4);- FAIL_IF(!inst);- INC_SIZE(4);- 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_u8*)ensure_buf(compiler, 1 + 4);- FAIL_IF(!inst);- INC_SIZE(4);- sljit_unaligned_store_s32(inst, (sljit_s32)src1w);- }- else {- 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;- *inst = IMUL_r_rm;- }-#endif- }- else if (src2 & SLJIT_IMM) {- /* Note: src1 is NOT immediate. */-- if (src2w <= 127 && src2w >= -128) {- inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);- FAIL_IF(!inst);- *inst = IMUL_r_rm_i8;- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);- FAIL_IF(!inst);- INC_SIZE(1);- *inst = U8(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_u8*)ensure_buf(compiler, 1 + 4);- FAIL_IF(!inst);- INC_SIZE(4);- 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_u8*)ensure_buf(compiler, 1 + 4);- FAIL_IF(!inst);- INC_SIZE(4);- sljit_unaligned_store_s32(inst, (sljit_s32)src2w);- }- else {- 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;- *inst = IMUL_r_rm;- }-#endif- }- else {- /* Neither argument is immediate. */- if (ADDRESSING_DEPENDS_ON(src2, dst_r))- dst_r = TMP_REG1;- EMIT_MOV(compiler, dst_r, 0, src1, src1w);- inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = IMUL_r_rm;- }-- if (dst & SLJIT_MEM)- EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);-- return SLJIT_SUCCESS;-}--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_u8* inst;- sljit_s32 dst_r, done = 0;-- /* These cases better be left to handled by normal way. */- 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;-- if (FAST_IS_REG(src1)) {- if (FAST_IS_REG(src2)) {- inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0);- FAIL_IF(!inst);- *inst = LEA_r_m;- done = 1;- }-#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_s32)src2w);-#else- if (src2 & SLJIT_IMM) {- inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w);-#endif- FAIL_IF(!inst);- *inst = LEA_r_m;- done = 1;- }- }- 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_s32)src1w);-#else- if (src1 & SLJIT_IMM) {- inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w);-#endif- FAIL_IF(!inst);- *inst = LEA_r_m;- done = 1;- }- }-- if (done) {- if (dst_r == TMP_REG1)- return emit_mov(compiler, dst, dstw, TMP_REG1, 0);- return SLJIT_SUCCESS;- }- return SLJIT_ERR_UNSUPPORTED;-}--static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- 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))) {-#else- if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {-#endif- BINARY_EAX_IMM(CMP_EAX_i32, src2w);- return SLJIT_SUCCESS;- }-- if (FAST_IS_REG(src1)) {- if (src2 & SLJIT_IMM) {- BINARY_IMM(CMP, CMP_rm_r, src2w, src1, 0);- }- else {- inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);- FAIL_IF(!inst);- *inst = CMP_r_rm;- }- return SLJIT_SUCCESS;- }-- if (FAST_IS_REG(src2) && !(src1 & SLJIT_IMM)) {- inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);- FAIL_IF(!inst);- *inst = CMP_rm_r;- return SLJIT_SUCCESS;- }-- if (src2 & SLJIT_IMM) {- if (src1 & SLJIT_IMM) {- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);- src1 = TMP_REG1;- src1w = 0;- }- BINARY_IMM(CMP, CMP_rm_r, src2w, src1, src1w);- }- else {- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);- FAIL_IF(!inst);- *inst = CMP_r_rm;- }- return SLJIT_SUCCESS;-}--static sljit_s32 emit_test_binary(struct sljit_compiler *compiler,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- 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))) {-#else- if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {-#endif- BINARY_EAX_IMM(TEST_EAX_i32, src2w);- return SLJIT_SUCCESS;- }--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- 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- BINARY_EAX_IMM(TEST_EAX_i32, src1w);- return SLJIT_SUCCESS;- }-- if (!(src1 & SLJIT_IMM)) {- if (src2 & SLJIT_IMM) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if (IS_HALFWORD(src2w) || compiler->mode32) {- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);- FAIL_IF(!inst);- *inst = GROUP_F7;- }- else {- 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;- }-#else- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);- FAIL_IF(!inst);- *inst = GROUP_F7;-#endif- return SLJIT_SUCCESS;- }- else if (FAST_IS_REG(src1)) {- inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);- FAIL_IF(!inst);- *inst = TEST_rm_r;- return SLJIT_SUCCESS;- }- }-- if (!(src2 & SLJIT_IMM)) {- if (src1 & SLJIT_IMM) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if (IS_HALFWORD(src1w) || compiler->mode32) {- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w);- FAIL_IF(!inst);- *inst = GROUP_F7;- }- else {- 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;- }-#else- inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w);- FAIL_IF(!inst);- *inst = GROUP_F7;-#endif- return SLJIT_SUCCESS;- }- else if (FAST_IS_REG(src2)) {- inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);- FAIL_IF(!inst);- *inst = TEST_rm_r;- return SLJIT_SUCCESS;- }- }-- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);- if (src2 & SLJIT_IMM) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if (IS_HALFWORD(src2w) || compiler->mode32) {- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);- FAIL_IF(!inst);- *inst = GROUP_F7;- }- else {- FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REG1, 0);- FAIL_IF(!inst);- *inst = TEST_rm_r;- }-#else- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);- FAIL_IF(!inst);- *inst = GROUP_F7;-#endif- }- else {- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);- FAIL_IF(!inst);- *inst = TEST_rm_r;- }- return SLJIT_SUCCESS;-}--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_u8* inst;-- if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) {- if (dst == src1 && dstw == src1w) {- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw);- FAIL_IF(!inst);- *inst |= mode;- return SLJIT_SUCCESS;- }- if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) {- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);- 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_REG1, 0);- return SLJIT_SUCCESS;- }- if (FAST_IS_REG(dst)) {- EMIT_MOV(compiler, dst, 0, src1, src1w);- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0);- FAIL_IF(!inst);- *inst |= mode;- return SLJIT_SUCCESS;- }-- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0);- FAIL_IF(!inst);- *inst |= mode;- EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);- return SLJIT_SUCCESS;- }-- if (dst == SLJIT_PREF_SHIFT_REG) {- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);- 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;- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);- }- else if (FAST_IS_REG(dst) && dst != src2 && dst != TMP_REG1 && !ADDRESSING_DEPENDS_ON(src2, dst)) {- if (src1 != dst)- EMIT_MOV(compiler, dst, 0, src1, src1w);- EMIT_MOV(compiler, TMP_REG1, 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, dst, 0);- FAIL_IF(!inst);- *inst |= mode;- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);- }- else {- /* This case is complex since ecx itself may be used for- addressing, and this case must be supported as well. */- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- 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;- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0);-#else- EMIT_MOV(compiler, TMP_REG2, 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;- EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);-#endif- if (dst != TMP_REG1)- return emit_mov(compiler, dst, dstw, TMP_REG1, 0);- }-- return SLJIT_SUCCESS;-}--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) {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0))- return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);-#else- if ((src2w & 0x1f) != 0)- return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);-#endif- if (!set_flags)- return emit_mov(compiler, dst, dstw, src1, src1w);- /* OR dst, src, 0 */- return emit_cum_binary(compiler, BINARY_OPCODE(OR),- dst, dstw, src1, src1w, SLJIT_IMM, 0);- }-- if (!set_flags)- return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);-- if (!FAST_IS_REG(dst))- FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));-- FAIL_IF(emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w));-- if (FAST_IS_REG(dst))- return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);- return SLJIT_SUCCESS;-}--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, 0, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- CHECK_EXTRA_REGS(dst, dstw, (void)0);- 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_32;-#endif-- SLJIT_ASSERT(dst != TMP_REG1 || HAS_FLAGS(op));-- switch (GET_OPCODE(op)) {- case SLJIT_ADD:- if (!HAS_FLAGS(op)) {- if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)- return compiler->error;- }- return emit_cum_binary(compiler, BINARY_OPCODE(ADD),- dst, dstw, src1, src1w, src2, src2w);- case SLJIT_ADDC:- return emit_cum_binary(compiler, BINARY_OPCODE(ADC),- dst, dstw, src1, src1w, src2, src2w);- case SLJIT_SUB:- if (src1 == SLJIT_IMM && src1w == 0)- return emit_unary(compiler, NEG_rm, dst, dstw, src2, src2w);-- 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;- if (FAST_IS_REG(dst) && src2 == dst) {- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, 0, dst, 0, src1, src1w));- return emit_unary(compiler, NEG_rm, dst, 0, dst, 0);- }- }-- return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),- dst, dstw, src1, src1w, src2, src2w);- case SLJIT_SUBC:- return emit_non_cum_binary(compiler, BINARY_OPCODE(SBB),- dst, dstw, src1, src1w, src2, src2w);- case SLJIT_MUL:- return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w);- case SLJIT_AND:- return emit_cum_binary(compiler, BINARY_OPCODE(AND),- dst, dstw, src1, src1w, src2, src2w);- case SLJIT_OR:- return emit_cum_binary(compiler, BINARY_OPCODE(OR),- dst, dstw, src1, src1w, src2, src2w);- case SLJIT_XOR:- return emit_cum_binary(compiler, BINARY_OPCODE(XOR),- dst, dstw, src1, src1w, src2, src2w);- case SLJIT_SHL:- 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, HAS_FLAGS(op),- dst, dstw, src1, src1w, src2, src2w);- case SLJIT_ASHR:- return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op),- dst, dstw, src1, src1w, src2, src2w);- }-- return SLJIT_SUCCESS;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src1, sljit_sw src1w,- sljit_s32 src2, sljit_sw src2w)-{- sljit_s32 opcode = GET_OPCODE(op);-- CHECK_ERROR();- CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));-- if (opcode != SLJIT_SUB && opcode != SLJIT_AND) {-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)- compiler->skip_checks = 1;-#endif- return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);- }-- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);-- 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_32;-#endif-- if (opcode == SLJIT_SUB) {- return emit_cmp_binary(compiler, src1, src1w, src2, src2w);- }- return emit_test_binary(compiler, src1, src1w, src2, src2w);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,- sljit_s32 src, sljit_sw srcw)-{- CHECK_ERROR();- CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- CHECK_EXTRA_REGS(src, srcw, (void)0);-- switch (op) {- case SLJIT_FAST_RETURN:- return emit_fast_return(compiler, src, srcw);- case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:- /* Don't adjust shadow stack if it isn't enabled. */- if (!cpu_has_shadow_stack ())- return SLJIT_SUCCESS;- return adjust_shadow_stack(compiler, src, srcw);- case SLJIT_PREFETCH_L1:- case SLJIT_PREFETCH_L2:- case SLJIT_PREFETCH_L3:- case SLJIT_PREFETCH_ONCE:- return emit_prefetch(compiler, op, src, srcw);- }-- return SLJIT_SUCCESS;-}--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_R8)- return -1;-#endif- return reg_map[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));-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- return reg;-#else- return freg_map[reg];-#endif-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,- void *instruction, sljit_u32 size)-{- sljit_u8 *inst;-- CHECK_ERROR();- CHECK(check_sljit_emit_op_custom(compiler, instruction, size));-- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);- FAIL_IF(!inst);- INC_SIZE(size);- SLJIT_MEMCPY(inst, instruction, size);- return SLJIT_SUCCESS;-}--/* --------------------------------------------------------------------- */-/* Floating point operators */-/* --------------------------------------------------------------------- */--/* Alignment(3) + 4 * 16 bytes. */-static sljit_u32 sse2_data[3 + (4 * 4)];-static sljit_u32 *sse2_buffer;--static void init_compiler(void)-{- /* Align to 16 bytes. */- sse2_buffer = (sljit_u32*)(((sljit_uw)sse2_data + 15) & ~(sljit_uw)0xf);-- /* Single precision constants (each constant is 16 byte long). */- sse2_buffer[0] = 0x80000000;- sse2_buffer[4] = 0x7fffffff;- /* 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;-}--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_u8 *inst;-- inst = emit_x86_instruction(compiler, 2 | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = opcode;- return SLJIT_SUCCESS;-}--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_u8 *inst;-- inst = emit_x86_instruction(compiler, 2 | (pref66 ? EX86_PREF_66 : 0) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = opcode;- return SLJIT_SUCCESS;-}--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_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_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_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_CONV_SW_FROM_F64)- compiler->mode32 = 0;-#endif-- inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_32) ? 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 & SLJIT_MEM)- return emit_mov(compiler, dst, dstw, TMP_REG1, 0);- return SLJIT_SUCCESS;-}--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_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_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_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_32) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw);- FAIL_IF(!inst);- *inst++ = GROUP_0F;- *inst = CVTSI2SD_x_rm;--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = 1;-#endif- if (dst_r == TMP_FREG)- return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);- return SLJIT_SUCCESS;-}--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 (!FAST_IS_REG(src1)) {- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));- src1 = TMP_FREG;- }-- return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_32), src1, src2, src2w);-}--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_s32 dst_r;--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = 1;-#endif-- CHECK_ERROR();- SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);-- if (GET_OPCODE(op) == SLJIT_MOV_F64) {- if (FAST_IS_REG(dst))- return emit_sse2_load(compiler, op & SLJIT_32, dst, src, srcw);- if (FAST_IS_REG(src))- return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, src);- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw));- return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);- }-- 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_32, src, src, 0));- }- else {- FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_32), TMP_FREG, src, srcw));- src = TMP_FREG;- }-- FAIL_IF(emit_sse2_logic(compiler, CVTPD2PS_x_xm, op & SLJIT_32, dst_r, src, 0));- if (dst_r == TMP_FREG)- return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);- return SLJIT_SUCCESS;- }-- if (FAST_IS_REG(dst)) {- dst_r = dst;- if (dst != src)- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_r, src, srcw));- }- else {- dst_r = TMP_FREG;- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_r, src, srcw));- }-- switch (GET_OPCODE(op)) {- case SLJIT_NEG_F64:- FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_32 ? sse2_buffer : sse2_buffer + 8)));- break;-- case SLJIT_ABS_F64:- FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_32 ? sse2_buffer + 4 : sse2_buffer + 12)));- break;- }-- if (dst_r == TMP_FREG)- return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);- return SLJIT_SUCCESS;-}--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_s32 dst_r;-- CHECK_ERROR();- CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));- ADJUST_LOCAL_OFFSET(dst, dstw);- ADJUST_LOCAL_OFFSET(src1, src1w);- ADJUST_LOCAL_OFFSET(src2, src2w);--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = 1;-#endif-- if (FAST_IS_REG(dst)) {- dst_r = dst;- if (dst == src1)- ; /* Do nothing here. */- 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_32, dst_r, src1, src1w));- else {- dst_r = TMP_FREG;- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));- }- }- else {- dst_r = TMP_FREG;- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));- }-- switch (GET_OPCODE(op)) {- case SLJIT_ADD_F64:- FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_32, dst_r, src2, src2w));- break;-- case SLJIT_SUB_F64:- FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_32, dst_r, src2, src2w));- break;-- case SLJIT_MUL_F64:- FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_32, dst_r, src2, src2w));- break;-- case SLJIT_DIV_F64:- FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_32, dst_r, src2, src2w));- break;- }-- if (dst_r == TMP_FREG)- return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);- return SLJIT_SUCCESS;-}--/* --------------------------------------------------------------------- */-/* Conditional instructions */-/* --------------------------------------------------------------------- */--SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)-{- sljit_u8 *inst;- struct sljit_label *label;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_label(compiler));-- if (compiler->last_label && compiler->last_label->size == compiler->size)- return compiler->last_label;-- label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));- PTR_FAIL_IF(!label);- set_label(label, compiler);-- inst = (sljit_u8*)ensure_buf(compiler, 2);- PTR_FAIL_IF(!inst);-- *inst++ = 0;- *inst++ = 0;-- return label;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)-{- sljit_u8 *inst;- struct sljit_jump *jump;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_jump(compiler, type));-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF_NULL(jump);- set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT)));- type &= 0xff;-- /* Worst case size. */-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- compiler->size += (type >= SLJIT_JUMP) ? 5 : 6;-#else- compiler->size += (type >= SLJIT_JUMP) ? (10 + 3) : (2 + 10 + 3);-#endif-- inst = (sljit_u8*)ensure_buf(compiler, 2);- PTR_FAIL_IF_NULL(inst);-- *inst++ = 0;- *inst++ = 1;- return jump;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)-{- sljit_u8 *inst;- struct sljit_jump *jump;-- CHECK_ERROR();- CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));- ADJUST_LOCAL_OFFSET(src, srcw);-- CHECK_EXTRA_REGS(src, srcw, (void)0);-- if (src == SLJIT_IMM) {- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- FAIL_IF_NULL(jump);- set_jump(jump, compiler, (sljit_u32)(JUMP_ADDR | (type << TYPE_SHIFT)));- jump->u.target = (sljit_uw)srcw;-- /* Worst case size. */-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- compiler->size += 5;-#else- compiler->size += 10 + 3;-#endif-- inst = (sljit_u8*)ensure_buf(compiler, 2);- FAIL_IF_NULL(inst);-- *inst++ = 0;- *inst++ = 1;- }- else {-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- /* REX_W is not necessary (src is not immediate). */- compiler->mode32 = 1;-#endif- inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);- FAIL_IF(!inst);- *inst++ = GROUP_FF;- *inst = U8(*inst | ((type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm));- }- return SLJIT_SUCCESS;-}--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_u8 *inst;- sljit_u8 cond_set = 0;-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- 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, type));-- ADJUST_LOCAL_OFFSET(dst, dstw);- CHECK_EXTRA_REGS(dst, dstw, (void)0);-- type &= 0xff;- /* setcc = jcc + 0x10. */- cond_set = U8(get_jump_code((sljit_uw)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)) {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 3);- FAIL_IF(!inst);- INC_SIZE(4 + 3);- /* Set low register to conditional flag. */- *inst++ = (reg_map[TMP_REG1] <= 7) ? REX : REX_B;- *inst++ = GROUP_0F;- *inst++ = cond_set;- *inst++ = MOD_REG | reg_lmap[TMP_REG1];- *inst++ = U8(REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B));- *inst++ = OR_rm8_r8;- *inst++ = U8(MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst]);- return SLJIT_SUCCESS;- }-- reg = (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG1;-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 4);- FAIL_IF(!inst);- INC_SIZE(4 + 4);- /* Set low register to conditional flag. */- *inst++ = (reg_map[reg] <= 7) ? REX : REX_B;- *inst++ = GROUP_0F;- *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 = U8(MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]);-- if (reg != TMP_REG1)- return SLJIT_SUCCESS;-- if (GET_OPCODE(op) < SLJIT_ADD) {- 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_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_u8*)ensure_buf(compiler, 1 + 3 + 3);- FAIL_IF(!inst);- INC_SIZE(3 + 3);- /* Set low byte to conditional flag. */- *inst++ = GROUP_0F;- *inst++ = cond_set;- *inst++ = U8(MOD_REG | reg_map[dst]);-- *inst++ = GROUP_0F;- *inst++ = MOVZX_r_rm8;- *inst = U8(MOD_REG | (reg_map[dst] << 3) | reg_map[dst]);- return SLJIT_SUCCESS;- }-- /* Low byte is not accessible. */- if (cpu_has_cmov == -1)- get_cpu_features();-- if (cpu_has_cmov) {- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1);- /* a xor reg, reg operation would overwrite the flags. */- EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0);-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);- FAIL_IF(!inst);- INC_SIZE(3);-- *inst++ = GROUP_0F;- /* cmovcc = setcc - 0x50. */- *inst++ = U8(cond_set - 0x50);- *inst++ = U8(MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REG1]);- return SLJIT_SUCCESS;- }-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);- FAIL_IF(!inst);- INC_SIZE(1 + 3 + 3 + 1);- *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);- /* Set al to conditional flag. */- *inst++ = GROUP_0F;- *inst++ = cond_set;- *inst++ = MOD_REG | 0 /* eax */;-- *inst++ = GROUP_0F;- *inst++ = MOVZX_r_rm8;- *inst++ = U8(MOD_REG | (reg_map[dst] << 3) | 0 /* eax */);- *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);- return SLJIT_SUCCESS;- }-- 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_u8*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1);- FAIL_IF(!inst);- INC_SIZE(1 + 3 + 2 + 1);- /* Set low register to conditional flag. */- *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);- *inst++ = GROUP_0F;- *inst++ = cond_set;- *inst++ = MOD_REG | 0 /* eax */;- *inst++ = OR_rm8_r8;- *inst++ = MOD_REG | (0 /* eax */ << 3) | reg_map[dst];- *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);- }- else {- 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. */- *inst++ = XCHG_r_rm;- *inst++ = U8(MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1]);- *inst++ = GROUP_0F;- *inst++ = cond_set;- *inst++ = MOD_REG | 1 /* ecx */;- *inst++ = OR_rm8_r8;- *inst++ = MOD_REG | (1 /* ecx */ << 3) | 0 /* eax */;- *inst++ = XCHG_r_rm;- *inst++ = U8(MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1]);- }- return SLJIT_SUCCESS;- }-- /* Set TMP_REG1 to the bit. */- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);- FAIL_IF(!inst);- INC_SIZE(1 + 3 + 3 + 1);- *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);- /* Set al to conditional flag. */- *inst++ = GROUP_0F;- *inst++ = cond_set;- *inst++ = MOD_REG | 0 /* eax */;-- *inst++ = GROUP_0F;- *inst++ = MOVZX_r_rm8;- *inst++ = MOD_REG | (0 << 3) /* eax */ | 0 /* eax */;-- *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);-- if (GET_OPCODE(op) < SLJIT_ADD)- 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_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);-#endif /* SLJIT_CONFIG_X86_64 */-}--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_32;-- 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_32;- dst_reg &= ~SLJIT_32;-#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 = U8(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));- ADJUST_LOCAL_OFFSET(dst, dstw);-- CHECK_EXTRA_REGS(dst, dstw, (void)0);--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = 0;-#endif-- ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- 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, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);- return compiler->error;-#else- return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0);-#endif- }-#endif-- if (offset != 0)- 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_s32 dst, sljit_sw dstw, sljit_sw init_value)-{- sljit_u8 *inst;- struct sljit_const *const_;-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- sljit_s32 reg;-#endif-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));- ADJUST_LOCAL_OFFSET(dst, dstw);-- CHECK_EXTRA_REGS(dst, dstw, (void)0);-- const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));- PTR_FAIL_IF(!const_);- set_const(const_, compiler);--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = 0;- reg = FAST_IS_REG(dst) ? dst : TMP_REG1;-- if (emit_load_imm64(compiler, reg, init_value))- return NULL;-#else- if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value))- return NULL;-#endif-- inst = (sljit_u8*)ensure_buf(compiler, 2);- PTR_FAIL_IF(!inst);-- *inst++ = 0;- *inst++ = 2;--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if (dst & SLJIT_MEM)- if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))- return NULL;-#endif-- return const_;-}--SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- struct sljit_put_label *put_label;- sljit_u8 *inst;-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- sljit_s32 reg;- sljit_uw start_size;-#endif-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));- ADJUST_LOCAL_OFFSET(dst, dstw);-- CHECK_EXTRA_REGS(dst, dstw, (void)0);-- put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));- PTR_FAIL_IF(!put_label);- set_put_label(put_label, compiler, 0);--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- compiler->mode32 = 0;- reg = FAST_IS_REG(dst) ? dst : TMP_REG1;-- if (emit_load_imm64(compiler, reg, 0))- return NULL;-#else- if (emit_mov(compiler, dst, dstw, SLJIT_IMM, 0))- return NULL;-#endif--#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)- if (dst & SLJIT_MEM) {- start_size = compiler->size;- if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))- return NULL;- put_label->flags = compiler->size - start_size;- }-#endif-- inst = (sljit_u8*)ensure_buf(compiler, 2);- PTR_FAIL_IF(!inst);-- *inst++ = 0;- *inst++ = 3;-- return put_label;+ return "x86" SLJIT_CPUINFO;+}++/*+ 32b register indexes:+ 0 - EAX+ 1 - ECX+ 2 - EDX+ 3 - EBX+ 4 - ESP+ 5 - EBP+ 6 - ESI+ 7 - EDI+*/++/*+ 64b register indexes:+ 0 - RAX+ 1 - RCX+ 2 - RDX+ 3 - RBX+ 4 - RSP+ 5 - RBP+ 6 - RSI+ 7 - RDI+ 8 - R8 - From now on REX prefix is required+ 9 - R9+ 10 - R10+ 11 - R11+ 12 - R12+ 13 - R13+ 14 - R14+ 15 - R15+*/++#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_FREG (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {+ 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 5, 7, 6, 4, 3+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = {+ 0, 1, 2, 3, 4, 5, 6, 7, 0+};++#define CHECK_EXTRA_REGS(p, w, do) \+ if (p >= SLJIT_R3 && p <= SLJIT_S3) { \+ w = (2 * SSIZE_OF(sw)) + ((p) - SLJIT_R3) * SSIZE_OF(sw); \+ p = SLJIT_MEM1(SLJIT_SP); \+ do; \+ }++#else /* SLJIT_CONFIG_X86_32 */++#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)++/* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present+ Note: avoid to use r12 and r13 for memory addressing+ therefore r12 is better to be a higher saved register. */+#ifndef _WIN64+/* 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, 7, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9+};+/* low-map. reg_map & 0x7. */+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {+ 0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1+};+#else+/* 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, 8, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 9, 10+};+/* low-map. reg_map & 0x7. */+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {+ 0, 0, 2, 0, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 1, 2+};+#endif++/* Args: xmm0-xmm3 */+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = {+ 0, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 4+};+/* low-map. freg_map & 0x7. */+static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = {+ 0, 0, 1, 2, 3, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 4+};++#define REX_W 0x48+#define REX_R 0x44+#define REX_X 0x42+#define REX_B 0x41+#define REX 0x40++#ifndef _WIN64+#define HALFWORD_MAX 0x7fffffffl+#define HALFWORD_MIN -0x80000000l+#else+#define HALFWORD_MAX 0x7fffffffll+#define HALFWORD_MIN -0x80000000ll+#endif++#define IS_HALFWORD(x) ((x) <= HALFWORD_MAX && (x) >= HALFWORD_MIN)+#define NOT_HALFWORD(x) ((x) > HALFWORD_MAX || (x) < HALFWORD_MIN)++#define CHECK_EXTRA_REGS(p, w, do)++#endif /* SLJIT_CONFIG_X86_32 */++#define U8(v) ((sljit_u8)(v))++/* Size flags for emit_x86_instruction: */+#define EX86_BIN_INS ((sljit_uw)0x000010)+#define EX86_SHIFT_INS ((sljit_uw)0x000020)+#define EX86_BYTE_ARG ((sljit_uw)0x000040)+#define EX86_HALF_ARG ((sljit_uw)0x000080)+/* Size flags for both emit_x86_instruction and emit_vex_instruction: */+#define EX86_REX ((sljit_uw)0x000100)+#define EX86_NO_REXW ((sljit_uw)0x000200)+#define EX86_PREF_66 ((sljit_uw)0x000400)+#define EX86_PREF_F2 ((sljit_uw)0x000800)+#define EX86_PREF_F3 ((sljit_uw)0x001000)+#define EX86_SSE2_OP1 ((sljit_uw)0x002000)+#define EX86_SSE2_OP2 ((sljit_uw)0x004000)+#define EX86_SSE2 (EX86_SSE2_OP1 | EX86_SSE2_OP2)+#define EX86_VEX_EXT ((sljit_uw)0x008000)+/* Op flags for emit_vex_instruction: */+#define VEX_OP_0F38 ((sljit_uw)0x010000)+#define VEX_OP_0F3A ((sljit_uw)0x020000)+#define VEX_SSE2_OPV ((sljit_uw)0x040000)+#define VEX_AUTO_W ((sljit_uw)0x080000)+#define VEX_W ((sljit_uw)0x100000)+#define VEX_256 ((sljit_uw)0x200000)++#define EX86_SELECT_66(op) (((op) & SLJIT_32) ? 0 : EX86_PREF_66)+#define EX86_SELECT_F2_F3(op) (((op) & SLJIT_32) ? EX86_PREF_F3 : EX86_PREF_F2)++/* --------------------------------------------------------------------- */+/* Instruction forms */+/* --------------------------------------------------------------------- */++#define ADD (/* BINARY */ 0 << 3)+#define ADD_EAX_i32 0x05+#define ADD_r_rm 0x03+#define ADD_rm_r 0x01+#define ADDSD_x_xm 0x58+#define ADC (/* BINARY */ 2 << 3)+#define ADC_EAX_i32 0x15+#define ADC_r_rm 0x13+#define ADC_rm_r 0x11+#define AND (/* BINARY */ 4 << 3)+#define AND_EAX_i32 0x25+#define AND_r_rm 0x23+#define AND_rm_r 0x21+#define ANDPD_x_xm 0x54+#define BSR_r_rm (/* GROUP_0F */ 0xbd)+#define BSF_r_rm (/* GROUP_0F */ 0xbc)+#define BSWAP_r (/* GROUP_0F */ 0xc8)+#define CALL_i32 0xe8+#define CALL_rm (/* GROUP_FF */ 2 << 3)+#define CDQ 0x99+#define CMOVE_r_rm (/* GROUP_0F */ 0x44)+#define CMP (/* BINARY */ 7 << 3)+#define CMP_EAX_i32 0x3d+#define CMP_r_rm 0x3b+#define CMP_rm_r 0x39+#define CMPS_x_xm 0xc2+#define CMPXCHG_rm_r 0xb1+#define CMPXCHG_rm8_r 0xb0+#define CVTPD2PS_x_xm 0x5a+#define CVTPS2PD_x_xm 0x5a+#define CVTSI2SD_x_rm 0x2a+#define CVTTSD2SI_r_xm 0x2c+#define DIV (/* GROUP_F7 */ 6 << 3)+#define DIVSD_x_xm 0x5e+#define EXTRACTPS_x_xm 0x17+#define FLDS 0xd9+#define FLDL 0xdd+#define FSTPS 0xd9+#define FSTPD 0xdd+#define INSERTPS_x_xm 0x21+#define INT3 0xcc+#define IDIV (/* GROUP_F7 */ 7 << 3)+#define IMUL (/* GROUP_F7 */ 5 << 3)+#define IMUL_r_rm (/* GROUP_0F */ 0xaf)+#define IMUL_r_rm_i8 0x6b+#define IMUL_r_rm_i32 0x69+#define JL_i8 0x7c+#define JE_i8 0x74+#define JNC_i8 0x73+#define JNE_i8 0x75+#define JMP_i8 0xeb+#define JMP_i32 0xe9+#define JMP_rm (/* GROUP_FF */ 4 << 3)+#define LEA_r_m 0x8d+#define LOOP_i8 0xe2+#define LZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbd)+#define MOV_r_rm 0x8b+#define MOV_r_i32 0xb8+#define MOV_rm_r 0x89+#define MOV_rm_i32 0xc7+#define MOV_rm8_i8 0xc6+#define MOV_rm8_r8 0x88+#define MOVAPS_x_xm 0x28+#define MOVAPS_xm_x 0x29+#define MOVD_x_rm 0x6e+#define MOVD_rm_x 0x7e+#define MOVDDUP_x_xm 0x12+#define MOVDQA_x_xm 0x6f+#define MOVDQA_xm_x 0x7f+#define MOVHLPS_x_x 0x12+#define MOVHPD_m_x 0x17+#define MOVHPD_x_m 0x16+#define MOVLHPS_x_x 0x16+#define MOVLPD_m_x 0x13+#define MOVLPD_x_m 0x12+#define MOVMSKPS_r_x (/* GROUP_0F */ 0x50)+#define MOVQ_x_xm (/* GROUP_0F */ 0x7e)+#define MOVSD_x_xm 0x10+#define MOVSD_xm_x 0x11+#define MOVSHDUP_x_xm 0x16+#define MOVSXD_r_rm 0x63+#define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe)+#define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf)+#define MOVUPS_x_xm 0x10+#define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6)+#define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7)+#define MUL (/* GROUP_F7 */ 4 << 3)+#define MULSD_x_xm 0x59+#define NEG_rm (/* GROUP_F7 */ 3 << 3)+#define NOP 0x90+#define NOT_rm (/* GROUP_F7 */ 2 << 3)+#define OR (/* BINARY */ 1 << 3)+#define OR_r_rm 0x0b+#define OR_EAX_i32 0x0d+#define OR_rm_r 0x09+#define OR_rm8_r8 0x08+#define ORPD_x_xm 0x56+#define PACKSSWB_x_xm (/* GROUP_0F */ 0x63)+#define PAND_x_xm 0xdb+#define PCMPEQD_x_xm 0x76+#define PINSRB_x_rm_i8 0x20+#define PINSRW_x_rm_i8 0xc4+#define PINSRD_x_rm_i8 0x22+#define PEXTRB_rm_x_i8 0x14+#define PEXTRW_rm_x_i8 0x15+#define PEXTRD_rm_x_i8 0x16+#define PMOVMSKB_r_x (/* GROUP_0F */ 0xd7)+#define PMOVSXBD_x_xm 0x21+#define PMOVSXBQ_x_xm 0x22+#define PMOVSXBW_x_xm 0x20+#define PMOVSXDQ_x_xm 0x25+#define PMOVSXWD_x_xm 0x23+#define PMOVSXWQ_x_xm 0x24+#define PMOVZXBD_x_xm 0x31+#define PMOVZXBQ_x_xm 0x32+#define PMOVZXBW_x_xm 0x30+#define PMOVZXDQ_x_xm 0x35+#define PMOVZXWD_x_xm 0x33+#define PMOVZXWQ_x_xm 0x34+#define POP_r 0x58+#define POP_rm 0x8f+#define POPF 0x9d+#define POR_x_xm 0xeb+#define PREFETCH 0x18+#define PSHUFB_x_xm 0x00+#define PSHUFD_x_xm 0x70+#define PSHUFLW_x_xm 0x70+#define PSRLDQ_x 0x73+#define PSLLD_x_i8 0x72+#define PSLLQ_x_i8 0x73+#define PUSH_i32 0x68+#define PUSH_r 0x50+#define PUSH_rm (/* GROUP_FF */ 6 << 3)+#define PUSHF 0x9c+#define PXOR_x_xm 0xef+#define ROL (/* SHIFT */ 0 << 3)+#define ROR (/* SHIFT */ 1 << 3)+#define RET_near 0xc3+#define RET_i16 0xc2+#define SBB (/* BINARY */ 3 << 3)+#define SBB_EAX_i32 0x1d+#define SBB_r_rm 0x1b+#define SBB_rm_r 0x19+#define SAR (/* SHIFT */ 7 << 3)+#define SHL (/* SHIFT */ 4 << 3)+#define SHLD (/* GROUP_0F */ 0xa5)+#define SHRD (/* GROUP_0F */ 0xad)+#define SHR (/* SHIFT */ 5 << 3)+#define SHUFPS_x_xm 0xc6+#define SUB (/* BINARY */ 5 << 3)+#define SUB_EAX_i32 0x2d+#define SUB_r_rm 0x2b+#define SUB_rm_r 0x29+#define SUBSD_x_xm 0x5c+#define TEST_EAX_i32 0xa9+#define TEST_rm_r 0x85+#define TZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbc)+#define UCOMISD_x_xm 0x2e+#define UNPCKLPD_x_xm 0x14+#define UNPCKLPS_x_xm 0x14+#define VBROADCASTSD_x_xm 0x19+#define VBROADCASTSS_x_xm 0x18+#define VEXTRACTF128_x_ym 0x19+#define VEXTRACTI128_x_ym 0x39+#define VINSERTF128_y_y_xm 0x18+#define VINSERTI128_y_y_xm 0x38+#define VPBROADCASTB_x_xm 0x78+#define VPBROADCASTD_x_xm 0x58+#define VPBROADCASTQ_x_xm 0x59+#define VPBROADCASTW_x_xm 0x79+#define VPERMPD_y_ym 0x01+#define VPERMQ_y_ym 0x00+#define XCHG_EAX_r 0x90+#define XCHG_r_rm 0x87+#define XOR (/* BINARY */ 6 << 3)+#define XOR_EAX_i32 0x35+#define XOR_r_rm 0x33+#define XOR_rm_r 0x31+#define XORPD_x_xm 0x57++#define GROUP_0F 0x0f+#define GROUP_66 0x66+#define GROUP_F3 0xf3+#define GROUP_F7 0xf7+#define GROUP_FF 0xff+#define GROUP_BINARY_81 0x81+#define GROUP_BINARY_83 0x83+#define GROUP_SHIFT_1 0xd1+#define GROUP_SHIFT_N 0xc1+#define GROUP_SHIFT_CL 0xd3+#define GROUP_LOCK 0xf0++#define MOD_REG 0xc0+#define MOD_DISP8 0x40++#define INC_SIZE(s) (*inst++ = U8(s), compiler->size += (s))++#define PUSH_REG(r) (*inst++ = U8(PUSH_r + (r)))+#define POP_REG(r) (*inst++ = U8(POP_r + (r)))+#define RET() (*inst++ = RET_near)+#define RET_I16(n) (*inst++ = RET_i16, *inst++ = U8(n), *inst++ = 0)++#define SLJIT_INST_LABEL 255+#define SLJIT_INST_JUMP 254+#define SLJIT_INST_MOV_ADDR 253+#define SLJIT_INST_CONST 252++/* Multithreading does not affect these static variables, since they store+ built-in CPU features. Therefore they can be overwritten by different threads+ if they detect the CPU features in the same time. */+#define CPU_FEATURE_DETECTED 0x001+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)+#define CPU_FEATURE_SSE2 0x002+#endif+#define CPU_FEATURE_SSE41 0x004+#define CPU_FEATURE_LZCNT 0x008+#define CPU_FEATURE_TZCNT 0x010+#define CPU_FEATURE_CMOV 0x020+#define CPU_FEATURE_AVX 0x040+#define CPU_FEATURE_AVX2 0x080+#define CPU_FEATURE_OSXSAVE 0x100++static sljit_u32 cpu_feature_list = 0;++#ifdef _WIN32_WCE+#include <cmnintrin.h>+#elif defined(_MSC_VER) && _MSC_VER >= 1400+#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 execute_cpu_id(sljit_u32 info[4])+{+#if defined(_MSC_VER) && _MSC_VER >= 1400++ __cpuidex((int*)info, (int)info[0], (int)info[2]);++#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__TINYC__)++ /* AT&T syntax. */+ __asm__ (+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ "movl %0, %%esi\n"+ "movl (%%esi), %%eax\n"+ "movl 8(%%esi), %%ecx\n"+ "pushl %%ebx\n"+ "cpuid\n"+ "movl %%eax, (%%esi)\n"+ "movl %%ebx, 4(%%esi)\n"+ "popl %%ebx\n"+ "movl %%ecx, 8(%%esi)\n"+ "movl %%edx, 12(%%esi)\n"+#else /* !SLJIT_CONFIG_X86_32 */+ "movq %0, %%rsi\n"+ "movl (%%rsi), %%eax\n"+ "movl 8(%%rsi), %%ecx\n"+ "cpuid\n"+ "movl %%eax, (%%rsi)\n"+ "movl %%ebx, 4(%%rsi)\n"+ "movl %%ecx, 8(%%rsi)\n"+ "movl %%edx, 12(%%rsi)\n"+#endif /* SLJIT_CONFIG_X86_32 */+ :+ : "r" (info)+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ : "memory", "eax", "ecx", "edx", "esi"+#else /* !SLJIT_CONFIG_X86_32 */+ : "memory", "rax", "rbx", "rcx", "rdx", "rsi"+#endif /* SLJIT_CONFIG_X86_32 */+ );++#else /* _MSC_VER < 1400 */++ /* Intel syntax. */+ __asm {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ mov esi, info+ mov eax, [esi]+ mov ecx, [esi + 8]+ cpuid+ mov [esi], eax+ mov [esi + 4], ebx+ mov [esi + 8], ecx+ mov [esi + 12], edx+#else /* !SLJIT_CONFIG_X86_32 */+ mov rsi, info+ mov eax, [rsi]+ mov ecx, [rsi + 8]+ cpuid+ mov [rsi], eax+ mov [rsi + 4], ebx+ mov [rsi + 8], ecx+ mov [rsi + 12], edx+#endif /* SLJIT_CONFIG_X86_32 */+ }++#endif /* _MSC_VER && _MSC_VER >= 1400 */+}++static sljit_u32 execute_get_xcr0_low(void)+{+ sljit_u32 xcr0;++#if defined(_MSC_VER) && _MSC_VER >= 1400++ xcr0 = (sljit_u32)_xgetbv(0);++#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__TINYC__)++ /* AT&T syntax. */+ __asm__ (+ "xorl %%ecx, %%ecx\n"+ "xgetbv\n"+ : "=a" (xcr0)+ :+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ : "ecx", "edx"+#else /* !SLJIT_CONFIG_X86_32 */+ : "rcx", "rdx"+#endif /* SLJIT_CONFIG_X86_32 */+ );++#else /* _MSC_VER < 1400 */++ /* Intel syntax. */+ __asm {+ mov ecx, 0+ xgetbv+ mov xcr0, eax+ }++#endif /* _MSC_VER && _MSC_VER >= 1400 */+ return xcr0;+}++static void get_cpu_features(void)+{+ sljit_u32 feature_list = CPU_FEATURE_DETECTED;+ sljit_u32 info[4] = {0};+ sljit_u32 max_id;++ execute_cpu_id(info);+ max_id = info[0];++ if (max_id >= 7) {+ info[0] = 7;+ info[2] = 0;+ execute_cpu_id(info);++ if (info[1] & 0x8)+ feature_list |= CPU_FEATURE_TZCNT;+ if (info[1] & 0x20)+ feature_list |= CPU_FEATURE_AVX2;+ }++ if (max_id >= 1) {+ info[0] = 1;+ execute_cpu_id(info);++ if (info[2] & 0x80000)+ feature_list |= CPU_FEATURE_SSE41;+ if (info[2] & 0x8000000)+ feature_list |= CPU_FEATURE_OSXSAVE;+ if (info[2] & 0x10000000)+ feature_list |= CPU_FEATURE_AVX;+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)+ if (info[3] & 0x4000000)+ feature_list |= CPU_FEATURE_SSE2;+#endif+ if (info[3] & 0x8000)+ feature_list |= CPU_FEATURE_CMOV;+ }++ info[0] = 0x80000001;+ execute_cpu_id(info);++ if (info[2] & 0x20)+ feature_list |= CPU_FEATURE_LZCNT;++ if ((feature_list & CPU_FEATURE_OSXSAVE) && (execute_get_xcr0_low() & 0x4) == 0)+ feature_list &= ~(sljit_u32)(CPU_FEATURE_AVX | CPU_FEATURE_AVX2);++ cpu_feature_list = feature_list;+}++static sljit_u8 get_jump_code(sljit_uw type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_ATOMIC_STORED:+ case SLJIT_F_EQUAL:+ case SLJIT_UNORDERED_OR_EQUAL:+ return 0x84 /* je */;++ case SLJIT_NOT_EQUAL:+ case SLJIT_ATOMIC_NOT_STORED:+ case SLJIT_F_NOT_EQUAL:+ case SLJIT_ORDERED_NOT_EQUAL:+ return 0x85 /* jne */;++ case SLJIT_LESS:+ case SLJIT_CARRY:+ case SLJIT_F_LESS:+ case SLJIT_UNORDERED_OR_LESS:+ case SLJIT_UNORDERED_OR_GREATER:+ return 0x82 /* jc */;++ case SLJIT_GREATER_EQUAL:+ case SLJIT_NOT_CARRY:+ case SLJIT_F_GREATER_EQUAL:+ case SLJIT_ORDERED_GREATER_EQUAL:+ case SLJIT_ORDERED_LESS_EQUAL:+ return 0x83 /* jae */;++ case SLJIT_GREATER:+ case SLJIT_F_GREATER:+ case SLJIT_ORDERED_LESS:+ case SLJIT_ORDERED_GREATER:+ return 0x87 /* jnbe */;++ case SLJIT_LESS_EQUAL:+ case SLJIT_F_LESS_EQUAL:+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:+ case SLJIT_UNORDERED_OR_LESS_EQUAL:+ return 0x86 /* jbe */;++ case SLJIT_SIG_LESS:+ return 0x8c /* jl */;++ case SLJIT_SIG_GREATER_EQUAL:+ return 0x8d /* jnl */;++ case SLJIT_SIG_GREATER:+ return 0x8f /* jnle */;++ case SLJIT_SIG_LESS_EQUAL:+ return 0x8e /* jle */;++ case SLJIT_OVERFLOW:+ return 0x80 /* jo */;++ case SLJIT_NOT_OVERFLOW:+ return 0x81 /* jno */;++ case SLJIT_UNORDERED:+ case SLJIT_ORDERED_EQUAL: /* NaN. */+ return 0x8a /* jp */;++ case SLJIT_ORDERED:+ case SLJIT_UNORDERED_OR_NOT_EQUAL: /* Not NaN. */+ return 0x8b /* jpo */;+ }+ return 0;+}++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset);+#else /* !SLJIT_CONFIG_X86_32 */+static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr);+static sljit_u8* generate_mov_addr_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset);+#endif /* SLJIT_CONFIG_X86_32 */++static sljit_u8* detect_near_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)+{+ sljit_uw type = jump->flags >> TYPE_SHIFT;+ sljit_s32 short_jump;+ sljit_uw label_addr;++ if (jump->flags & JUMP_ADDR)+ label_addr = jump->u.target - (sljit_uw)executable_offset;+ else+ label_addr = (sljit_uw)(code + jump->u.label->size);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((sljit_sw)(label_addr - (sljit_uw)(code_ptr + 6)) > HALFWORD_MAX || (sljit_sw)(label_addr - (sljit_uw)(code_ptr + 5)) < HALFWORD_MIN)+ return detect_far_jump_type(jump, code_ptr);+#endif /* SLJIT_CONFIG_X86_64 */++ short_jump = (sljit_sw)(label_addr - (sljit_uw)(code_ptr + 2)) >= -0x80 && (sljit_sw)(label_addr - (sljit_uw)(code_ptr + 2)) <= 0x7f;++ if (type == SLJIT_JUMP) {+ if (short_jump)+ *code_ptr++ = JMP_i8;+ else+ *code_ptr++ = JMP_i32;+ } else if (type > SLJIT_JUMP) {+ short_jump = 0;+ *code_ptr++ = CALL_i32;+ } else if (short_jump) {+ *code_ptr++ = U8(get_jump_code(type) - 0x10);+ } else {+ *code_ptr++ = GROUP_0F;+ *code_ptr++ = get_jump_code(type);+ }++ jump->addr = (sljit_uw)code_ptr;++ if (short_jump) {+ jump->flags |= PATCH_MB;+ code_ptr += sizeof(sljit_s8);+ } else {+ jump->flags |= PATCH_MW;+ code_ptr += sizeof(sljit_s32);+ }++ return code_ptr;+}++static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)+{+ sljit_uw flags = jump->flags;+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;+ sljit_uw jump_addr = jump->addr;+ SLJIT_UNUSED_ARG(executable_offset);++ if (SLJIT_UNLIKELY(flags & JUMP_MOV_ADDR)) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_unaligned_store_sw((void*)(jump_addr - sizeof(sljit_sw)), (sljit_sw)addr);+#else /* SLJIT_CONFIG_X86_32 */+ if (flags & PATCH_MD) {+ SLJIT_ASSERT(addr > HALFWORD_MAX);+ sljit_unaligned_store_sw((void*)(jump_addr - sizeof(sljit_sw)), (sljit_sw)addr);+ return;+ }++ if (flags & PATCH_MW) {+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET((sljit_u8*)jump_addr, executable_offset);+ SLJIT_ASSERT((sljit_sw)addr <= HALFWORD_MAX && (sljit_sw)addr >= HALFWORD_MIN);+ } else {+ SLJIT_ASSERT(addr <= HALFWORD_MAX);+ }+ sljit_unaligned_store_s32((void*)(jump_addr - sizeof(sljit_s32)), (sljit_s32)addr);+#endif /* !SLJIT_CONFIG_X86_32 */+ return;+ }++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (SLJIT_UNLIKELY(flags & PATCH_MD)) {+ SLJIT_ASSERT(!(flags & JUMP_ADDR));+ sljit_unaligned_store_sw((void*)jump_addr, (sljit_sw)addr);+ return;+ }+#endif /* SLJIT_CONFIG_X86_64 */++ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET((sljit_u8*)jump_addr, executable_offset);++ if (flags & PATCH_MB) {+ addr -= sizeof(sljit_s8);+ SLJIT_ASSERT((sljit_sw)addr <= 0x7f && (sljit_sw)addr >= -0x80);+ *(sljit_u8*)jump_addr = U8(addr);+ return;+ } else if (flags & PATCH_MW) {+ addr -= sizeof(sljit_s32);+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_unaligned_store_sw((void*)jump_addr, (sljit_sw)addr);+#else /* !SLJIT_CONFIG_X86_32 */+ SLJIT_ASSERT((sljit_sw)addr <= HALFWORD_MAX && (sljit_sw)addr >= HALFWORD_MIN);+ sljit_unaligned_store_s32((void*)jump_addr, (sljit_s32)addr);+#endif /* SLJIT_CONFIG_X86_32 */+ }+}++static void reduce_code_size(struct sljit_compiler *compiler)+{+ struct sljit_label *label;+ struct sljit_jump *jump;+ sljit_uw next_label_size;+ sljit_uw next_jump_addr;+ sljit_uw next_min_addr;+ sljit_uw size_reduce = 0;+ sljit_sw diff;+ sljit_uw type;+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ sljit_uw size_reduce_max;+#endif /* SLJIT_DEBUG */++ label = compiler->labels;+ jump = compiler->jumps;++ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);++ while (1) {+ next_min_addr = next_label_size;+ if (next_jump_addr < next_min_addr)+ next_min_addr = next_jump_addr;++ if (next_min_addr == SLJIT_MAX_ADDRESS)+ break;++ if (next_min_addr == next_label_size) {+ label->size -= size_reduce;++ label = label->next;+ next_label_size = SLJIT_GET_NEXT_SIZE(label);+ }++ if (next_min_addr != next_jump_addr)+ continue;++ if (!(jump->flags & JUMP_MOV_ADDR)) {+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ size_reduce_max = size_reduce + (((jump->flags >> TYPE_SHIFT) < SLJIT_JUMP) ? CJUMP_MAX_SIZE : JUMP_MAX_SIZE);+#endif /* SLJIT_DEBUG */++ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {+ if (jump->flags & JUMP_ADDR) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (jump->u.target <= 0xffffffffl)+ size_reduce += sizeof(sljit_s32);+#endif /* SLJIT_CONFIG_X86_64 */+ } else {+ /* Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)(jump->addr - size_reduce);+ type = jump->flags >> TYPE_SHIFT;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (type == SLJIT_JUMP) {+ if (diff <= 0x7f + 2 && diff >= -0x80 + 2)+ size_reduce += JUMP_MAX_SIZE - 2;+ else if (diff <= HALFWORD_MAX + 5 && diff >= HALFWORD_MIN + 5)+ size_reduce += JUMP_MAX_SIZE - 5;+ } else if (type < SLJIT_JUMP) {+ if (diff <= 0x7f + 2 && diff >= -0x80 + 2)+ size_reduce += CJUMP_MAX_SIZE - 2;+ else if (diff <= HALFWORD_MAX + 6 && diff >= HALFWORD_MIN + 6)+ size_reduce += CJUMP_MAX_SIZE - 6;+ } else {+ if (diff <= HALFWORD_MAX + 5 && diff >= HALFWORD_MIN + 5)+ size_reduce += JUMP_MAX_SIZE - 5;+ }+#else /* !SLJIT_CONFIG_X86_64 */+ if (type == SLJIT_JUMP) {+ if (diff <= 0x7f + 2 && diff >= -0x80 + 2)+ size_reduce += JUMP_MAX_SIZE - 2;+ } else if (type < SLJIT_JUMP) {+ if (diff <= 0x7f + 2 && diff >= -0x80 + 2)+ size_reduce += CJUMP_MAX_SIZE - 2;+ }+#endif /* SLJIT_CONFIG_X86_64 */+ }+ }++#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ jump->flags |= (size_reduce_max - size_reduce) << JUMP_SIZE_SHIFT;+#endif /* SLJIT_DEBUG */+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ } else {+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ size_reduce_max = size_reduce + 10;+#endif /* SLJIT_DEBUG */++ if (!(jump->flags & JUMP_ADDR)) {+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)(jump->addr - size_reduce - 3);++ if (diff <= HALFWORD_MAX && diff >= HALFWORD_MIN)+ size_reduce += 3;+ } else if (jump->u.target <= 0xffffffffl)+ size_reduce += (jump->flags & MOV_ADDR_HI) ? 4 : 5;++#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ jump->flags |= (size_reduce_max - size_reduce) << JUMP_SIZE_SHIFT;+#endif /* SLJIT_DEBUG */+#endif /* SLJIT_CONFIG_X86_64 */+ }++ jump = jump->next;+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);+ }++ compiler->size -= size_reduce;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)+{+ struct sljit_memory_fragment *buf;+ sljit_u8 *code;+ sljit_u8 *code_ptr;+ sljit_u8 *buf_ptr;+ sljit_u8 *buf_end;+ sljit_u8 len;+ sljit_sw executable_offset;+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ sljit_uw addr;+#endif /* SLJIT_DEBUG */++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));++ reduce_code_size(compiler);++ /* Second code generation pass. */+ code = (sljit_u8*)allocate_executable_memory(compiler->size, options, exec_allocator_data, &executable_offset);+ PTR_FAIL_WITH_EXEC_IF(code);++ reverse_buf(compiler);+ buf = compiler->buf;++ code_ptr = code;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;++ do {+ buf_ptr = buf->memory;+ buf_end = buf_ptr + buf->used_size;+ do {+ len = *buf_ptr++;+ SLJIT_ASSERT(len > 0);+ if (len < SLJIT_INST_CONST) {+ /* The code is already generated. */+ SLJIT_MEMCPY(code_ptr, buf_ptr, len);+ code_ptr += len;+ buf_ptr += len;+ } else {+ switch (len) {+ case SLJIT_INST_LABEL:+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = (sljit_uw)(code_ptr - code);+ label = label->next;+ break;+ case SLJIT_INST_JUMP:+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ addr = (sljit_uw)code_ptr;+#endif /* SLJIT_DEBUG */+ if (!(jump->flags & SLJIT_REWRITABLE_JUMP))+ code_ptr = detect_near_jump_type(jump, code_ptr, code, executable_offset);+ else {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ code_ptr = detect_far_jump_type(jump, code_ptr, executable_offset);+#else /* !SLJIT_CONFIG_X86_32 */+ code_ptr = detect_far_jump_type(jump, code_ptr);+#endif /* SLJIT_CONFIG_X86_32 */+ }++ SLJIT_ASSERT((sljit_uw)code_ptr - addr <= ((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f));+ jump = jump->next;+ break;+ case SLJIT_INST_MOV_ADDR:+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ code_ptr = generate_mov_addr_code(jump, code_ptr, code, executable_offset);+#endif /* SLJIT_CONFIG_X86_64 */+ jump->addr = (sljit_uw)code_ptr;+ jump = jump->next;+ break;+ default:+ SLJIT_ASSERT(len == SLJIT_INST_CONST);+ const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);+ const_ = const_->next;+ break;+ }+ }+ } while (buf_ptr < buf_end);++ SLJIT_ASSERT(buf_ptr == buf_end);+ buf = buf->next;+ } while (buf);++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(code_ptr <= code + compiler->size);++ jump = compiler->jumps;+ while (jump) {+ generate_jump_or_mov_addr(jump, executable_offset);+ jump = jump->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (sljit_uw)(code_ptr - code);++ code = (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);++ SLJIT_UPDATE_WX_FLAGS(code, (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset), 1);+ return (void*)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) != 0;+#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)+ if (cpu_feature_list == 0)+ get_cpu_features();+ return (cpu_feature_list & CPU_FEATURE_SSE2) != 0;+#else /* SLJIT_DETECT_SSE2 */+ return 1;+#endif /* SLJIT_DETECT_SSE2 */++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ case SLJIT_HAS_VIRTUAL_REGISTERS:+ return 1;+#endif /* SLJIT_CONFIG_X86_32 */++ case SLJIT_HAS_CLZ:+ if (cpu_feature_list == 0)+ get_cpu_features();++ return (cpu_feature_list & CPU_FEATURE_LZCNT) ? 1 : 2;++ case SLJIT_HAS_CTZ:+ if (cpu_feature_list == 0)+ get_cpu_features();++ return (cpu_feature_list & CPU_FEATURE_TZCNT) ? 1 : 2;++ case SLJIT_HAS_CMOV:+ if (cpu_feature_list == 0)+ get_cpu_features();+ return (cpu_feature_list & CPU_FEATURE_CMOV) != 0;++ case SLJIT_HAS_REV:+ case SLJIT_HAS_ROT:+ case SLJIT_HAS_PREFETCH:+ case SLJIT_HAS_COPY_F32:+ case SLJIT_HAS_COPY_F64:+ case SLJIT_HAS_ATOMIC:+ return 1;++#if !(defined SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE+ case SLJIT_HAS_AVX:+ if (cpu_feature_list == 0)+ get_cpu_features();+ return (cpu_feature_list & CPU_FEATURE_AVX) != 0;+ case SLJIT_HAS_AVX2:+ if (cpu_feature_list == 0)+ get_cpu_features();+ return (cpu_feature_list & CPU_FEATURE_AVX2) != 0;+ case SLJIT_HAS_SIMD:+ if (cpu_feature_list == 0)+ get_cpu_features();+ return (cpu_feature_list & CPU_FEATURE_SSE41) != 0;+#endif /* SLJIT_IS_FPU_AVAILABLE */+ default:+ return 0;+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)+{+ switch (type) {+ case SLJIT_ORDERED_EQUAL:+ case SLJIT_UNORDERED_OR_NOT_EQUAL:+ return 2;+ }++ return 0;+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++#define BINARY_OPCODE(opcode) (((opcode ## _EAX_i32) << 24) | ((opcode ## _r_rm) << 16) | ((opcode ## _rm_r) << 8) | (opcode))++#define BINARY_IMM32(op_imm, immw, arg, argw) \+ do { \+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \+ FAIL_IF(!inst); \+ *(inst + 1) |= (op_imm); \+ } while (0)++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)++#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \+ do { \+ if (IS_HALFWORD(immw) || compiler->mode32) { \+ BINARY_IMM32(op_imm, immw, arg, argw); \+ } \+ else { \+ FAIL_IF(emit_load_imm64(compiler, FAST_IS_REG(arg) ? TMP_REG2 : TMP_REG1, immw)); \+ inst = emit_x86_instruction(compiler, 1, FAST_IS_REG(arg) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \+ FAIL_IF(!inst); \+ *inst = (op_mr); \+ } \+ } while (0)++#define BINARY_EAX_IMM(op_eax_imm, immw) \+ FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw))++#else /* !SLJIT_CONFIG_X86_64 */++#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \+ BINARY_IMM32(op_imm, immw, arg, argw)++#define BINARY_EAX_IMM(op_eax_imm, immw) \+ FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw))++#endif /* SLJIT_CONFIG_X86_64 */++static sljit_s32 emit_byte(struct sljit_compiler *compiler, sljit_u8 byte)+{+ sljit_u8 *inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ *inst = byte;+ return SLJIT_SUCCESS;+}++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));++static sljit_s32 emit_groupf(struct sljit_compiler *compiler,+ sljit_uw op,+ sljit_s32 dst, sljit_s32 src, sljit_sw srcw);++static sljit_s32 emit_groupf_ext(struct sljit_compiler *compiler,+ sljit_uw op,+ sljit_s32 dst, sljit_s32 src, sljit_sw srcw);++static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,+ sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src);++static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,+ sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw);++static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++static sljit_s32 emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw);++static SLJIT_INLINE sljit_s32 emit_endbranch(struct sljit_compiler *compiler)+{+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)+ /* Emit endbr32/endbr64 when CET is enabled. */+ sljit_u8 *inst;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ inst[0] = GROUP_F3;+ inst[1] = GROUP_0F;+ inst[2] = 0x1e;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ inst[3] = 0xfb;+#else /* !SLJIT_CONFIG_X86_32 */+ inst[3] = 0xfa;+#endif /* SLJIT_CONFIG_X86_32 */+#else /* !SLJIT_CONFIG_X86_CET */+ SLJIT_UNUSED_ARG(compiler);+#endif /* SLJIT_CONFIG_X86_CET */+ return SLJIT_SUCCESS;+}++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)++static SLJIT_INLINE sljit_s32 emit_rdssp(struct sljit_compiler *compiler, sljit_s32 reg)+{+ sljit_u8 *inst;+ sljit_s32 size;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ size = 5;+#else+ size = 4;+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ *inst++ = GROUP_F3;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);+#endif+ inst[0] = GROUP_0F;+ inst[1] = 0x1e;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ inst[2] = U8(MOD_REG | (0x1 << 3) | reg_lmap[reg]);+#else+ inst[2] = U8(MOD_REG | (0x1 << 3) | reg_map[reg]);+#endif+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_incssp(struct sljit_compiler *compiler, sljit_s32 reg)+{+ sljit_u8 *inst;+ sljit_s32 size;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ size = 5;+#else+ size = 4;+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ *inst++ = GROUP_F3;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);+#endif+ inst[0] = GROUP_0F;+ inst[1] = 0xae;+ inst[2] = (0x3 << 6) | (0x5 << 3) | (reg_map[reg] & 0x7);+ return SLJIT_SUCCESS;+}++#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */++static SLJIT_INLINE sljit_s32 cpu_has_shadow_stack(void)+{+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)+ return _get_ssp() != 0;+#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */+ return 0;+#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */+}++static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)+ sljit_u8 *inst, *jz_after_cmp_inst;+ sljit_uw size_jz_after_cmp_inst;++ sljit_uw size_before_rdssp_inst = compiler->size;++ /* Generate "RDSSP TMP_REG1". */+ FAIL_IF(emit_rdssp(compiler, TMP_REG1));++ /* Load return address on shadow stack into TMP_REG1. */+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), 0);++ /* Compare return address against TMP_REG1. */+ FAIL_IF(emit_cmp_binary (compiler, TMP_REG1, 0, src, srcw));++ /* Generate JZ to skip shadow stack ajdustment when shadow+ stack matches normal stack. */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ *inst++ = get_jump_code(SLJIT_EQUAL) - 0x10;+ size_jz_after_cmp_inst = compiler->size;+ jz_after_cmp_inst = inst;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ /* REX_W is not necessary. */+ compiler->mode32 = 1;+#endif+ /* Load 1 into TMP_REG1. */+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1);++ /* Generate "INCSSP TMP_REG1". */+ FAIL_IF(emit_incssp(compiler, TMP_REG1));++ /* Jump back to "RDSSP TMP_REG1" to check shadow stack again. */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = JMP_i8;+ inst[1] = size_before_rdssp_inst - compiler->size;++ *jz_after_cmp_inst = compiler->size - size_jz_after_cmp_inst;+#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);+#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */+ return SLJIT_SUCCESS;+}++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+#include "sljitNativeX86_32.c"+#else+#include "sljitNativeX86_64.c"+#endif++static sljit_s32 emit_mov(struct sljit_compiler *compiler,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;++ if (FAST_IS_REG(src)) {+ inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_r;+ return SLJIT_SUCCESS;+ }++ if (src == SLJIT_IMM) {+ if (FAST_IS_REG(dst)) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);+#else+ if (!compiler->mode32) {+ if (NOT_HALFWORD(srcw))+ return emit_load_imm64(compiler, dst, srcw);+ }+ else+ return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, U8(MOV_r_i32 | reg_lmap[dst]), srcw);+#endif+ }+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (!compiler->mode32 && NOT_HALFWORD(srcw)) {+ /* 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;+ }+#endif+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ return SLJIT_SUCCESS;+ }+ if (FAST_IS_REG(dst)) {+ inst = emit_x86_instruction(compiler, 1, dst, 0, src, srcw);+ FAIL_IF(!inst);+ *inst = MOV_r_rm;+ return SLJIT_SUCCESS;+ }++ /* 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;+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_r;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;+ sljit_uw size;++ SLJIT_ASSERT(type >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = U8(get_jump_code((sljit_uw)type ^ 0x1) - 0x10);++ size = compiler->size;+ EMIT_MOV(compiler, dst_reg, 0, src, srcw);++ inst[1] = U8(compiler->size - size);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+ sljit_u8 *inst;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_uw size;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ switch (GET_OPCODE(op)) {+ case SLJIT_BREAKPOINT:+ return emit_byte(compiler, INT3);+ case SLJIT_NOP:+ return emit_byte(compiler, NOP);+ 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_ASSERT(+ reg_map[SLJIT_R0] == 0+ && reg_map[SLJIT_R1] == 2+ && reg_map[TMP_REG1] > 7);+#else+ SLJIT_ASSERT(+ reg_map[SLJIT_R0] == 0+ && reg_map[SLJIT_R1] < 7+ && reg_map[TMP_REG1] == 2);+#endif+ compiler->mode32 = op & SLJIT_32;+#endif+ 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_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);+#else+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);+#endif+ FAIL_IF(!inst);+ *inst = XOR_r_rm;+ }++ 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)+ FAIL_IF(emit_byte(compiler, CDQ));+#else+ if (!compiler->mode32) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = REX_W;+ inst[1] = CDQ;+ } else+ FAIL_IF(emit_byte(compiler, CDQ));+#endif+ }++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = GROUP_F7;+ inst[1] = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);+#else /* !SLJIT_CONFIG_X86_32 */+#ifdef _WIN64+ size = (!compiler->mode32 || op >= SLJIT_DIVMOD_UW) ? 3 : 2;+#else /* !_WIN64 */+ size = (!compiler->mode32) ? 3 : 2;+#endif /* _WIN64 */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+#ifdef _WIN64+ if (!compiler->mode32)+ *inst++ = REX_W | ((op >= SLJIT_DIVMOD_UW) ? REX_B : 0);+ else if (op >= SLJIT_DIVMOD_UW)+ *inst++ = REX_B;+ inst[0] = GROUP_F7;+ inst[1] = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);+#else /* !_WIN64 */+ if (!compiler->mode32)+ *inst++ = REX_W;+ inst[0] = GROUP_F7;+ inst[1] = MOD_REG | reg_map[SLJIT_R1];+#endif /* _WIN64 */+#endif /* SLJIT_CONFIG_X86_32 */+ switch (op) {+ case SLJIT_LMUL_UW:+ inst[1] |= MUL;+ break;+ case SLJIT_LMUL_SW:+ inst[1] |= IMUL;+ break;+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIV_UW:+ inst[1] |= DIV;+ break;+ case SLJIT_DIVMOD_SW:+ case SLJIT_DIV_SW:+ inst[1] |= IDIV;+ break;+ }+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)+ if (op <= SLJIT_DIVMOD_SW)+ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);+#else+ if (op >= SLJIT_DIV_UW)+ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);+#endif+ break;+ case SLJIT_ENDBR:+ return emit_endbranch(compiler);+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return skip_frames_before_return(compiler);+ }++ return SLJIT_SUCCESS;+}++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_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)) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);+#else+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ return SLJIT_SUCCESS;+#endif+ }+ inst = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm8_i8;+ return SLJIT_SUCCESS;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (reg_map[src] >= 4) {+ SLJIT_ASSERT(dst_r == TMP_REG1);+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);+ } else+ dst_r = src;+#else+ dst_r = src;+#endif+ } else {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (FAST_IS_REG(src) && reg_map[src] >= 4) {+ /* Both src and dst are registers. */+ SLJIT_ASSERT(FAST_IS_REG(dst));++ if (src == dst && !sign) {+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0xff, dst, 0);+ FAIL_IF(!inst);+ *(inst + 1) |= AND;+ return SLJIT_SUCCESS;+ }++ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);+ src = TMP_REG1;+ srcw = 0;+ }+#endif /* !SLJIT_CONFIG_X86_32 */++ /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */+ FAIL_IF(emit_groupf(compiler, sign ? MOVSX_r_rm8 : MOVZX_r_rm8, dst_r, src, srcw));+ }++ if (dst & SLJIT_MEM) {+ inst = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm8_r8;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif++ inst = emit_x86_instruction(compiler, 2, 0, 0, src, srcw);+ FAIL_IF(!inst);+ inst[0] = GROUP_0F;+ inst[1] = PREFETCH;++ if (op == SLJIT_PREFETCH_L1)+ inst[2] |= (1 << 3);+ else if (op == SLJIT_PREFETCH_L2)+ inst[2] |= (2 << 3);+ else if (op == SLJIT_PREFETCH_L3)+ inst[2] |= (3 << 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)) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);+#else+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ return SLJIT_SUCCESS;+#endif+ }+ inst = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ return SLJIT_SUCCESS;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if ((dst & SLJIT_MEM) && FAST_IS_REG(src))+ dst_r = src;+ else+ FAIL_IF(emit_groupf(compiler, sign ? MOVSX_r_rm16 : MOVZX_r_rm16, dst_r, src, srcw));++ if (dst & SLJIT_MEM) {+ inst = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_r;+ }++ return SLJIT_SUCCESS;+}++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_u8* inst;++ if (dst == src && dstw == srcw) {+ /* Same input and output */+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);+ FAIL_IF(!inst);+ inst[0] = GROUP_F7;+ inst[1] |= opcode;+ return SLJIT_SUCCESS;+ }++ if (FAST_IS_REG(dst)) {+ EMIT_MOV(compiler, dst, 0, src, srcw);+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);+ FAIL_IF(!inst);+ inst[0] = GROUP_F7;+ inst[1] |= 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);+ inst[0] = GROUP_F7;+ inst[1] |= opcode;+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+}++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+static const sljit_sw emit_clz_arg = 32 + 31;+static const sljit_sw emit_ctz_arg = 32;+#endif++static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 is_clz,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;+ sljit_s32 dst_r;+ sljit_sw max;++ SLJIT_ASSERT(cpu_feature_list != 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (is_clz ? (cpu_feature_list & CPU_FEATURE_LZCNT) : (cpu_feature_list & CPU_FEATURE_TZCNT)) {+ FAIL_IF(emit_groupf(compiler, (is_clz ? LZCNT_r_rm : TZCNT_r_rm) | EX86_PREF_F3, dst_r, src, srcw));++ if (dst & SLJIT_MEM)+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+ }++ FAIL_IF(emit_groupf(compiler, is_clz ? BSR_r_rm : BSF_r_rm, dst_r, src, srcw));++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ max = is_clz ? (32 + 31) : 32;++ if (cpu_feature_list & CPU_FEATURE_CMOV) {+ if (dst_r != TMP_REG1) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, max);+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0);+ }+ else+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), is_clz ? (sljit_sw)&emit_clz_arg : (sljit_sw)&emit_ctz_arg);++ FAIL_IF(!inst);+ inst[0] = GROUP_0F;+ inst[1] = CMOVE_r_rm;+ }+ else+ FAIL_IF(emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max));++ if (is_clz) {+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);+ FAIL_IF(!inst);+ *(inst + 1) |= XOR;+ }+#else+ if (is_clz)+ max = compiler->mode32 ? (32 + 31) : (64 + 63);+ else+ max = compiler->mode32 ? 32 : 64;++ if (cpu_feature_list & CPU_FEATURE_CMOV) {+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, max);+ FAIL_IF(emit_groupf(compiler, CMOVE_r_rm, dst_r, TMP_REG2, 0));+ } else+ FAIL_IF(emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max));++ if (is_clz) {+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, max >> 1, dst_r, 0);+ FAIL_IF(!inst);+ *(inst + 1) |= XOR;+ }+#endif++ if (dst & SLJIT_MEM)+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_bswap(struct sljit_compiler *compiler,+ sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8 *inst;+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ sljit_uw size;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_u8 rex = 0;+#else /* !SLJIT_CONFIG_X86_64 */+ sljit_s32 dst_is_ereg = op & SLJIT_32;+#endif /* SLJIT_CONFIG_X86_64 */++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (op == SLJIT_REV_U32 || op == SLJIT_REV_S32)+ compiler->mode32 = 1;+#else /* !SLJIT_CONFIG_X86_64 */+ op &= ~SLJIT_32;+#endif /* SLJIT_CONFIG_X86_64 */++ if (src != dst_r) {+ /* Only the lower 16 bit is read for eregs. */+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16)+ FAIL_IF(emit_mov_half(compiler, 0, dst_r, 0, src, srcw));+ else+ EMIT_MOV(compiler, dst_r, 0, src, srcw);+ }++ size = 2;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (!compiler->mode32)+ rex = REX_W;++ if (reg_map[dst_r] >= 8)+ rex |= REX_B;++ if (rex != 0)+ size++;+#endif /* SLJIT_CONFIG_X86_64 */++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (rex != 0)+ *inst++ = rex;++ inst[0] = GROUP_0F;+ inst[1] = BSWAP_r | reg_lmap[dst_r];+#else /* !SLJIT_CONFIG_X86_64 */+ inst[0] = GROUP_0F;+ inst[1] = BSWAP_r | reg_map[dst_r];+#endif /* SLJIT_CONFIG_X86_64 */++ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ size = compiler->mode32 ? 16 : 48;+#else /* !SLJIT_CONFIG_X86_64 */+ size = 16;+#endif /* SLJIT_CONFIG_X86_64 */++ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, (sljit_sw)size, dst_r, 0);+ FAIL_IF(!inst);+ if (op == SLJIT_REV_U16)+ inst[1] |= SHR;+ else+ inst[1] |= SAR;+ }++ if (dst & SLJIT_MEM) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (dst_is_ereg)+ op = SLJIT_REV;+#endif /* SLJIT_CONFIG_X86_32 */+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16)+ return emit_mov_half(compiler, 0, dst, dstw, TMP_REG1, 0);++ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ }++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (op == SLJIT_REV_S32) {+ compiler->mode32 = 0;+ inst = emit_x86_instruction(compiler, 1, dst, 0, dst, 0);+ FAIL_IF(!inst);+ *inst = MOVSXD_r_rm;+ }+#endif /* SLJIT_CONFIG_X86_64 */++ return SLJIT_SUCCESS;+}++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_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 dst_is_ereg = 0;+#else /* !SLJIT_CONFIG_X86_32 */+ sljit_s32 op_flags = GET_ALL_FLAGS(op);+#endif /* SLJIT_CONFIG_X86_32 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);+ CHECK_EXTRA_REGS(src, srcw, (void)0);+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = op_flags & SLJIT_32;+#endif /* SLJIT_CONFIG_X86_64 */++ op = GET_OPCODE(op);++ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+#endif /* SLJIT_CONFIG_X86_64 */++ 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_flags & SLJIT_32) {+ if (src & SLJIT_MEM) {+ if (op == SLJIT_MOV_S32)+ op = SLJIT_MOV_U32;+ }+ else if (src == SLJIT_IMM) {+ if (op == SLJIT_MOV_U32)+ op = SLJIT_MOV_S32;+ }+ }+#endif /* SLJIT_CONFIG_X86_64 */++ if (src == SLJIT_IMM) {+ switch (op) {+ case SLJIT_MOV_U8:+ srcw = (sljit_u8)srcw;+ break;+ case SLJIT_MOV_S8:+ srcw = (sljit_s8)srcw;+ break;+ case SLJIT_MOV_U16:+ srcw = (sljit_u16)srcw;+ break;+ case SLJIT_MOV_S16:+ srcw = (sljit_s16)srcw;+ break;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ case SLJIT_MOV_U32:+ srcw = (sljit_u32)srcw;+ break;+ case SLJIT_MOV_S32:+ srcw = (sljit_s32)srcw;+ break;+#endif /* SLJIT_CONFIG_X86_64 */+ }+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (SLJIT_UNLIKELY(dst_is_ereg))+ return emit_mov(compiler, dst, dstw, src, srcw);+#endif /* SLJIT_CONFIG_X86_32 */+ }++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ 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;+ }+#endif /* SLJIT_CONFIG_X86_32 */++ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+#endif /* SLJIT_CONFIG_X86_32 */+ EMIT_MOV(compiler, dst, dstw, src, srcw);+ break;+ case SLJIT_MOV_U8:+ FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, srcw));+ break;+ case SLJIT_MOV_S8:+ FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, srcw));+ break;+ case SLJIT_MOV_U16:+ FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, srcw));+ break;+ 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_U32:+ FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, srcw));+ break;+ case SLJIT_MOV_S32:+ FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, srcw));+ break;+ case SLJIT_MOV32:+ compiler->mode32 = 1;+ EMIT_MOV(compiler, dst, dstw, src, srcw);+ compiler->mode32 = 0;+ break;+#endif /* SLJIT_CONFIG_X86_64 */+ }++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1)+ return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0);+#endif /* SLJIT_CONFIG_X86_32 */+ return SLJIT_SUCCESS;+ }++ switch (op) {+ case SLJIT_CLZ:+ case SLJIT_CTZ:+ return emit_clz_ctz(compiler, (op == SLJIT_CLZ), dst, dstw, src, srcw);+ case SLJIT_REV:+ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ case SLJIT_REV_U32:+ case SLJIT_REV_S32:+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (dst_is_ereg)+ op |= SLJIT_32;+#endif /* SLJIT_CONFIG_X86_32 */+ return emit_bswap(compiler, op, dst, dstw, src, srcw);+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,+ sljit_u32 op_types,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;+ sljit_u8 op_eax_imm = U8(op_types >> 24);+ sljit_u8 op_rm = U8((op_types >> 16) & 0xff);+ sljit_u8 op_mr = U8((op_types >> 8) & 0xff);+ sljit_u8 op_imm = U8(op_types & 0xff);++ if (dst == src1 && dstw == src1w) {+ if (src2 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {+#else+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {+#endif+ BINARY_EAX_IMM(op_eax_imm, src2w);+ }+ else {+ BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);+ }+ }+ else if (FAST_IS_REG(dst)) {+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ else if (FAST_IS_REG(src2)) {+ /* Special exception for sljit_emit_op_flags. */+ inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ else {+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ return SLJIT_SUCCESS;+ }++ /* Only for cumulative operations. */+ if (dst == src2 && dstw == src2w) {+ if (src1 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {+#else+ if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128)) {+#endif+ BINARY_EAX_IMM(op_eax_imm, src1w);+ }+ else {+ BINARY_IMM(op_imm, op_mr, src1w, dst, dstw);+ }+ }+ else if (FAST_IS_REG(dst)) {+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ else if (FAST_IS_REG(src1)) {+ inst = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ else {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ return SLJIT_SUCCESS;+ }++ /* General version. */+ if (FAST_IS_REG(dst)) {+ EMIT_MOV(compiler, dst, 0, src1, src1w);+ if (src2 == SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, dst, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ }+ else {+ /* This version requires less memory writing. */+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ if (src2 == SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,+ sljit_u32 op_types,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;+ sljit_u8 op_eax_imm = U8(op_types >> 24);+ sljit_u8 op_rm = U8((op_types >> 16) & 0xff);+ sljit_u8 op_mr = U8((op_types >> 8) & 0xff);+ sljit_u8 op_imm = U8(op_types & 0xff);++ if (dst == src1 && dstw == src1w) {+ if (src2 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {+#else+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {+#endif+ BINARY_EAX_IMM(op_eax_imm, src2w);+ }+ else {+ BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);+ }+ }+ else if (FAST_IS_REG(dst)) {+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ else if (FAST_IS_REG(src2)) {+ inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ else {+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ return SLJIT_SUCCESS;+ }++ /* General version. */+ if (FAST_IS_REG(dst) && dst != src2) {+ EMIT_MOV(compiler, dst, 0, src1, src1w);+ if (src2 == SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, dst, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ }+ else {+ /* This version requires less memory writing. */+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ if (src2 == SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ }++ return SLJIT_SUCCESS;+}++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_u8* inst;+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ /* Register destination. */+ if (dst_r == src1 && src2 != SLJIT_IMM) {+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, src2, src2w));+ } else if (dst_r == src2 && src1 != SLJIT_IMM) {+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, src1, src1w));+ } else if (src1 == SLJIT_IMM) {+ if (src2 == SLJIT_IMM) {+ EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, src2w);+ src2 = dst_r;+ src2w = 0;+ }++ if (src1w <= 127 && src1w >= -128) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = IMUL_r_rm_i8;++ FAIL_IF(emit_byte(compiler, U8(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_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ 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_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ sljit_unaligned_store_s32(inst, (sljit_s32)src1w);+ }+ else {+ if (dst_r != src2)+ EMIT_MOV(compiler, dst_r, 0, src2, src2w);+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, TMP_REG2, 0));+ }+#endif+ }+ else if (src2 == SLJIT_IMM) {+ /* Note: src1 is NOT immediate. */++ if (src2w <= 127 && src2w >= -128) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = IMUL_r_rm_i8;++ FAIL_IF(emit_byte(compiler, U8(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_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ 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_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ sljit_unaligned_store_s32(inst, (sljit_s32)src2w);+ } else {+ if (dst_r != src1)+ EMIT_MOV(compiler, dst_r, 0, src1, src1w);+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, TMP_REG2, 0));+ }+#endif+ } else {+ /* Neither argument is immediate. */+ if (ADDRESSING_DEPENDS_ON(src2, dst_r))+ dst_r = TMP_REG1;+ EMIT_MOV(compiler, dst_r, 0, src1, src1w);+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, src2, src2w));+ }++ if (dst & SLJIT_MEM)+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);++ return SLJIT_SUCCESS;+}++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_u8* inst;+ sljit_s32 dst_r, done = 0;++ /* These cases better be left to handled by normal way. */+ 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;++ if (FAST_IS_REG(src1)) {+ if (FAST_IS_REG(src2)) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0);+ FAIL_IF(!inst);+ *inst = LEA_r_m;+ done = 1;+ }+#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_s32)src2w);+#else+ if (src2 == SLJIT_IMM) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w);+#endif+ FAIL_IF(!inst);+ *inst = LEA_r_m;+ done = 1;+ }+ }+ 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_s32)src1w);+#else+ if (src1 == SLJIT_IMM) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w);+#endif+ FAIL_IF(!inst);+ *inst = LEA_r_m;+ done = 1;+ }+ }++ if (done) {+ if (dst_r == TMP_REG1)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+ }+ return SLJIT_ERR_UNSUPPORTED;+}++static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ 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))) {+#else+ if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128)) {+#endif+ BINARY_EAX_IMM(CMP_EAX_i32, src2w);+ return SLJIT_SUCCESS;+ }++ if (FAST_IS_REG(src1)) {+ if (src2 == SLJIT_IMM) {+ BINARY_IMM(CMP, CMP_rm_r, src2w, src1, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = CMP_r_rm;+ }+ return SLJIT_SUCCESS;+ }++ if (FAST_IS_REG(src2) && src1 != SLJIT_IMM) {+ inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = CMP_rm_r;+ return SLJIT_SUCCESS;+ }++ if (src2 == SLJIT_IMM) {+ if (src1 == SLJIT_IMM) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ src1 = TMP_REG1;+ src1w = 0;+ }+ BINARY_IMM(CMP, CMP_rm_r, src2w, src1, src1w);+ }+ else {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = CMP_r_rm;+ }+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_test_binary(struct sljit_compiler *compiler,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ 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))) {+#else+ if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128)) {+#endif+ BINARY_EAX_IMM(TEST_EAX_i32, src2w);+ return SLJIT_SUCCESS;+ }++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ 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+ BINARY_EAX_IMM(TEST_EAX_i32, src1w);+ return SLJIT_SUCCESS;+ }++ if (src1 != SLJIT_IMM) {+ if (src2 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (IS_HALFWORD(src2w) || compiler->mode32) {+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+ } else {+ FAIL_IF(emit_load_imm64(compiler, FAST_IS_REG(src1) ? TMP_REG2 : TMP_REG1, src2w));+ inst = emit_x86_instruction(compiler, 1, FAST_IS_REG(src1) ? TMP_REG2 : TMP_REG1, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ }+#else+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+#endif+ return SLJIT_SUCCESS;+ }+ else if (FAST_IS_REG(src1)) {+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ return SLJIT_SUCCESS;+ }+ }++ if (src2 != SLJIT_IMM) {+ if (src1 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (IS_HALFWORD(src1w) || compiler->mode32) {+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+ }+ else {+ 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;+ }+#else+ inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+#endif+ return SLJIT_SUCCESS;+ }+ else if (FAST_IS_REG(src2)) {+ inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ return SLJIT_SUCCESS;+ }+ }++ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ if (src2 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (IS_HALFWORD(src2w) || compiler->mode32) {+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+ }+ else {+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ }+#else+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+#endif+ }+ else {+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ }+ return SLJIT_SUCCESS;+}++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)+{+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_s32 mode32;+#endif+ sljit_u8* inst;++ if (src2 == SLJIT_IMM || src2 == SLJIT_PREF_SHIFT_REG) {+ if (dst == src1 && dstw == src1w) {+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw);+ FAIL_IF(!inst);+ inst[1] |= mode;+ return SLJIT_SUCCESS;+ }+ if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ inst[1] |= mode;+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ return SLJIT_SUCCESS;+ }+ if (FAST_IS_REG(dst)) {+ EMIT_MOV(compiler, dst, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0);+ FAIL_IF(!inst);+ inst[1] |= mode;+ return SLJIT_SUCCESS;+ }++ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0);+ FAIL_IF(!inst);+ inst[1] |= mode;+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+ }++ if (dst == SLJIT_PREF_SHIFT_REG) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ 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[1] |= mode;+ return emit_mov(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ }++ if (FAST_IS_REG(dst) && dst != src2 && dst != TMP_REG1 && !ADDRESSING_DEPENDS_ON(src2, dst)) {+ if (src1 != dst)+ EMIT_MOV(compiler, dst, 0, src1, src1w);+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ mode32 = compiler->mode32;+ compiler->mode32 = 0;+#endif+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = mode32;+#endif+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0);+ FAIL_IF(!inst);+ inst[1] |= mode;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+#endif+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = mode32;+#endif+ return SLJIT_SUCCESS;+ }++ /* This case is complex since ecx itself may be used for+ addressing, and this case must be supported as well. */+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0);+#else /* !SLJIT_CONFIG_X86_32 */+ mode32 = compiler->mode32;+ compiler->mode32 = 0;+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);+ compiler->mode32 = mode32;+#endif /* SLJIT_CONFIG_X86_32 */++ 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[1] |= mode;++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0);+#else+ compiler->mode32 = 0;+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);+ compiler->mode32 = mode32;+#endif /* SLJIT_CONFIG_X86_32 */++ if (dst != TMP_REG1)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);++ return SLJIT_SUCCESS;+}++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) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ src2w &= compiler->mode32 ? 0x1f : 0x3f;+#else /* !SLJIT_CONFIG_X86_64 */+ src2w &= 0x1f;+#endif /* SLJIT_CONFIG_X86_64 */+ if (src2w != 0)+ return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);++ if (!set_flags)+ return emit_mov(compiler, dst, dstw, src1, src1w);+ /* OR dst, src, 0 */+ return emit_cum_binary(compiler, BINARY_OPCODE(OR),+ dst, dstw, src1, src1w, SLJIT_IMM, 0);+ }++ if (!set_flags)+ return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);++ if (!FAST_IS_REG(dst))+ FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));++ FAIL_IF(emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w));++ if (FAST_IS_REG(dst))+ return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);+ return SLJIT_SUCCESS;+}++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, 0, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);+ 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_32;+#endif++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ if (!HAS_FLAGS(op)) {+ if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)+ return compiler->error;+ }+ return emit_cum_binary(compiler, BINARY_OPCODE(ADD),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_ADDC:+ return emit_cum_binary(compiler, BINARY_OPCODE(ADC),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_SUB:+ if (src1 == SLJIT_IMM && src1w == 0)+ return emit_unary(compiler, NEG_rm, dst, dstw, src2, src2w);++ 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;+ if (FAST_IS_REG(dst) && src2 == dst) {+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, 0, dst, 0, src1, src1w));+ return emit_unary(compiler, NEG_rm, dst, 0, dst, 0);+ }+ }++ return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_SUBC:+ return emit_non_cum_binary(compiler, BINARY_OPCODE(SBB),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_MUL:+ return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_AND:+ return emit_cum_binary(compiler, BINARY_OPCODE(AND),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_OR:+ return emit_cum_binary(compiler, BINARY_OPCODE(OR),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_XOR:+ if (!HAS_FLAGS(op)) {+ if (src2 == SLJIT_IMM && src2w == -1)+ return emit_unary(compiler, NOT_rm, dst, dstw, src1, src1w);+ if (src1 == SLJIT_IMM && src1w == -1)+ return emit_unary(compiler, NOT_rm, dst, dstw, src2, src2w);+ }++ return emit_cum_binary(compiler, BINARY_OPCODE(XOR),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_SHL:+ case SLJIT_MSHL:+ return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ return emit_shift_with_flags(compiler, SHR, HAS_FLAGS(op),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_ASHR:+ case SLJIT_MASHR:+ return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_ROTL:+ return emit_shift_with_flags(compiler, ROL, 0,+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_ROTR:+ return emit_shift_with_flags(compiler, ROR, 0,+ dst, dstw, src1, src1w, src2, src2w);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 opcode = GET_OPCODE(op);++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));++ if (opcode != SLJIT_SUB && opcode != SLJIT_AND) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);+ }++ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ 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_32;+#endif++ if (opcode == SLJIT_SUB)+ return emit_cmp_binary(compiler, src1, src1w, src2, src2w);++ return emit_test_binary(compiler, src1, src1w, src2, src2w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;+ sljit_sw dstw = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ CHECK_EXTRA_REGS(dst_reg, dstw, (void)0);+ 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_32;+#endif++ switch (GET_OPCODE(op)) {+ case SLJIT_MULADD:+ FAIL_IF(emit_mul(compiler, TMP_REG1, 0, src1, src1w, src2, src2w));+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst_reg, dstw);+ FAIL_IF(!inst);+ *inst = ADD_rm_r;+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 src1_reg,+ sljit_s32 src2_reg,+ sljit_s32 src3, sljit_sw src3w)+{+ sljit_s32 is_rotate, is_left, move_src1;+ sljit_u8* inst;+ sljit_sw src1w = 0;+ sljit_sw dstw = 0;+ /* The whole register must be saved even for 32 bit operations. */+ sljit_u8 restore_ecx = 0;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_sw src2w = 0;+ sljit_s32 restore_sp4 = 0;+#endif /* SLJIT_CONFIG_X86_32 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));+ ADJUST_LOCAL_OFFSET(src3, src3w);++ CHECK_EXTRA_REGS(dst_reg, dstw, (void)0);+ CHECK_EXTRA_REGS(src3, src3w, (void)0);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = op & SLJIT_32;+#endif /* SLJIT_CONFIG_X86_64 */++ if (src3 == SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ src3w &= 0x1f;+#else /* !SLJIT_CONFIG_X86_32 */+ src3w &= (op & SLJIT_32) ? 0x1f : 0x3f;+#endif /* SLJIT_CONFIG_X86_32 */++ if (src3w == 0)+ return SLJIT_SUCCESS;+ }++ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);++ is_rotate = (src1_reg == src2_reg);+ CHECK_EXTRA_REGS(src1_reg, src1w, (void)0);+ CHECK_EXTRA_REGS(src2_reg, src2w, (void)0);++ if (is_rotate)+ return emit_shift(compiler, is_left ? ROL : ROR, dst_reg, dstw, src1_reg, src1w, src3, src3w);++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (src2_reg & SLJIT_MEM) {+ EMIT_MOV(compiler, TMP_REG1, 0, src2_reg, src2w);+ src2_reg = TMP_REG1;+ }+#endif /* SLJIT_CONFIG_X86_32 */++ if (dst_reg == SLJIT_PREF_SHIFT_REG && src3 != SLJIT_IMM && (src3 != SLJIT_PREF_SHIFT_REG || src1_reg != SLJIT_PREF_SHIFT_REG)) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w);+ src1_reg = TMP_REG1;+ src1w = 0;+#else /* !SLJIT_CONFIG_X86_64 */+ if (src2_reg != TMP_REG1) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w);+ src1_reg = TMP_REG1;+ src1w = 0;+ } else if ((src1_reg & SLJIT_MEM) || src1_reg == SLJIT_PREF_SHIFT_REG) {+ restore_sp4 = (src3 == SLJIT_R0) ? SLJIT_R1 : SLJIT_R0;+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), restore_sp4, 0);+ EMIT_MOV(compiler, restore_sp4, 0, src1_reg, src1w);+ src1_reg = restore_sp4;+ src1w = 0;+ } else {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), src1_reg, 0);+ restore_sp4 = src1_reg;+ }+#endif /* SLJIT_CONFIG_X86_64 */++ if (src3 != SLJIT_PREF_SHIFT_REG)+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src3, src3w);+ } else {+ if (src2_reg == SLJIT_PREF_SHIFT_REG && src3 != SLJIT_IMM && src3 != SLJIT_PREF_SHIFT_REG) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+#endif /* SLJIT_CONFIG_X86_64 */+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = op & SLJIT_32;+#endif /* SLJIT_CONFIG_X86_64 */+ src2_reg = TMP_REG1;+ restore_ecx = 1;+ }++ move_src1 = 0;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (dst_reg != src1_reg) {+ if (dst_reg != src3) {+ EMIT_MOV(compiler, dst_reg, 0, src1_reg, src1w);+ src1_reg = dst_reg;+ src1w = 0;+ } else+ move_src1 = 1;+ }+#else /* !SLJIT_CONFIG_X86_64 */+ if (dst_reg & SLJIT_MEM) {+ if (src2_reg != TMP_REG1) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w);+ src1_reg = TMP_REG1;+ src1w = 0;+ } else if ((src1_reg & SLJIT_MEM) || src1_reg == SLJIT_PREF_SHIFT_REG) {+ restore_sp4 = (src3 == SLJIT_R0) ? SLJIT_R1 : SLJIT_R0;+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), restore_sp4, 0);+ EMIT_MOV(compiler, restore_sp4, 0, src1_reg, src1w);+ src1_reg = restore_sp4;+ src1w = 0;+ } else {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), src1_reg, 0);+ restore_sp4 = src1_reg;+ }+ } else if (dst_reg != src1_reg) {+ if (dst_reg != src3) {+ EMIT_MOV(compiler, dst_reg, 0, src1_reg, src1w);+ src1_reg = dst_reg;+ src1w = 0;+ } else+ move_src1 = 1;+ }+#endif /* SLJIT_CONFIG_X86_64 */++ if (src3 != SLJIT_IMM && src3 != SLJIT_PREF_SHIFT_REG) {+ if (!restore_ecx) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);+ compiler->mode32 = op & SLJIT_32;+ restore_ecx = 1;+#else /* !SLJIT_CONFIG_X86_64 */+ if (src1_reg != TMP_REG1 && src2_reg != TMP_REG1) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);+ restore_ecx = 1;+ } else {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0);+ restore_ecx = 2;+ }+#endif /* SLJIT_CONFIG_X86_64 */+ }+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src3, src3w);+ }++ if (move_src1) {+ EMIT_MOV(compiler, dst_reg, 0, src1_reg, src1w);+ src1_reg = dst_reg;+ src1w = 0;+ }+ }++ inst = emit_x86_instruction(compiler, 2, src2_reg, 0, src1_reg, src1w);+ FAIL_IF(!inst);+ inst[0] = GROUP_0F;++ if (src3 == SLJIT_IMM) {+ inst[1] = U8((is_left ? SHLD : SHRD) - 1);++ /* Immediate argument is added separately. */+ FAIL_IF(emit_byte(compiler, U8(src3w)));+ } else+ inst[1] = U8(is_left ? SHLD : SHRD);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (restore_ecx) {+ compiler->mode32 = 0;+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ }++ if (src1_reg != dst_reg) {+ compiler->mode32 = op & SLJIT_32;+ return emit_mov(compiler, dst_reg, dstw, src1_reg, 0);+ }+#else /* !SLJIT_CONFIG_X86_64 */+ if (restore_ecx)+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, restore_ecx == 1 ? TMP_REG1 : SLJIT_MEM1(SLJIT_SP), 0);++ if (src1_reg != dst_reg)+ EMIT_MOV(compiler, dst_reg, dstw, src1_reg, 0);++ if (restore_sp4)+ return emit_mov(compiler, restore_sp4, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32));+#endif /* SLJIT_CONFIG_X86_32 */++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ CHECK_EXTRA_REGS(src, srcw, (void)0);++ switch (op) {+ case SLJIT_FAST_RETURN:+ return emit_fast_return(compiler, src, srcw);+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ /* Don't adjust shadow stack if it isn't enabled. */+ if (!cpu_has_shadow_stack ())+ return SLJIT_SUCCESS;+ return adjust_shadow_stack(compiler, src, srcw);+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ return emit_prefetch(compiler, op, src, srcw);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++ switch (op) {+ case SLJIT_FAST_ENTER:+ return emit_fast_enter(compiler, dst, dstw);+ case SLJIT_GET_RETURN_ADDRESS:+ return sljit_emit_get_return_address(compiler, dst, dstw);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));++ if (type == SLJIT_GP_REGISTER) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (reg >= SLJIT_R3 && reg <= SLJIT_R8)+ return -1;+#endif /* SLJIT_CONFIG_X86_32 */+ return reg_map[reg];+ }++ if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_128 && type != SLJIT_SIMD_REG_256 && type != SLJIT_SIMD_REG_512)+ return -1;++ return freg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_u32 size)+{+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ SLJIT_MEMCPY(inst, instruction, size);+ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++/* Alignment(3) + 4 * 16 bytes. */+static sljit_u32 sse2_data[3 + (4 * 4)];+static sljit_u32 *sse2_buffer;++static void init_compiler(void)+{+ get_cpu_features();++ /* Align to 16 bytes. */+ sse2_buffer = (sljit_u32*)(((sljit_uw)sse2_data + 15) & ~(sljit_uw)0xf);++ /* Single precision constants (each constant is 16 byte long). */+ sse2_buffer[0] = 0x80000000;+ sse2_buffer[4] = 0x7fffffff;+ /* 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;+}++static sljit_s32 emit_groupf(struct sljit_compiler *compiler,+ sljit_uw op,+ sljit_s32 dst, sljit_s32 src, sljit_sw srcw)+{+ sljit_u8 *inst = emit_x86_instruction(compiler, 2 | (op & ~(sljit_uw)0xff), dst, 0, src, srcw);+ FAIL_IF(!inst);+ inst[0] = GROUP_0F;+ inst[1] = op & 0xff;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_groupf_ext(struct sljit_compiler *compiler,+ sljit_uw op,+ sljit_s32 dst, sljit_s32 src, sljit_sw srcw)+{+ sljit_u8 *inst;++ SLJIT_ASSERT((op & EX86_SSE2) && ((op & VEX_OP_0F38) || (op & VEX_OP_0F3A)));++ inst = emit_x86_instruction(compiler, 3 | (op & ~((sljit_uw)0xff | VEX_OP_0F38 | VEX_OP_0F3A)), dst, 0, src, srcw);+ FAIL_IF(!inst);+ inst[0] = GROUP_0F;+ inst[1] = U8((op & VEX_OP_0F38) ? 0x38 : 0x3A);+ inst[2] = op & 0xff;+ return SLJIT_SUCCESS;+}++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_groupf(compiler, MOVSD_x_xm | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, dst, src, srcw);+}++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_groupf(compiler, MOVSD_xm_x | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, src, dst, dstw);+}++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_s32 dst_r;++ CHECK_EXTRA_REGS(dst, dstw, (void)0);+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)+ compiler->mode32 = 0;+#endif++ FAIL_IF(emit_groupf(compiler, CVTTSD2SI_r_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP2, dst_r, src, srcw));++ if (dst & SLJIT_MEM)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+}++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_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;++ CHECK_EXTRA_REGS(src, srcw, (void)0);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ 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_CONV_F64_FROM_S32)+ srcw = (sljit_s32)srcw;+#endif+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);+ src = TMP_REG1;+ srcw = 0;+ }++ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, srcw));++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif+ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+}++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)+{+ switch (GET_FLAG_TYPE(op)) {+ case SLJIT_ORDERED_EQUAL:+ /* Also: SLJIT_UNORDERED_OR_NOT_EQUAL */+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));+ FAIL_IF(emit_groupf(compiler, CMPS_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, TMP_FREG, src2, src2w));++ /* EQ */+ FAIL_IF(emit_byte(compiler, 0));++ src1 = TMP_FREG;+ src2 = TMP_FREG;+ src2w = 0;+ break;++ case SLJIT_ORDERED_LESS:+ case SLJIT_UNORDERED_OR_GREATER:+ /* Also: SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_ORDERED_LESS_EQUAL */+ if (!FAST_IS_REG(src2)) {+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src2, src2w));+ src2 = TMP_FREG;+ }++ return emit_groupf(compiler, UCOMISD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, src2, src1, src1w);+ }++ if (!FAST_IS_REG(src1)) {+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));+ src1 = TMP_FREG;+ }++ return emit_groupf(compiler, UCOMISD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, src1, src2, src2w);+}++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_s32 dst_r;+ sljit_u8 *inst;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif++ CHECK_ERROR();+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ if (GET_OPCODE(op) == SLJIT_MOV_F64) {+ if (FAST_IS_REG(dst))+ return emit_sse2_load(compiler, op & SLJIT_32, dst, src, srcw);+ if (FAST_IS_REG(src))+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, src);+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw));+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);+ }++ 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_groupf(compiler, UNPCKLPD_x_xm | ((op & SLJIT_32) ? EX86_PREF_66 : 0) | EX86_SSE2, src, src, 0));+ } else {+ FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_32), TMP_FREG, src, srcw));+ src = TMP_FREG;+ }++ FAIL_IF(emit_groupf(compiler, CVTPD2PS_x_xm | ((op & SLJIT_32) ? EX86_PREF_66 : 0) | EX86_SSE2, dst_r, src, 0));+ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+ }++ if (FAST_IS_REG(dst)) {+ dst_r = (dst == src) ? TMP_FREG : dst;++ if (src & SLJIT_MEM)+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw));++ FAIL_IF(emit_groupf(compiler, PCMPEQD_x_xm | EX86_PREF_66 | EX86_SSE2, dst_r, dst_r, 0));++ inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP2, 0, 0, dst_r, 0);+ inst[0] = GROUP_0F;+ /* Same as PSRLD_x / PSRLQ_x */+ inst[1] = (op & SLJIT_32) ? PSLLD_x_i8 : PSLLQ_x_i8;++ if (GET_OPCODE(op) == SLJIT_ABS_F64) {+ inst[2] |= 2 << 3;+ FAIL_IF(emit_byte(compiler, 1));+ } else {+ inst[2] |= 6 << 3;+ FAIL_IF(emit_byte(compiler, ((op & SLJIT_32) ? 31 : 63)));+ }++ if (dst_r != TMP_FREG)+ dst_r = (src & SLJIT_MEM) ? TMP_FREG : src;+ return emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_NEG_F64 ? XORPD_x_xm : ANDPD_x_xm) | EX86_SSE2, dst, dst_r, 0);+ }++ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw));++ switch (GET_OPCODE(op)) {+ case SLJIT_NEG_F64:+ FAIL_IF(emit_groupf(compiler, XORPD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, TMP_FREG, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer : sse2_buffer + 8)));+ break;++ case SLJIT_ABS_F64:+ FAIL_IF(emit_groupf(compiler, ANDPD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, TMP_FREG, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer + 4 : sse2_buffer + 12)));+ break;+ }++ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);+}++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_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif++ if (FAST_IS_REG(dst)) {+ dst_r = dst;+ if (dst == src1)+ ; /* Do nothing here. */+ else if (dst == src2 && (GET_OPCODE(op) == SLJIT_ADD_F64 || GET_OPCODE(op) == SLJIT_MUL_F64)) {+ /* Swap arguments. */+ src2 = src1;+ src2w = src1w;+ } else if (dst != src2)+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_r, src1, src1w));+ else {+ dst_r = TMP_FREG;+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));+ }+ } else {+ dst_r = TMP_FREG;+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w));+ break;++ case SLJIT_SUB_F64:+ FAIL_IF(emit_groupf(compiler, SUBSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w));+ break;++ case SLJIT_MUL_F64:+ FAIL_IF(emit_groupf(compiler, MULSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w));+ break;++ case SLJIT_DIV_F64:+ FAIL_IF(emit_groupf(compiler, DIVSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w));+ break;+ }++ if (dst_r != dst)+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_uw pref;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif++ if (dst_freg == src1) {+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src2, src2w));+ pref = EX86_SELECT_66(op) | EX86_SSE2;+ FAIL_IF(emit_groupf(compiler, XORPD_x_xm | pref, TMP_FREG, src1, src1w));+ FAIL_IF(emit_groupf(compiler, ANDPD_x_xm | pref, TMP_FREG, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer : sse2_buffer + 8)));+ return emit_groupf(compiler, XORPD_x_xm | pref, dst_freg, TMP_FREG, 0);+ }++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));+ src1 = TMP_FREG;+ src1w = 0;+ }++ if (dst_freg != src2)+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_freg, src2, src2w));++ pref = EX86_SELECT_66(op) | EX86_SSE2;+ FAIL_IF(emit_groupf(compiler, XORPD_x_xm | pref, dst_freg, src1, src1w));+ FAIL_IF(emit_groupf(compiler, ANDPD_x_xm | pref, dst_freg, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer : sse2_buffer + 8)));+ return emit_groupf(compiler, XORPD_x_xm | pref, dst_freg, src1, src1w);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ sljit_u8 *inst;+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);++ inst = (sljit_u8*)ensure_buf(compiler, 1);+ PTR_FAIL_IF(!inst);+ inst[0] = SLJIT_INST_LABEL;++ return label;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ sljit_u8 *inst;+ struct sljit_jump *jump;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF_NULL(jump);+ set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT)));+ type &= 0xff;++ jump->addr = compiler->size;+ /* Worst case size. */+ compiler->size += (type >= SLJIT_JUMP) ? JUMP_MAX_SIZE : CJUMP_MAX_SIZE;+ inst = (sljit_u8*)ensure_buf(compiler, 1);+ PTR_FAIL_IF_NULL(inst);++ inst[0] = SLJIT_INST_JUMP;+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ sljit_u8 *inst;+ struct sljit_jump *jump;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ CHECK_EXTRA_REGS(src, srcw, (void)0);++ if (src == SLJIT_IMM) {+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF_NULL(jump);+ set_jump(jump, compiler, (sljit_u32)(JUMP_ADDR | (type << TYPE_SHIFT)));+ jump->u.target = (sljit_uw)srcw;++ jump->addr = compiler->size;+ /* Worst case size. */+ compiler->size += JUMP_MAX_SIZE;+ inst = (sljit_u8*)ensure_buf(compiler, 1);+ FAIL_IF_NULL(inst);++ inst[0] = SLJIT_INST_JUMP;+ } else {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ /* REX_W is not necessary (src is not immediate). */+ compiler->mode32 = 1;+#endif+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);+ FAIL_IF(!inst);+ inst[0] = GROUP_FF;+ inst[1] = U8(inst[1] | ((type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm));+ }+ return SLJIT_SUCCESS;+}++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_u8 *inst;+ sljit_u8 cond_set;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_s32 reg;+#endif /* !SLJIT_CONFIG_X86_64 */+ /* 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, type));++ ADJUST_LOCAL_OFFSET(dst, dstw);+ CHECK_EXTRA_REGS(dst, dstw, (void)0);++ /* setcc = jcc + 0x10. */+ cond_set = U8(get_jump_code((sljit_uw)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)) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 3);+ FAIL_IF(!inst);+ INC_SIZE(4 + 3);+ /* Set low register to conditional flag. */+ inst[0] = (reg_map[TMP_REG1] <= 7) ? REX : REX_B;+ inst[1] = GROUP_0F;+ inst[2] = cond_set;+ inst[3] = MOD_REG | reg_lmap[TMP_REG1];+ inst[4] = U8(REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B));+ inst[5] = OR_rm8_r8;+ inst[6] = U8(MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst]);+ return SLJIT_SUCCESS;+ }++ reg = (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG1;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4 + 4);+ /* Set low register to conditional flag. */+ inst[0] = (reg_map[reg] <= 7) ? REX : REX_B;+ inst[1] = GROUP_0F;+ inst[2] = cond_set;+ inst[3] = MOD_REG | reg_lmap[reg];+ inst[4] = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));+ /* The movzx instruction does not affect flags. */+ inst[5] = GROUP_0F;+ inst[6] = MOVZX_r_rm8;+ inst[7] = U8(MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]);++ if (reg != TMP_REG1)+ return SLJIT_SUCCESS;++ if (GET_OPCODE(op) < SLJIT_ADD) {+ compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV;+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ }++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);++#else /* !SLJIT_CONFIG_X86_64 */+ SLJIT_ASSERT(reg_map[TMP_REG1] < 4);++ /* The SLJIT_CONFIG_X86_32 code path starts here. */+ if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst) && reg_map[dst] <= 4) {+ /* Low byte is accessible. */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3 + 3);+ /* Set low byte to conditional flag. */+ inst[0] = GROUP_0F;+ inst[1] = cond_set;+ inst[2] = U8(MOD_REG | reg_map[dst]);++ inst[3] = GROUP_0F;+ inst[4] = MOVZX_r_rm8;+ inst[5] = U8(MOD_REG | (reg_map[dst] << 3) | reg_map[dst]);+ return SLJIT_SUCCESS;+ }++ if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && reg_map[dst] <= 4) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 2);+ FAIL_IF(!inst);+ INC_SIZE(3 + 2);++ /* Set low byte to conditional flag. */+ inst[0] = GROUP_0F;+ inst[1] = cond_set;+ inst[2] = U8(MOD_REG | reg_map[TMP_REG1]);++ inst[3] = OR_rm8_r8;+ inst[4] = U8(MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[dst]);+ return SLJIT_SUCCESS;+ }++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3 + 3);+ /* Set low byte to conditional flag. */+ inst[0] = GROUP_0F;+ inst[1] = cond_set;+ inst[2] = U8(MOD_REG | reg_map[TMP_REG1]);++ inst[3] = GROUP_0F;+ inst[4] = MOVZX_r_rm8;+ inst[5] = U8(MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[TMP_REG1]);++ if (GET_OPCODE(op) < SLJIT_ADD)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);+#endif /* SLJIT_CONFIG_X86_64 */+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2_freg)+{+ sljit_u8* inst;+ sljit_uw size;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif /* SLJIT_CONFIG_X86_64 */++ if (dst_freg != src2_freg) {+ if (dst_freg == src1) {+ src1 = src2_freg;+ src1w = 0;+ type ^= 0x1;+ } else+ FAIL_IF(emit_sse2_load(compiler, type & SLJIT_32, dst_freg, src2_freg, 0));+ }++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ inst[0] = U8(get_jump_code((sljit_uw)(type & ~SLJIT_32) ^ 0x1) - 0x10);++ size = compiler->size;+ FAIL_IF(emit_sse2_load(compiler, type & SLJIT_32, dst_freg, src1, src1w));++ inst[1] = U8(compiler->size - size);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);+ sljit_uw op;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif /* SLJIT_CONFIG_X86_64 */++ switch (reg_size) {+ case 4:+ op = EX86_SSE2;+ break;+ case 5:+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))+ return SLJIT_ERR_UNSUPPORTED;+ op = EX86_SSE2 | VEX_256;+ break;+ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (!(srcdst & SLJIT_MEM))+ alignment = reg_size;++ if (type & SLJIT_SIMD_FLOAT) {+ if (elem_size == 2 || elem_size == 3) {+ op |= alignment >= reg_size ? MOVAPS_x_xm : MOVUPS_x_xm;++ if (elem_size == 3)+ op |= EX86_PREF_66;++ if (type & SLJIT_SIMD_STORE)+ op += 1;+ } else+ return SLJIT_ERR_UNSUPPORTED;+ } else {+ op |= ((type & SLJIT_SIMD_STORE) ? MOVDQA_xm_x : MOVDQA_x_xm)+ | (alignment >= reg_size ? EX86_PREF_66 : EX86_PREF_F3);+ }++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if ((op & VEX_256) || ((cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX)))+ return emit_vex_instruction(compiler, op, freg, 0, srcdst, srcdstw);++ return emit_groupf(compiler, op, freg, srcdst, srcdstw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);+ sljit_u8 *inst;+ sljit_u8 opcode = 0;+ sljit_uw op;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (!(type & SLJIT_SIMD_FLOAT)) {+ CHECK_EXTRA_REGS(src, srcw, (void)0);+ }++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))+ return SLJIT_ERR_UNSUPPORTED;+#else /* !SLJIT_CONFIG_X86_32 */+ compiler->mode32 = 1;++ if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2))+ return SLJIT_ERR_UNSUPPORTED;+#endif /* SLJIT_CONFIG_X86_32 */++ if (reg_size != 4 && (reg_size != 5 || !(cpu_feature_list & CPU_FEATURE_AVX2)))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 5)+ use_vex = 1;++ if (use_vex && src != SLJIT_IMM) {+ op = 0;++ switch (elem_size) {+ case 0:+ if (cpu_feature_list & CPU_FEATURE_AVX2)+ op = VPBROADCASTB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;+ break;+ case 1:+ if (cpu_feature_list & CPU_FEATURE_AVX2)+ op = VPBROADCASTW_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;+ break;+ case 2:+ if (type & SLJIT_SIMD_FLOAT) {+ if ((cpu_feature_list & CPU_FEATURE_AVX2) || ((cpu_feature_list & CPU_FEATURE_AVX) && (src & SLJIT_MEM)))+ op = VBROADCASTSS_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;+ } else if (cpu_feature_list & CPU_FEATURE_AVX2)+ op = VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;+ break;+ default:+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (!(type & SLJIT_SIMD_FLOAT)) {+ if (cpu_feature_list & CPU_FEATURE_AVX2)+ op = VPBROADCASTQ_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;+ break;+ }+#endif /* SLJIT_CONFIG_X86_64 */++ if (reg_size == 5)+ op = VBROADCASTSD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;+ break;+ }++ if (op != 0) {+ if (!(src & SLJIT_MEM) && !(type & SLJIT_SIMD_FLOAT)) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (elem_size >= 3)+ compiler->mode32 = 0;+#endif /* SLJIT_CONFIG_X86_64 */+ FAIL_IF(emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, src, srcw));+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif /* SLJIT_CONFIG_X86_64 */+ src = freg;+ srcw = 0;+ }++ if (reg_size == 5)+ op |= VEX_256;++ return emit_vex_instruction(compiler, op, freg, 0, src, srcw);+ }+ }++ if (type & SLJIT_SIMD_FLOAT) {+ if (src == SLJIT_IMM) {+ if (use_vex)+ return emit_vex_instruction(compiler, XORPD_x_xm | (reg_size == 5 ? VEX_256 : 0) | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, freg, 0);++ return emit_groupf(compiler, XORPD_x_xm | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2, freg, freg, 0);+ }++ SLJIT_ASSERT(reg_size == 4);++ if (use_vex) {+ if (elem_size == 3)+ return emit_vex_instruction(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, 0, src, srcw);++ SLJIT_ASSERT(!(src & SLJIT_MEM));+ FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, freg, src, src, 0));+ return emit_byte(compiler, 0);+ }++ if (elem_size == 2 && freg != src) {+ FAIL_IF(emit_sse2_load(compiler, 1, freg, src, srcw));+ src = freg;+ srcw = 0;+ }++ op = (elem_size == 2 ? SHUFPS_x_xm : MOVDDUP_x_xm) | (elem_size == 2 ? 0 : EX86_PREF_F2) | EX86_SSE2;+ FAIL_IF(emit_groupf(compiler, op, freg, src, srcw));++ if (elem_size == 2)+ return emit_byte(compiler, 0);+ return SLJIT_SUCCESS;+ }++ if (src == SLJIT_IMM) {+ if (elem_size == 0) {+ srcw = (sljit_u8)srcw;+ srcw |= srcw << 8;+ srcw |= srcw << 16;+ elem_size = 2;+ } else if (elem_size == 1) {+ srcw = (sljit_u16)srcw;+ srcw |= srcw << 16;+ elem_size = 2;+ }++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (elem_size == 2 && (sljit_s32)srcw == -1)+ srcw = -1;+#endif /* SLJIT_CONFIG_X86_64 */++ if (srcw == 0 || srcw == -1) {+ if (use_vex)+ return emit_vex_instruction(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | (reg_size == 5 ? VEX_256 : 0) | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, freg, 0);++ return emit_groupf(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | EX86_PREF_66 | EX86_SSE2, freg, freg, 0);+ }++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (elem_size == 3)+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));+ else+#endif /* SLJIT_CONFIG_X86_64 */+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);++ src = TMP_REG1;+ srcw = 0;++ }++ op = 2;+ opcode = MOVD_x_rm;++ switch (elem_size) {+ case 0:+ if (!FAST_IS_REG(src)) {+ opcode = 0x3a /* Prefix of PINSRB_x_rm_i8. */;+ op = 3;+ }+ break;+ case 1:+ if (!FAST_IS_REG(src))+ opcode = PINSRW_x_rm_i8;+ break;+ case 2:+ break;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ case 3:+ /* MOVQ */+ compiler->mode32 = 0;+ break;+#endif /* SLJIT_CONFIG_X86_64 */+ }++ if (use_vex) {+ if (opcode != MOVD_x_rm) {+ op = (opcode == 0x3a) ? (PINSRB_x_rm_i8 | VEX_OP_0F3A) : opcode;+ FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1 | VEX_SSE2_OPV, freg, freg, src, srcw));+ } else+ FAIL_IF(emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, src, srcw));+ } else {+ inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, src, srcw);+ FAIL_IF(!inst);+ inst[0] = GROUP_0F;+ inst[1] = opcode;++ if (op == 3) {+ SLJIT_ASSERT(opcode == 0x3a);+ inst[2] = PINSRB_x_rm_i8;+ }+ }++ if (use_vex && elem_size >= 2) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ op = VPBROADCASTD_x_xm;+#else /* !SLJIT_CONFIG_X86_32 */+ op = (elem_size == 3) ? VPBROADCASTQ_x_xm : VPBROADCASTD_x_xm;+#endif /* SLJIT_CONFIG_X86_32 */+ return emit_vex_instruction(compiler, op | ((reg_size == 5) ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, freg, 0);+ }++ SLJIT_ASSERT(reg_size == 4);++ if (opcode != MOVD_x_rm)+ FAIL_IF(emit_byte(compiler, 0));++ switch (elem_size) {+ case 0:+ if (use_vex) {+ FAIL_IF(emit_vex_instruction(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, TMP_FREG, TMP_FREG, 0));+ return emit_vex_instruction(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, TMP_FREG, 0);+ }+ FAIL_IF(emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, TMP_FREG, 0));+ return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, TMP_FREG, 0);+ case 1:+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, 0, freg, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, freg, 0));+ FAIL_IF(emit_byte(compiler, 0));+ /* fallthrough */+ default:+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, 0, freg, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0));+ return emit_byte(compiler, 0);+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ case 3:+ compiler->mode32 = 1;+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, 0, freg, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0));+ return emit_byte(compiler, 0x44);+#endif /* SLJIT_CONFIG_X86_64 */+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);+ sljit_u8 *inst;+ sljit_u8 opcode = 0;+ sljit_uw op;+ sljit_s32 freg_orig = freg;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 srcdst_is_ereg = 0;+ sljit_s32 srcdst_orig = 0;+ sljit_sw srcdstw_orig = 0;+#endif /* SLJIT_CONFIG_X86_32 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size == 5) {+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))+ return SLJIT_ERR_UNSUPPORTED;+ use_vex = 1;+ } else if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)+ return SLJIT_ERR_UNSUPPORTED;+#else /* SLJIT_CONFIG_X86_32 */+ if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2))+ return SLJIT_ERR_UNSUPPORTED;+#endif /* SLJIT_CONFIG_X86_32 */++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#else /* !SLJIT_CONFIG_X86_64 */+ if (!(type & SLJIT_SIMD_FLOAT)) {+ CHECK_EXTRA_REGS(srcdst, srcdstw, srcdst_is_ereg = 1);++ if ((type & SLJIT_SIMD_STORE) && ((srcdst_is_ereg && elem_size < 2) || (elem_size == 0 && (type & SLJIT_SIMD_LANE_SIGNED) && FAST_IS_REG(srcdst) && reg_map[srcdst] >= 4))) {+ srcdst_orig = srcdst;+ srcdstw_orig = srcdstw;+ srcdst = TMP_REG1;+ srcdstw = 0;+ }+ }+#endif /* SLJIT_CONFIG_X86_64 */++ if (type & SLJIT_SIMD_LANE_ZERO) {+ if (lane_index == 0) {+ if (!(type & SLJIT_SIMD_FLOAT)) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (elem_size == 3) {+ compiler->mode32 = 0;+ elem_size = 2;+ }+#endif /* SLJIT_CONFIG_X86_64 */+ if (srcdst == SLJIT_IMM) {+ if (elem_size == 0)+ srcdstw = (sljit_u8)srcdstw;+ else if (elem_size == 1)+ srcdstw = (sljit_u16)srcdstw;++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcdstw);+ srcdst = TMP_REG1;+ srcdstw = 0;+ elem_size = 2;+ }++ if (elem_size == 2) {+ if (use_vex)+ return emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, srcdst, srcdstw);+ return emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, freg, srcdst, srcdstw);+ }+ } else if (srcdst & SLJIT_MEM) {+ SLJIT_ASSERT(elem_size == 2 || elem_size == 3);++ if (use_vex)+ return emit_vex_instruction(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, freg, 0, srcdst, srcdstw);+ return emit_groupf(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, freg, srcdst, srcdstw);+ } else if (elem_size == 3) {+ if (use_vex)+ return emit_vex_instruction(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, freg, 0, srcdst, 0);+ return emit_groupf(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, freg, srcdst, 0);+ } else if (use_vex) {+ FAIL_IF(emit_vex_instruction(compiler, XORPD_x_xm | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, TMP_FREG, TMP_FREG, 0));+ return emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F3 | EX86_SSE2 | VEX_SSE2_OPV, freg, TMP_FREG, srcdst, 0);+ }+ }++ if (reg_size == 5 && lane_index >= (1 << (4 - elem_size))) {+ freg = TMP_FREG;+ lane_index -= (1 << (4 - elem_size));+ } else if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) {+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, TMP_FREG, srcdst, srcdstw));+ else+ FAIL_IF(emit_sse2_load(compiler, elem_size == 2, TMP_FREG, srcdst, srcdstw));+ srcdst = TMP_FREG;+ srcdstw = 0;+ }++ op = ((!(type & SLJIT_SIMD_FLOAT) || elem_size != 2) ? EX86_PREF_66 : 0)+ | ((type & SLJIT_SIMD_FLOAT) ? XORPD_x_xm : PXOR_x_xm) | EX86_SSE2;++ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, op | (reg_size == 5 ? VEX_256 : 0) | VEX_SSE2_OPV, freg, freg, freg, 0));+ else+ FAIL_IF(emit_groupf(compiler, op, freg, freg, 0));+ } else if (reg_size == 5 && lane_index >= (1 << (4 - elem_size))) {+ FAIL_IF(emit_vex_instruction(compiler, ((type & SLJIT_SIMD_FLOAT) ? VEXTRACTF128_x_ym : VEXTRACTI128_x_ym) | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, 0, TMP_FREG, 0));+ FAIL_IF(emit_byte(compiler, 1));++ freg = TMP_FREG;+ lane_index -= (1 << (4 - elem_size));+ }++ if (type & SLJIT_SIMD_FLOAT) {+ if (elem_size == 3) {+ if (srcdst & SLJIT_MEM) {+ if (type & SLJIT_SIMD_STORE)+ op = lane_index == 0 ? MOVLPD_m_x : MOVHPD_m_x;+ else+ op = lane_index == 0 ? MOVLPD_x_m : MOVHPD_x_m;++ /* VEX prefix clears upper bits of the target register. */+ if (use_vex && ((type & SLJIT_SIMD_STORE) || reg_size == 4 || freg == TMP_FREG))+ FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2+ | ((type & SLJIT_SIMD_STORE) ? 0 : VEX_SSE2_OPV), freg, (type & SLJIT_SIMD_STORE) ? 0 : freg, srcdst, srcdstw));+ else+ FAIL_IF(emit_groupf(compiler, op | EX86_PREF_66 | EX86_SSE2, freg, srcdst, srcdstw));++ /* In case of store, freg is not TMP_FREG. */+ } else if (type & SLJIT_SIMD_STORE) {+ if (lane_index == 1) {+ if (use_vex)+ return emit_vex_instruction(compiler, MOVHLPS_x_x | EX86_SSE2 | VEX_SSE2_OPV, srcdst, srcdst, freg, 0);+ return emit_groupf(compiler, MOVHLPS_x_x | EX86_SSE2, srcdst, freg, 0);+ }+ if (use_vex)+ return emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, srcdst, srcdst, freg, 0);+ return emit_sse2_load(compiler, 0, srcdst, freg, 0);+ } else if (use_vex && (reg_size == 4 || freg == TMP_FREG)) {+ if (lane_index == 1)+ FAIL_IF(emit_vex_instruction(compiler, MOVLHPS_x_x | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, srcdst, 0));+ else+ FAIL_IF(emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, srcdst, 0));+ } else {+ if (lane_index == 1)+ FAIL_IF(emit_groupf(compiler, MOVLHPS_x_x | EX86_SSE2, freg, srcdst, 0));+ else+ FAIL_IF(emit_sse2_load(compiler, 0, freg, srcdst, 0));+ }+ } else if (type & SLJIT_SIMD_STORE) {+ if (lane_index == 0) {+ if (use_vex)+ return emit_vex_instruction(compiler, ((srcdst & SLJIT_MEM) ? MOVSD_xm_x : MOVSD_x_xm) | EX86_PREF_F3 | EX86_SSE2+ | ((srcdst & SLJIT_MEM) ? 0 : VEX_SSE2_OPV), freg, ((srcdst & SLJIT_MEM) ? 0 : freg), srcdst, srcdstw);+ return emit_sse2_store(compiler, 1, srcdst, srcdstw, freg);+ }++ if (srcdst & SLJIT_MEM) {+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, 0, srcdst, srcdstw));+ else+ FAIL_IF(emit_groupf_ext(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, srcdst, srcdstw));+ return emit_byte(compiler, U8(lane_index));+ }++ if (use_vex) {+ FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, srcdst, freg, freg, 0));+ return emit_byte(compiler, U8(lane_index));+ }++ if (srcdst == freg)+ op = SHUFPS_x_xm | EX86_SSE2;+ else {+ switch (lane_index) {+ case 1:+ op = MOVSHDUP_x_xm | EX86_PREF_F3 | EX86_SSE2;+ break;+ case 2:+ op = MOVHLPS_x_x | EX86_SSE2;+ break;+ default:+ SLJIT_ASSERT(lane_index == 3);+ op = PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2;+ break;+ }+ }++ FAIL_IF(emit_groupf(compiler, op, srcdst, freg, 0));++ op &= 0xff;+ if (op == SHUFPS_x_xm || op == PSHUFD_x_xm)+ return emit_byte(compiler, U8(lane_index));++ return SLJIT_SUCCESS;+ } else {+ if (lane_index != 0 || (srcdst & SLJIT_MEM)) {+ FAIL_IF(emit_groupf_ext(compiler, INSERTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, srcdst, srcdstw));+ FAIL_IF(emit_byte(compiler, U8(lane_index << 4)));+ } else+ FAIL_IF(emit_sse2_store(compiler, 1, freg, 0, srcdst));+ }++ if (freg != TMP_FREG || (type & SLJIT_SIMD_STORE))+ return SLJIT_SUCCESS;++ SLJIT_ASSERT(reg_size == 5);++ if (type & SLJIT_SIMD_LANE_ZERO) {+ FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg_orig, 0, TMP_FREG, 0));+ return emit_byte(compiler, 0x4e);+ }++ FAIL_IF(emit_vex_instruction(compiler, VINSERTF128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, freg_orig, freg_orig, TMP_FREG, 0));+ return emit_byte(compiler, 1);+ }++ if (srcdst == SLJIT_IMM) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcdstw);+ srcdst = TMP_REG1;+ srcdstw = 0;+ }++ op = 3;++ switch (elem_size) {+ case 0:+ opcode = (type & SLJIT_SIMD_STORE) ? PEXTRB_rm_x_i8 : PINSRB_x_rm_i8;+ break;+ case 1:+ if (!(type & SLJIT_SIMD_STORE)) {+ op = 2;+ opcode = PINSRW_x_rm_i8;+ } else+ opcode = PEXTRW_rm_x_i8;+ break;+ case 2:+ opcode = (type & SLJIT_SIMD_STORE) ? PEXTRD_rm_x_i8 : PINSRD_x_rm_i8;+ break;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ case 3:+ /* PINSRQ / PEXTRQ */+ opcode = (type & SLJIT_SIMD_STORE) ? PEXTRD_rm_x_i8 : PINSRD_x_rm_i8;+ compiler->mode32 = 0;+ break;+#endif /* SLJIT_CONFIG_X86_64 */+ }++ if (use_vex && (type & SLJIT_SIMD_STORE)) {+ op = opcode | ((op == 3) ? VEX_OP_0F3A : 0);+ FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | VEX_AUTO_W | EX86_SSE2_OP1 | VEX_SSE2_OPV, freg, 0, srcdst, srcdstw));+ } else {+ inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, srcdst, srcdstw);+ FAIL_IF(!inst);+ inst[0] = GROUP_0F;++ if (op == 3) {+ inst[1] = 0x3a;+ inst[2] = opcode;+ } else+ inst[1] = opcode;+ }++ FAIL_IF(emit_byte(compiler, U8(lane_index)));++ if (!(type & SLJIT_SIMD_LANE_SIGNED) || (srcdst & SLJIT_MEM)) {+ if (freg == TMP_FREG && !(type & SLJIT_SIMD_STORE)) {+ SLJIT_ASSERT(reg_size == 5);++ if (type & SLJIT_SIMD_LANE_ZERO) {+ FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg_orig, 0, TMP_FREG, 0));+ return emit_byte(compiler, 0x4e);+ }++ FAIL_IF(emit_vex_instruction(compiler, VINSERTI128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, freg_orig, freg_orig, TMP_FREG, 0));+ return emit_byte(compiler, 1);+ }++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (srcdst_orig & SLJIT_MEM)+ return emit_mov(compiler, srcdst_orig, srcdstw_orig, TMP_REG1, 0);+#endif /* SLJIT_CONFIG_X86_32 */+ return SLJIT_SUCCESS;+ }++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (elem_size >= 3)+ return SLJIT_SUCCESS;++ compiler->mode32 = (type & SLJIT_32);++ op = 2;++ if (elem_size == 0)+ op |= EX86_REX;++ if (elem_size == 2) {+ if (type & SLJIT_32)+ return SLJIT_SUCCESS;++ SLJIT_ASSERT(!(compiler->mode32));+ op = 1;+ }++ inst = emit_x86_instruction(compiler, op, srcdst, 0, srcdst, 0);+ FAIL_IF(!inst);++ if (op != 1) {+ inst[0] = GROUP_0F;+ inst[1] = U8((elem_size == 0) ? MOVSX_r_rm8 : MOVSX_r_rm16);+ } else+ inst[0] = MOVSXD_r_rm;+#else /* !SLJIT_CONFIG_X86_64 */+ if (elem_size >= 2)+ return SLJIT_SUCCESS;++ FAIL_IF(emit_groupf(compiler, (elem_size == 0) ? MOVSX_r_rm8 : MOVSX_r_rm16,+ (srcdst_orig != 0 && FAST_IS_REG(srcdst_orig)) ? srcdst_orig : srcdst, srcdst, 0));++ if (srcdst_orig & SLJIT_MEM)+ return emit_mov(compiler, srcdst_orig, srcdstw_orig, TMP_REG1, 0);+#endif /* SLJIT_CONFIG_X86_64 */+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_s32 src_lane_index)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);+ sljit_uw pref;+ sljit_u8 byte;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 opcode3 = TMP_REG1;+#else /* !SLJIT_CONFIG_X86_32 */+ sljit_s32 opcode3 = SLJIT_S0;+#endif /* SLJIT_CONFIG_X86_32 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index));++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif /* SLJIT_CONFIG_X86_64 */+ SLJIT_ASSERT(reg_map[opcode3] == 3);++ if (reg_size == 5) {+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))+ return SLJIT_ERR_UNSUPPORTED;+ use_vex = 1;+ } else if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_FLOAT) {+ pref = 0;+ byte = U8(src_lane_index);++ if (elem_size == 3) {+ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 5) {+ if (src_lane_index == 0)+ return emit_vex_instruction(compiler, VBROADCASTSD_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, 0);++ FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0));++ byte = U8(byte | (byte << 2));+ return emit_byte(compiler, U8(byte | (byte << 4)));+ }++ if (src_lane_index == 0) {+ if (use_vex)+ return emit_vex_instruction(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, 0, src, 0);+ return emit_groupf(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, src, 0);+ }++ /* Changes it to SHUFPD_x_xm. */+ pref = EX86_PREF_66;+ } else if (elem_size != 2)+ return SLJIT_ERR_UNSUPPORTED;+ else if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 5) {+ SLJIT_ASSERT(elem_size == 2);++ if (src_lane_index == 0)+ return emit_vex_instruction(compiler, VBROADCASTSS_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, 0);++ FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0));++ byte = 0x44;+ if (src_lane_index >= 4) {+ byte = 0xee;+ src_lane_index -= 4;+ }++ FAIL_IF(emit_byte(compiler, byte));+ FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | VEX_256 | pref | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, freg, 0));+ byte = U8(src_lane_index);+ } else if (use_vex) {+ FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | pref | EX86_SSE2 | VEX_SSE2_OPV, freg, src, src, 0));+ } else {+ if (freg != src)+ FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | pref | EX86_SSE2, freg, src, 0));++ FAIL_IF(emit_groupf(compiler, SHUFPS_x_xm | pref | EX86_SSE2, freg, freg, 0));+ }++ if (elem_size == 2) {+ byte = U8(byte | (byte << 2));+ byte = U8(byte | (byte << 4));+ } else+ byte = U8(byte | (byte << 1));++ return emit_byte(compiler, U8(byte));+ }++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (elem_size == 0) {+ if (reg_size == 5 && src_lane_index >= 16) {+ FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0));+ FAIL_IF(emit_byte(compiler, src_lane_index >= 24 ? 0xff : 0xaa));+ src_lane_index &= 0x7;+ src = freg;+ }++ if (src_lane_index != 0 || (freg != src && (!(cpu_feature_list & CPU_FEATURE_AVX2) || !use_vex))) {+ pref = 0;++ if ((src_lane_index & 0x3) == 0) {+ pref = EX86_PREF_66;+ byte = U8(src_lane_index >> 2);+ } else if (src_lane_index < 8 && (src_lane_index & 0x1) == 0) {+ pref = EX86_PREF_F2;+ byte = U8(src_lane_index >> 1);+ } else {+ if (!use_vex) {+ if (freg != src)+ FAIL_IF(emit_groupf(compiler, MOVDQA_x_xm | EX86_PREF_66 | EX86_SSE2, freg, src, 0));++ FAIL_IF(emit_groupf(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2, opcode3, freg, 0));+ } else+ FAIL_IF(emit_vex_instruction(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2 | VEX_SSE2_OPV, opcode3, freg, src, 0));++ FAIL_IF(emit_byte(compiler, U8(src_lane_index)));+ }++ if (pref != 0) {+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, 0, src, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, src, 0));+ FAIL_IF(emit_byte(compiler, byte));+ }++ src = freg;+ }++ if (use_vex && (cpu_feature_list & CPU_FEATURE_AVX2))+ return emit_vex_instruction(compiler, VPBROADCASTB_x_xm | (reg_size == 5 ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, 0);++ SLJIT_ASSERT(reg_size == 4);+ FAIL_IF(emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, TMP_FREG, 0));+ return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, TMP_FREG, 0);+ }++ if ((cpu_feature_list & CPU_FEATURE_AVX2) && use_vex && src_lane_index == 0 && elem_size <= 3) {+ switch (elem_size) {+ case 1:+ pref = VPBROADCASTW_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;+ break;+ case 2:+ pref = VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;+ break;+ default:+ pref = VPBROADCASTQ_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;+ break;+ }++ if (reg_size == 5)+ pref |= VEX_256;++ return emit_vex_instruction(compiler, pref, freg, 0, src, 0);+ }++ if (reg_size == 5) {+ switch (elem_size) {+ case 1:+ byte = U8(src_lane_index & 0x3);+ src_lane_index >>= 2;+ pref = PSHUFLW_x_xm | VEX_256 | ((src_lane_index & 1) == 0 ? EX86_PREF_F2 : EX86_PREF_F3) | EX86_SSE2;+ break;+ case 2:+ byte = U8(src_lane_index & 0x3);+ src_lane_index >>= 1;+ pref = PSHUFD_x_xm | VEX_256 | EX86_PREF_66 | EX86_SSE2;+ break;+ case 3:+ pref = 0;+ break;+ default:+ FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0));+ return emit_byte(compiler, U8(src_lane_index == 0 ? 0x44 : 0xee));+ }++ if (pref != 0) {+ FAIL_IF(emit_vex_instruction(compiler, pref, freg, 0, src, 0));+ byte = U8(byte | (byte << 2));+ FAIL_IF(emit_byte(compiler, U8(byte | (byte << 4))));++ if (src_lane_index == 0)+ return emit_vex_instruction(compiler, VPBROADCASTQ_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, freg, 0);++ src = freg;+ }++ FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0));+ byte = U8(src_lane_index);+ byte = U8(byte | (byte << 2));+ return emit_byte(compiler, U8(byte | (byte << 4)));+ }++ switch (elem_size) {+ case 1:+ byte = U8(src_lane_index & 0x3);+ src_lane_index >>= 1;+ pref = (src_lane_index & 2) == 0 ? EX86_PREF_F2 : EX86_PREF_F3;++ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, 0, src, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, src, 0));+ byte = U8(byte | (byte << 2));+ FAIL_IF(emit_byte(compiler, U8(byte | (byte << 4))));++ if ((cpu_feature_list & CPU_FEATURE_AVX2) && use_vex && pref == EX86_PREF_F2)+ return emit_vex_instruction(compiler, VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, freg, 0);++ src = freg;+ /* fallthrough */+ case 2:+ byte = U8(src_lane_index);+ byte = U8(byte | (byte << 2));+ break;+ default:+ byte = U8(src_lane_index << 1);+ byte = U8(byte | (byte << 2) | 0x4);+ break;+ }++ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, 0, src, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, src, 0));+ return emit_byte(compiler, U8(byte | (byte << 4)));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);+ sljit_u8 opcode;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif /* SLJIT_CONFIG_X86_64 */++ if (reg_size == 5) {+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))+ return SLJIT_ERR_UNSUPPORTED;+ use_vex = 1;+ } else if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_FLOAT) {+ if (elem_size != 2 || elem2_size != 3)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (use_vex)+ return emit_vex_instruction(compiler, CVTPS2PD_x_xm | ((reg_size == 5) ? VEX_256 : 0) | EX86_SSE2, freg, 0, src, srcw);+ return emit_groupf(compiler, CVTPS2PD_x_xm | EX86_SSE2, freg, src, srcw);+ }++ switch (elem_size) {+ case 0:+ if (elem2_size == 1)+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXBW_x_xm : PMOVZXBW_x_xm;+ else if (elem2_size == 2)+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXBD_x_xm : PMOVZXBD_x_xm;+ else if (elem2_size == 3)+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXBQ_x_xm : PMOVZXBQ_x_xm;+ else+ return SLJIT_ERR_UNSUPPORTED;+ break;+ case 1:+ if (elem2_size == 2)+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXWD_x_xm : PMOVZXWD_x_xm;+ else if (elem2_size == 3)+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXWQ_x_xm : PMOVZXWQ_x_xm;+ else+ return SLJIT_ERR_UNSUPPORTED;+ break;+ case 2:+ if (elem2_size == 3)+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXDQ_x_xm : PMOVZXDQ_x_xm;+ else+ return SLJIT_ERR_UNSUPPORTED;+ break;+ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (use_vex)+ return emit_vex_instruction(compiler, opcode | ((reg_size == 5) ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, srcw);+ return emit_groupf_ext(compiler, opcode | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, src, srcw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 dst, sljit_sw dstw)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);+ sljit_s32 dst_r;+ sljit_uw op;+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw));++ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif /* SLJIT_CONFIG_X86_64 */++ if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2))+ return SLJIT_ERR_UNSUPPORTED;++ if (reg_size == 4) {+ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ op = EX86_PREF_66 | EX86_SSE2_OP2;++ switch (elem_size) {+ case 1:+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, freg, freg, 0));+ else+ FAIL_IF(emit_groupf(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, freg, 0));+ freg = TMP_FREG;+ break;+ case 2:+ op = EX86_SSE2_OP2;+ break;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ op |= (elem_size < 2) ? PMOVMSKB_r_x : MOVMSKPS_r_x;++ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, op, dst_r, 0, freg, 0));+ else+ FAIL_IF(emit_groupf(compiler, op, dst_r, freg, 0));++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = type & SLJIT_32;+#endif /* SLJIT_CONFIG_X86_64 */++ if (elem_size == 1) {+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 8, dst_r, 0);+ FAIL_IF(!inst);+ inst[1] |= SHR;+ }++ if (dst_r == TMP_REG1)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);++ return SLJIT_SUCCESS;+ }++ if (reg_size != 5 || !(cpu_feature_list & CPU_FEATURE_AVX2))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (elem_size == 1) {+ FAIL_IF(emit_vex_instruction(compiler, VEXTRACTI128_x_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, 0, TMP_FREG, 0));+ FAIL_IF(emit_byte(compiler, 1));+ FAIL_IF(emit_vex_instruction(compiler, PACKSSWB_x_xm | VEX_256 | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, freg, TMP_FREG, 0));+ FAIL_IF(emit_groupf(compiler, PMOVMSKB_r_x | EX86_PREF_66 | EX86_SSE2_OP2, dst_r, TMP_FREG, 0));+ } else {+ op = MOVMSKPS_r_x | VEX_256 | EX86_SSE2_OP2;++ if (elem_size == 0)+ op = PMOVMSKB_r_x | VEX_256 | EX86_PREF_66 | EX86_SSE2_OP2;+ else if (elem_size == 3)+ op |= EX86_PREF_66;++ FAIL_IF(emit_vex_instruction(compiler, op, dst_r, 0, freg, 0));+ }++ if (dst_r == TMP_REG1) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = type & SLJIT_32;+#endif /* SLJIT_CONFIG_X86_64 */+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src_freg)+{+ sljit_uw op = ((type & SLJIT_SIMD_FLOAT) ? MOVAPS_x_xm : MOVDQA_x_xm) | EX86_SSE2;++ SLJIT_ASSERT(SLJIT_SIMD_GET_REG_SIZE(type) == 4);++ if (!(type & SLJIT_SIMD_FLOAT) || SLJIT_SIMD_GET_ELEM_SIZE(type) == 3)+ op |= EX86_PREF_66;++ return emit_groupf(compiler, op, dst_freg, src_freg, 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_uw op = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg));++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif /* SLJIT_CONFIG_X86_64 */++ if (reg_size == 5) {+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))+ return SLJIT_ERR_UNSUPPORTED;+ } else if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))+ return SLJIT_ERR_UNSUPPORTED;++ switch (SLJIT_SIMD_GET_OPCODE(type)) {+ case SLJIT_SIMD_OP2_AND:+ op = (type & SLJIT_SIMD_FLOAT) ? ANDPD_x_xm : PAND_x_xm;++ if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3)+ op |= EX86_PREF_66;+ break;+ case SLJIT_SIMD_OP2_OR:+ op = (type & SLJIT_SIMD_FLOAT) ? ORPD_x_xm : POR_x_xm;++ if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3)+ op |= EX86_PREF_66;+ break;+ case SLJIT_SIMD_OP2_XOR:+ op = (type & SLJIT_SIMD_FLOAT) ? XORPD_x_xm : PXOR_x_xm;++ if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3)+ op |= EX86_PREF_66;+ break;+ }++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (reg_size == 5 || ((cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX))) {+ if (reg_size == 5)+ op |= VEX_256;++ return emit_vex_instruction(compiler, op | EX86_SSE2 | VEX_SSE2_OPV, dst_freg, src1_freg, src2_freg, 0);+ }++ if (dst_freg != src1_freg) {+ if (dst_freg == src2_freg)+ src2_freg = src1_freg;+ else+ FAIL_IF(emit_simd_mov(compiler, type, dst_freg, src1_freg));+ }++ FAIL_IF(emit_groupf(compiler, op | EX86_SSE2, dst_freg, src2_freg, 0));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst_reg,+ sljit_s32 mem_reg)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op1(compiler, op, dst_reg, 0, SLJIT_MEM1(mem_reg), 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src_reg,+ sljit_s32 mem_reg,+ sljit_s32 temp_reg)+{+ sljit_uw pref;+ sljit_s32 free_reg = TMP_REG1;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_sw srcw = 0;+ sljit_sw tempw = 0;+#endif /* SLJIT_CONFIG_X86_32 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));+ CHECK_EXTRA_REGS(src_reg, srcw, (void)0);+ CHECK_EXTRA_REGS(temp_reg, tempw, (void)0);++ SLJIT_ASSERT(FAST_IS_REG(src_reg) || src_reg == SLJIT_MEM1(SLJIT_SP));+ SLJIT_ASSERT(FAST_IS_REG(temp_reg) || temp_reg == SLJIT_MEM1(SLJIT_SP));++ op = GET_OPCODE(op);+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if ((src_reg & SLJIT_MEM) || (op == SLJIT_MOV_U8 && reg_map[src_reg] >= 4)) {+ /* Src is virtual register or its low byte is not accessible. */+ SLJIT_ASSERT(src_reg != SLJIT_R1);+ free_reg = src_reg;++ EMIT_MOV(compiler, TMP_REG1, 0, src_reg, srcw);+ src_reg = TMP_REG1;++ if (mem_reg == src_reg)+ mem_reg = TMP_REG1;+ }+#endif /* SLJIT_CONFIG_X86_32 */++ if (temp_reg != SLJIT_R0) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;++ EMIT_MOV(compiler, free_reg, 0, SLJIT_R0, 0);+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, 0);++ if (src_reg == SLJIT_R0)+ src_reg = free_reg;+ if (mem_reg == SLJIT_R0)+ mem_reg = free_reg;+#else /* !SLJIT_CONFIG_X86_64 */+ if (src_reg == TMP_REG1 && mem_reg == SLJIT_R0 && (free_reg & SLJIT_MEM)) {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R1, 0);+ EMIT_MOV(compiler, SLJIT_R1, 0, SLJIT_R0, 0);+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw);++ mem_reg = SLJIT_R1;+ free_reg = SLJIT_R1;+ } else {+ EMIT_MOV(compiler, free_reg, 0, SLJIT_R0, 0);+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw);++ if (src_reg == SLJIT_R0)+ src_reg = free_reg;+ if (mem_reg == SLJIT_R0)+ mem_reg = free_reg;+ }+#endif /* SLJIT_CONFIG_X86_64 */+ }++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = op != SLJIT_MOV && op != SLJIT_MOV_P;+#endif /* SLJIT_CONFIG_X86_64 */++ /* Lock prefix. */+ FAIL_IF(emit_byte(compiler, GROUP_LOCK));++ pref = 0;+ if (op == SLJIT_MOV_U16)+ pref = EX86_HALF_ARG | EX86_PREF_66;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (op == SLJIT_MOV_U8)+ pref = EX86_REX;+#endif /* SLJIT_CONFIG_X86_64 */++ FAIL_IF(emit_groupf(compiler, (op == SLJIT_MOV_U8 ? CMPXCHG_rm8_r : CMPXCHG_rm_r) | pref, src_reg, SLJIT_MEM1(mem_reg), 0));++ if (temp_reg != SLJIT_R0) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+ return emit_mov(compiler, SLJIT_R0, 0, TMP_REG1, 0);+#else /* !SLJIT_CONFIG_X86_64 */+ EMIT_MOV(compiler, SLJIT_R0, 0, free_reg, 0);+ if (free_reg != TMP_REG1)+ return emit_mov(compiler, free_reg, 0, (free_reg == SLJIT_R1) ? SLJIT_MEM1(SLJIT_SP) : TMP_REG1, 0);+#endif /* SLJIT_CONFIG_X86_64 */+ }+ 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));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+#endif++ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ 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, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);+ return compiler->error;+#else+ return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0);+#endif+ }+#endif++ if (offset != 0)+ 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_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ sljit_u8 *inst;+ struct sljit_const *const_;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_s32 reg;+#endif++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (emit_load_imm64(compiler, reg, init_value))+ return NULL;+#else+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value))+ return NULL;+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 1);+ PTR_FAIL_IF(!inst);++ inst[0] = SLJIT_INST_CONST;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (dst & SLJIT_MEM)+ if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))+ return NULL;+#endif++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_u8 *inst;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_s32 reg;+#endif /* SLJIT_CONFIG_X86_64 */++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ PTR_FAIL_IF(emit_load_imm64(compiler, reg, 0));+ jump->addr = compiler->size;++ if (reg_map[reg] >= 8)+ jump->flags |= MOV_ADDR_HI;+#else /* !SLJIT_CONFIG_X86_64 */+ PTR_FAIL_IF(emit_mov(compiler, dst, dstw, SLJIT_IMM, 0));+#endif /* SLJIT_CONFIG_X86_64 */++ inst = (sljit_u8*)ensure_buf(compiler, 1);+ PTR_FAIL_IF(!inst);++ inst[0] = SLJIT_INST_MOV_ADDR;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_mov(compiler, dst, dstw, TMP_REG1, 0));+#endif /* SLJIT_CONFIG_X86_64 */++ return jump; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
− src/c/pcre2/src/sljit/sljitProtExecAllocator.c
@@ -1,474 +0,0 @@-/*- * Stack-less Just-In-Time compiler- *- * 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:- *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.- *- * 2. Redistributions in binary form must reproduce the above copyright notice, this list- * of conditions and the following disclaimer in the documentation and/or other materials- * provided with the distribution.- *- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT- * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.- */--/*- This file contains a simple executable memory allocator-- It is assumed, that executable code blocks are usually medium (or sometimes- large) memory blocks, and the allocator is not too frequently called (less- optimized than other allocators). Thus, using it as a generic allocator is- not suggested.-- How does it work:- Memory is allocated in continuous memory areas called chunks by alloc_chunk()- Chunk format:- [ block ][ block ] ... [ block ][ block terminator ]-- All blocks and the block terminator is started with block_header. The block- header contains the size of the previous and the next block. These sizes- can also contain special values.- Block size:- 0 - The block is a free_block, with a different size member.- 1 - The block is a block terminator.- n - The block is used at the moment, and the value contains its size.- Previous block size:- 0 - This is the first block of the memory chunk.- n - The size of the previous block.-- Using these size values we can go forward or backward on the block chain.- The unused blocks are stored in a chain list pointed by free_blocks. This- list is useful if we need to find a suitable memory area when the allocator- is called.-- When a block is freed, the new free block is connected to its adjacent free- blocks if possible.-- [ free block ][ used block ][ free block ]- and "used block" is freed, the three blocks are connected together:- [ one big free block ]-*/--/* --------------------------------------------------------------------- */-/* System (OS) functions */-/* --------------------------------------------------------------------- */--/* 64 KByte. */-#define CHUNK_SIZE (sljit_uw)0x10000--struct chunk_header {- void *executable;-};--/*- alloc_chunk / free_chunk :- * allocate executable system memory chunks- * the size is always divisible by CHUNK_SIZE- SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK :- * provided as part of sljitUtils- * only the allocator requires this lock, sljit is fully thread safe- as it only uses local variables-*/--#ifndef __NetBSD__-#include <sys/stat.h>-#include <fcntl.h>-#include <stdio.h>-#include <string.h>--#ifndef O_NOATIME-#define O_NOATIME 0-#endif--/* this is a linux extension available since kernel 3.11 */-#ifndef O_TMPFILE-#define O_TMPFILE 020200000-#endif--#ifndef _GNU_SOURCE-char *secure_getenv(const char *name);-int mkostemp(char *template, int flags);-#endif--static SLJIT_INLINE int create_tempfile(void)-{- int fd;- char tmp_name[256];- size_t tmp_name_len = 0;- char *dir;- struct stat st;-#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED- mode_t mode;-#endif--#ifdef HAVE_MEMFD_CREATE- /* this is a GNU extension, make sure to use -D_GNU_SOURCE */- fd = memfd_create("sljit", MFD_CLOEXEC);- if (fd != -1) {- fchmod(fd, 0);- return fd;- }-#endif-- dir = secure_getenv("TMPDIR");-- if (dir) {- tmp_name_len = strlen(dir);- if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)) {- if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode))- strcpy(tmp_name, dir);- }- }--#ifdef P_tmpdir- if (!tmp_name_len) {- tmp_name_len = strlen(P_tmpdir);- if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name))- strcpy(tmp_name, P_tmpdir);- }-#endif- if (!tmp_name_len) {- strcpy(tmp_name, "/tmp");- tmp_name_len = 4;- }-- SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name));-- if (tmp_name[tmp_name_len - 1] == '/')- tmp_name[--tmp_name_len] = '\0';--#ifdef __linux__- /*- * the previous trimming might had left an empty string if TMPDIR="/"- * so work around the problem below- */- fd = open(tmp_name_len ? tmp_name : "/",- O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0);- if (fd != -1)- return fd;-#endif-- if (tmp_name_len + 7 >= sizeof(tmp_name))- return -1;-- strcpy(tmp_name + tmp_name_len, "/XXXXXX");-#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED- mode = umask(0777);-#endif- fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME);-#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED- umask(mode);-#else- fchmod(fd, 0);-#endif-- if (fd == -1)- return -1;-- if (unlink(tmp_name)) {- close(fd);- return -1;- }-- return fd;-}--static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size)-{- struct chunk_header *retval;- int fd;-- fd = create_tempfile();- if (fd == -1)- return NULL;-- if (ftruncate(fd, (off_t)size)) {- close(fd);- return NULL;- }-- retval = (struct chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);-- if (retval == MAP_FAILED) {- close(fd);- return NULL;- }-- retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);-- if (retval->executable == MAP_FAILED) {- munmap((void *)retval, size);- close(fd);- return NULL;- }-- close(fd);- return retval;-}-#else-/*- * MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to- * adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed- */-static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size)-{- struct chunk_header *retval;-- retval = (struct chunk_header *)mmap(NULL, size,- PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC),- MAP_ANON | MAP_SHARED, -1, 0);-- if (retval == MAP_FAILED)- return NULL;-- retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP);- if (retval->executable == MAP_FAILED) {- munmap((void *)retval, size);- return NULL;- }-- if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) {- munmap(retval->executable, size);- munmap((void *)retval, size);- return NULL;- }-- return retval;-}-#endif /* NetBSD */--static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)-{- struct chunk_header *header = ((struct chunk_header *)chunk) - 1;-- munmap(header->executable, size);- munmap((void *)header, size);-}--/* --------------------------------------------------------------------- */-/* Common functions */-/* --------------------------------------------------------------------- */--#define CHUNK_MASK (~(CHUNK_SIZE - 1))--struct block_header {- sljit_uw size;- sljit_uw prev_size;- sljit_sw executable_offset;-};--struct free_block {- struct block_header header;- struct free_block *next;- struct free_block *prev;- sljit_uw size;-};--#define AS_BLOCK_HEADER(base, offset) \- ((struct block_header*)(((sljit_u8*)base) + offset))-#define AS_FREE_BLOCK(base, offset) \- ((struct free_block*)(((sljit_u8*)base) + offset))-#define MEM_START(base) ((void*)((base) + 1))-#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7)--static struct free_block* free_blocks;-static sljit_uw allocated_size;-static sljit_uw total_size;--static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)-{- free_block->header.size = 0;- free_block->size = size;-- free_block->next = free_blocks;- free_block->prev = NULL;- if (free_blocks)- free_blocks->prev = free_block;- free_blocks = free_block;-}--static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)-{- if (free_block->next)- free_block->next->prev = free_block->prev;-- if (free_block->prev)- free_block->prev->next = free_block->next;- else {- SLJIT_ASSERT(free_blocks == free_block);- free_blocks = free_block->next;- }-}--SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)-{- struct chunk_header *chunk_header;- struct block_header *header;- struct block_header *next_header;- struct free_block *free_block;- sljit_uw chunk_size;- sljit_sw executable_offset;-- SLJIT_ALLOCATOR_LOCK();- if (size < (64 - sizeof(struct block_header)))- size = (64 - sizeof(struct block_header));- size = ALIGN_SIZE(size);-- free_block = free_blocks;- while (free_block) {- if (free_block->size >= size) {- chunk_size = free_block->size;- if (chunk_size > size + 64) {- /* We just cut a block from the end of the free block. */- chunk_size -= size;- free_block->size = chunk_size;- header = AS_BLOCK_HEADER(free_block, chunk_size);- header->prev_size = chunk_size;- header->executable_offset = free_block->header.executable_offset;- AS_BLOCK_HEADER(header, size)->prev_size = size;- }- else {- sljit_remove_free_block(free_block);- header = (struct block_header*)free_block;- size = chunk_size;- }- allocated_size += size;- header->size = size;- SLJIT_ALLOCATOR_UNLOCK();- return MEM_START(header);- }- free_block = free_block->next;- }-- chunk_size = sizeof(struct chunk_header) + sizeof(struct block_header);- chunk_size = (chunk_size + size + CHUNK_SIZE - 1) & CHUNK_MASK;-- chunk_header = alloc_chunk(chunk_size);- if (!chunk_header) {- SLJIT_ALLOCATOR_UNLOCK();- return NULL;- }-- executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (sljit_u8*)chunk_header);-- chunk_size -= sizeof(struct chunk_header) + sizeof(struct block_header);- total_size += chunk_size;-- header = (struct block_header *)(chunk_header + 1);-- header->prev_size = 0;- header->executable_offset = executable_offset;- if (chunk_size > size + 64) {- /* Cut the allocated space into a free and a used block. */- allocated_size += size;- header->size = size;- chunk_size -= size;-- free_block = AS_FREE_BLOCK(header, size);- free_block->header.prev_size = size;- free_block->header.executable_offset = executable_offset;- sljit_insert_free_block(free_block, chunk_size);- next_header = AS_BLOCK_HEADER(free_block, chunk_size);- }- else {- /* All space belongs to this allocation. */- allocated_size += chunk_size;- header->size = chunk_size;- next_header = AS_BLOCK_HEADER(header, chunk_size);- }- next_header->size = 1;- next_header->prev_size = chunk_size;- next_header->executable_offset = executable_offset;- SLJIT_ALLOCATOR_UNLOCK();- return MEM_START(header);-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)-{- struct block_header *header;- struct free_block* free_block;-- SLJIT_ALLOCATOR_LOCK();- header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));- header = AS_BLOCK_HEADER(header, -header->executable_offset);- allocated_size -= header->size;-- /* Connecting free blocks together if possible. */-- /* If header->prev_size == 0, free_block will equal to header.- In this case, free_block->header.size will be > 0. */- free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);- if (SLJIT_UNLIKELY(!free_block->header.size)) {- free_block->size += header->size;- header = AS_BLOCK_HEADER(free_block, free_block->size);- header->prev_size = free_block->size;- }- else {- free_block = (struct free_block*)header;- sljit_insert_free_block(free_block, header->size);- }-- header = AS_BLOCK_HEADER(free_block, free_block->size);- if (SLJIT_UNLIKELY(!header->size)) {- free_block->size += ((struct free_block*)header)->size;- sljit_remove_free_block((struct free_block*)header);- header = AS_BLOCK_HEADER(free_block, free_block->size);- header->prev_size = free_block->size;- }-- /* The whole chunk is free. */- if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {- /* If this block is freed, we still have (allocated_size / 2) free space. */- if (total_size - free_block->size > (allocated_size * 3 / 2)) {- total_size -= free_block->size;- sljit_remove_free_block(free_block);- free_chunk(free_block, free_block->size +- sizeof(struct chunk_header) +- sizeof(struct block_header));- }- }-- SLJIT_ALLOCATOR_UNLOCK();-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)-{- struct free_block* free_block;- struct free_block* next_free_block;-- SLJIT_ALLOCATOR_LOCK();-- free_block = free_blocks;- while (free_block) {- next_free_block = free_block->next;- if (!free_block->header.prev_size && - AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {- total_size -= free_block->size;- sljit_remove_free_block(free_block);- free_chunk(free_block, free_block->size +- sizeof(struct chunk_header) +- sizeof(struct block_header));- }- free_block = next_free_block;- }-- SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));- SLJIT_ALLOCATOR_UNLOCK();-}--SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr)-{- return ((struct block_header *)(ptr))[-1].executable_offset;-}
+ src/c/pcre2/src/sljit/sljitSerialize.c view
@@ -0,0 +1,516 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * 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:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list+ * of conditions and the following disclaimer in the documentation and/or other materials+ * provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_label(struct sljit_jump *jump)+{+ return !(jump->flags & JUMP_ADDR) && (jump->u.label != NULL);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_target(struct sljit_jump *jump)+{+ return (jump->flags & JUMP_ADDR) != 0;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_is_mov_addr(struct sljit_jump *jump)+{+ return (jump->flags & JUMP_MOV_ADDR) != 0;+}++#define SLJIT_SERIALIZE_DEBUG ((sljit_u16)0x1)++struct sljit_serialized_compiler {+ sljit_u32 signature;+ sljit_u16 version;+ sljit_u16 cpu_type;++ sljit_uw buf_segment_count;+ sljit_uw label_count;+ sljit_uw jump_count;+ sljit_uw const_count;++ sljit_s32 options;+ sljit_s32 scratches;+ sljit_s32 saveds;+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ sljit_s32 local_size;+ sljit_uw size;++#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)+ sljit_s32 status_flags_state;+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 args_size;+#endif /* SLJIT_CONFIG_X86_32 */++#if ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ sljit_uw args_size;+#endif /* (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ sljit_uw cpool_diff;+ sljit_uw cpool_fill;+ sljit_uw patches;+#endif /* SLJIT_CONFIG_ARM_V6 */++#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+ sljit_s32 delay_slot;+#endif /* SLJIT_CONFIG_MIPS */++};++struct sljit_serialized_debug_info {+ sljit_sw last_flags;+ sljit_s32 last_return;+ sljit_s32 logical_local_size;+};++struct sljit_serialized_label {+ sljit_uw size;+};++struct sljit_serialized_jump {+ sljit_uw addr;+ sljit_uw flags;+ sljit_uw value;+};++struct sljit_serialized_const {+ sljit_uw addr;+};++#define SLJIT_SERIALIZE_ALIGN(v) (((v) + sizeof(sljit_uw) - 1) & ~(sljit_uw)(sizeof(sljit_uw) - 1))+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#define SLJIT_SERIALIZE_SIGNATURE 0x534c4a54+#else /* !SLJIT_LITTLE_ENDIAN */+#define SLJIT_SERIALIZE_SIGNATURE 0x544a4c53+#endif /* SLJIT_LITTLE_ENDIAN */+#define SLJIT_SERIALIZE_VERSION 1++SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_uw *size)+{+ sljit_uw serialized_size = sizeof(struct sljit_serialized_compiler);+ struct sljit_memory_fragment *buf;+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ struct sljit_serialized_compiler *serialized_compiler;+ struct sljit_serialized_label *serialized_label;+ struct sljit_serialized_jump *serialized_jump;+ struct sljit_serialized_const *serialized_const;+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)+ struct sljit_serialized_debug_info *serialized_debug_info;+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */+ sljit_uw counter, used_size;+ sljit_u8 *result;+ sljit_u8 *ptr;+ SLJIT_UNUSED_ARG(options);++ if (size != NULL)+ *size = 0;++ PTR_FAIL_IF(compiler->error);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)+ if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG))+ serialized_size += sizeof(struct sljit_serialized_debug_info);+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ serialized_size += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));+#endif /* SLJIT_CONFIG_ARM_V6 */++ /* Compute the size of the data. */+ buf = compiler->buf;+ while (buf != NULL) {+ serialized_size += sizeof(sljit_uw) + SLJIT_SERIALIZE_ALIGN(buf->used_size);+ buf = buf->next;+ }++ serialized_size += compiler->label_count * sizeof(struct sljit_serialized_label);++ jump = compiler->jumps;+ while (jump != NULL) {+ serialized_size += sizeof(struct sljit_serialized_jump);+ jump = jump->next;+ }++ const_ = compiler->consts;+ while (const_ != NULL) {+ serialized_size += sizeof(struct sljit_serialized_const);+ const_ = const_->next;+ }++ result = (sljit_u8*)SLJIT_MALLOC(serialized_size, compiler->allocator_data);+ PTR_FAIL_IF_NULL(result);++ if (size != NULL)+ *size = serialized_size;++ ptr = result;+ serialized_compiler = (struct sljit_serialized_compiler*)ptr;+ ptr += sizeof(struct sljit_serialized_compiler);++ serialized_compiler->signature = SLJIT_SERIALIZE_SIGNATURE;+ serialized_compiler->version = SLJIT_SERIALIZE_VERSION;+ serialized_compiler->cpu_type = 0;+ serialized_compiler->label_count = compiler->label_count;+ serialized_compiler->options = compiler->options;+ serialized_compiler->scratches = compiler->scratches;+ serialized_compiler->saveds = compiler->saveds;+ serialized_compiler->fscratches = compiler->fscratches;+ serialized_compiler->fsaveds = compiler->fsaveds;+ serialized_compiler->local_size = compiler->local_size;+ serialized_compiler->size = compiler->size;++#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)+ serialized_compiler->status_flags_state = compiler->status_flags_state;+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \+ || ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ serialized_compiler->args_size = compiler->args_size;+#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ serialized_compiler->cpool_diff = compiler->cpool_diff;+ serialized_compiler->cpool_fill = compiler->cpool_fill;+ serialized_compiler->patches = compiler->patches;++ SLJIT_MEMCPY(ptr, compiler->cpool, compiler->cpool_fill * sizeof(sljit_uw));+ SLJIT_MEMCPY(ptr + compiler->cpool_fill * sizeof(sljit_uw), compiler->cpool_unique, compiler->cpool_fill);+ ptr += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));+#endif /* SLJIT_CONFIG_ARM_V6 */++#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+ serialized_compiler->delay_slot = compiler->delay_slot;+#endif /* SLJIT_CONFIG_MIPS */++ buf = compiler->buf;+ counter = 0;+ while (buf != NULL) {+ used_size = buf->used_size;+ *(sljit_uw*)ptr = used_size;+ ptr += sizeof(sljit_uw);+ SLJIT_MEMCPY(ptr, buf->memory, used_size);+ ptr += SLJIT_SERIALIZE_ALIGN(used_size);+ buf = buf->next;+ counter++;+ }+ serialized_compiler->buf_segment_count = counter;++ label = compiler->labels;+ while (label != NULL) {+ serialized_label = (struct sljit_serialized_label*)ptr;+ serialized_label->size = label->size;+ ptr += sizeof(struct sljit_serialized_label);+ label = label->next;+ }++ jump = compiler->jumps;+ counter = 0;+ while (jump != NULL) {+ serialized_jump = (struct sljit_serialized_jump*)ptr;+ serialized_jump->addr = jump->addr;+ serialized_jump->flags = jump->flags;++ if (jump->flags & JUMP_ADDR)+ serialized_jump->value = jump->u.target;+ else if (jump->u.label != NULL)+ serialized_jump->value = jump->u.label->u.index;+ else+ serialized_jump->value = SLJIT_MAX_ADDRESS;++ ptr += sizeof(struct sljit_serialized_jump);+ jump = jump->next;+ counter++;+ }+ serialized_compiler->jump_count = counter;++ const_ = compiler->consts;+ counter = 0;+ while (const_ != NULL) {+ serialized_const = (struct sljit_serialized_const*)ptr;+ serialized_const->addr = const_->addr;+ ptr += sizeof(struct sljit_serialized_const);+ const_ = const_->next;+ counter++;+ }+ serialized_compiler->const_count = counter;++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)+ if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG)) {+ serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;+ serialized_debug_info->last_flags = compiler->last_flags;+ serialized_debug_info->last_return = compiler->last_return;+ serialized_debug_info->logical_local_size = compiler->logical_local_size;+ serialized_compiler->cpu_type |= SLJIT_SERIALIZE_DEBUG;+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ ptr += sizeof(struct sljit_serialized_debug_info);+#endif /* SLJIT_DEBUG */+ }+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */++ SLJIT_ASSERT((sljit_uw)(ptr - result) == serialized_size);+ return (sljit_uw*)result;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit_uw* buffer, sljit_uw size,+ sljit_s32 options, void *allocator_data)+{+ struct sljit_compiler *compiler;+ struct sljit_serialized_compiler *serialized_compiler;+ struct sljit_serialized_label *serialized_label;+ struct sljit_serialized_jump *serialized_jump;+ struct sljit_serialized_const *serialized_const;+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)+ struct sljit_serialized_debug_info *serialized_debug_info;+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */+ struct sljit_memory_fragment *buf;+ struct sljit_memory_fragment *last_buf;+ struct sljit_label *label;+ struct sljit_label *last_label;+ struct sljit_label **label_list = NULL;+ struct sljit_jump *jump;+ struct sljit_jump *last_jump;+ struct sljit_const *const_;+ struct sljit_const *last_const;+ sljit_u8 *ptr = (sljit_u8*)buffer;+ sljit_u8 *end = ptr + size;+ sljit_uw i, used_size, aligned_size, label_count;+ SLJIT_UNUSED_ARG(options);++ if (size < sizeof(struct sljit_serialized_compiler) || (size & (sizeof(sljit_uw) - 1)) != 0)+ return NULL;++ serialized_compiler = (struct sljit_serialized_compiler*)ptr;++ if (serialized_compiler->signature != SLJIT_SERIALIZE_SIGNATURE || serialized_compiler->version != SLJIT_SERIALIZE_VERSION)+ return NULL;++ compiler = sljit_create_compiler(allocator_data);+ PTR_FAIL_IF(compiler == NULL);++ compiler->label_count = serialized_compiler->label_count;+ compiler->options = serialized_compiler->options;+ compiler->scratches = serialized_compiler->scratches;+ compiler->saveds = serialized_compiler->saveds;+ compiler->fscratches = serialized_compiler->fscratches;+ compiler->fsaveds = serialized_compiler->fsaveds;+ compiler->local_size = serialized_compiler->local_size;+ compiler->size = serialized_compiler->size;++#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)+ compiler->status_flags_state = serialized_compiler->status_flags_state;+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \+ || ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ compiler->args_size = serialized_compiler->args_size;+#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ used_size = serialized_compiler->cpool_fill;+ aligned_size = SLJIT_SERIALIZE_ALIGN(used_size * (sizeof(sljit_uw) + 1));+ compiler->cpool_diff = serialized_compiler->cpool_diff;+ compiler->cpool_fill = used_size;+ compiler->patches = serialized_compiler->patches;++ if ((sljit_uw)(end - ptr) < aligned_size)+ goto error;++ SLJIT_MEMCPY(compiler->cpool, ptr, used_size * sizeof(sljit_uw));+ SLJIT_MEMCPY(compiler->cpool_unique, ptr + used_size * sizeof(sljit_uw), used_size);+ ptr += aligned_size;+#endif /* SLJIT_CONFIG_ARM_V6 */++#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+ compiler->delay_slot = serialized_compiler->delay_slot;+#endif /* SLJIT_CONFIG_MIPS */++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)+ if (!(serialized_compiler->cpu_type & SLJIT_SERIALIZE_DEBUG))+ goto error;+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */++ ptr += sizeof(struct sljit_serialized_compiler);+ i = serialized_compiler->buf_segment_count;+ last_buf = NULL;+ while (i > 0) {+ if ((sljit_uw)(end - ptr) < sizeof(sljit_uw))+ goto error;++ used_size = *(sljit_uw*)ptr;+ aligned_size = SLJIT_SERIALIZE_ALIGN(used_size);+ ptr += sizeof(sljit_uw);++ if ((sljit_uw)(end - ptr) < aligned_size)+ goto error;++ if (last_buf == NULL) {+ SLJIT_ASSERT(compiler->buf != NULL && compiler->buf->next == NULL);+ buf = compiler->buf;+ } else {+ buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);+ if (!buf)+ goto error;+ buf->next = NULL;+ }++ buf->used_size = used_size;+ SLJIT_MEMCPY(buf->memory, ptr, used_size);++ if (last_buf != NULL)+ last_buf->next = buf;+ last_buf = buf;++ ptr += aligned_size;+ i--;+ }++ last_label = NULL;+ label_count = serialized_compiler->label_count;+ if ((sljit_uw)(end - ptr) < label_count * sizeof(struct sljit_serialized_label))+ goto error;++ label_list = (struct sljit_label **)SLJIT_MALLOC(label_count * sizeof(struct sljit_label*), allocator_data);+ if (label_list == NULL)+ goto error;++ for (i = 0; i < label_count; i++) {+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ if (label == NULL)+ goto error;++ serialized_label = (struct sljit_serialized_label*)ptr;+ label->next = NULL;+ label->u.index = i;+ label->size = serialized_label->size;++ if (last_label != NULL)+ last_label->next = label;+ else+ compiler->labels = label;+ last_label = label;++ label_list[i] = label;+ ptr += sizeof(struct sljit_serialized_label);+ }+ compiler->last_label = last_label;++ last_jump = NULL;+ i = serialized_compiler->jump_count;+ if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_jump))+ goto error;++ while (i > 0) {+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ if (jump == NULL)+ goto error;++ serialized_jump = (struct sljit_serialized_jump*)ptr;+ jump->next = NULL;+ jump->addr = serialized_jump->addr;+ jump->flags = serialized_jump->flags;++ if (!(serialized_jump->flags & JUMP_ADDR)) {+ if (serialized_jump->value != SLJIT_MAX_ADDRESS) {+ if (serialized_jump->value >= label_count)+ goto error;+ jump->u.label = label_list[serialized_jump->value];+ } else+ jump->u.label = NULL;+ } else+ jump->u.target = serialized_jump->value;++ if (last_jump != NULL)+ last_jump->next = jump;+ else+ compiler->jumps = jump;+ last_jump = jump;++ ptr += sizeof(struct sljit_serialized_jump);+ i--;+ }+ compiler->last_jump = last_jump;++ SLJIT_FREE(label_list, allocator_data);+ label_list = NULL;++ last_const = NULL;+ i = serialized_compiler->const_count;+ if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_const))+ goto error;++ while (i > 0) {+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ if (const_ == NULL)+ goto error;++ serialized_const = (struct sljit_serialized_const*)ptr;+ const_->next = NULL;+ const_->addr = serialized_const->addr;++ if (last_const != NULL)+ last_const->next = const_;+ else+ compiler->consts = const_;+ last_const = const_;++ ptr += sizeof(struct sljit_serialized_const);+ i--;+ }+ compiler->last_const = last_const;++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)+ if ((sljit_uw)(end - ptr) < sizeof(struct sljit_serialized_debug_info))+ goto error;++ serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;+ compiler->last_flags = (sljit_s32)serialized_debug_info->last_flags;+ compiler->last_return = serialized_debug_info->last_return;+ compiler->logical_local_size = serialized_debug_info->logical_local_size;+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */++ return compiler;++error:+ sljit_free_compiler(compiler);+ if (label_list != NULL)+ SLJIT_FREE(label_list, allocator_data);+ return NULL;+}
− src/c/pcre2/src/sljit/sljitWXExecAllocator.c
@@ -1,229 +0,0 @@-/*- * Stack-less Just-In-Time compiler- *- * 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:- *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.- *- * 2. Redistributions in binary form must reproduce the above copyright notice, this list- * of conditions and the following disclaimer in the documentation and/or other materials- * provided with the distribution.- *- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT- * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.- */--/*- This file contains a simple W^X executable memory allocator for POSIX- like systems and Windows-- In *NIX, MAP_ANON is required (that is considered a feature) so make- sure to set the right availability macros for your system or the code- will fail to build.-- If your system doesn't support mapping of anonymous pages (ex: IRIX) it- is also likely that it doesn't need this allocator and should be using- the standard one instead.-- It allocates a separate map for each code block and may waste a lot of- memory, because whatever was requested, will be rounded up to the page- size (minimum 4KB, but could be even bigger).-- It changes the page permissions (RW <-> RX) as needed and therefore, if you- will be updating the code after it has been generated, need to make sure to- block any concurrent execution, or could result in a SIGBUS, that could- even manifest itself at a different address than the one that was being- modified.-- Only use if you are unable to use the regular allocator because of security- restrictions and adding exceptions to your application or the system are- not possible.-*/--#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \- sljit_update_wx_flags((from), (to), (enable_exec))--#ifndef _WIN32-#include <sys/types.h>-#include <sys/mman.h>--#ifdef __NetBSD__-#if defined(PROT_MPROTECT)-#define check_se_protected(ptr, size) (0)-#define SLJIT_PROT_WX PROT_MPROTECT(PROT_EXEC)-#else /* !PROT_MPROTECT */-#ifdef _NETBSD_SOURCE-#include <sys/param.h>-#else /* !_NETBSD_SOURCE */-typedef unsigned int u_int;-#define devmajor_t sljit_s32-#endif /* _NETBSD_SOURCE */-#include <sys/sysctl.h>-#include <unistd.h>--#define check_se_protected(ptr, size) netbsd_se_protected()--static SLJIT_INLINE int netbsd_se_protected(void)-{- int mib[3];- int paxflags;- size_t len = sizeof(paxflags);-- mib[0] = CTL_PROC;- mib[1] = getpid();- mib[2] = PROC_PID_PAXFLAGS;-- if (SLJIT_UNLIKELY(sysctl(mib, 3, &paxflags, &len, NULL, 0) < 0))- return -1;-- return (paxflags & CTL_PROC_PAXFLAGS_MPROTECT) ? -1 : 0;-}-#endif /* PROT_MPROTECT */-#else /* POSIX */-#define check_se_protected(ptr, size) generic_se_protected(ptr, size)--static SLJIT_INLINE int generic_se_protected(void *ptr, sljit_uw size)-{- if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC)))- return mprotect(ptr, size, PROT_READ | PROT_WRITE);-- return -1;-}-#endif /* NetBSD */--#if defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED-#define SLJIT_SE_LOCK()-#define SLJIT_SE_UNLOCK()-#else /* !SLJIT_SINGLE_THREADED */-#include <pthread.h>-#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock)-#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock)-#endif /* SLJIT_SINGLE_THREADED */--#ifndef SLJIT_PROT_WX-#define SLJIT_PROT_WX 0-#endif /* !SLJIT_PROT_WX */--SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)-{-#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)- static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER;-#endif- static int se_protected = !SLJIT_PROT_WX;- int prot = PROT_READ | PROT_WRITE | SLJIT_PROT_WX;- sljit_uw* ptr;-- if (SLJIT_UNLIKELY(se_protected < 0))- return NULL;--#ifdef PROT_MAX- prot |= PROT_MAX(PROT_READ | PROT_WRITE | PROT_EXEC);-#endif-- size += sizeof(sljit_uw);- ptr = (sljit_uw*)mmap(NULL, size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);-- if (ptr == MAP_FAILED)- return NULL;-- if (SLJIT_UNLIKELY(se_protected > 0)) {- SLJIT_SE_LOCK();- se_protected = check_se_protected(ptr, size);- SLJIT_SE_UNLOCK();- if (SLJIT_UNLIKELY(se_protected < 0)) {- munmap((void *)ptr, size);- return NULL;- }- }-- *ptr++ = size;- return ptr;-}--#undef SLJIT_PROT_WX-#undef SLJIT_SE_UNLOCK-#undef SLJIT_SE_LOCK--SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)-{- sljit_uw *start_ptr = ((sljit_uw*)ptr) - 1;- munmap((void*)start_ptr, *start_ptr);-}--static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)-{- sljit_uw page_mask = (sljit_uw)get_page_alignment();- sljit_uw start = (sljit_uw)from;- sljit_uw end = (sljit_uw)to;- int prot = PROT_READ | (enable_exec ? PROT_EXEC : PROT_WRITE);-- SLJIT_ASSERT(start < end);-- start &= ~page_mask;- end = (end + page_mask) & ~page_mask;-- mprotect((void*)start, end - start, prot);-}--#else /* windows */--SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)-{- sljit_uw *ptr;-- size += sizeof(sljit_uw);- ptr = (sljit_uw*)VirtualAlloc(NULL, size,- MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);-- if (!ptr)- return NULL;-- *ptr++ = size;-- return ptr;-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)-{- sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw);-#if defined(SLJIT_DEBUG) && SLJIT_DEBUG- sljit_uw page_mask = (sljit_uw)get_page_alignment();-- SLJIT_ASSERT(!(start & page_mask));-#endif- VirtualFree((void*)start, 0, MEM_RELEASE);-}--static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)-{- DWORD oldprot;- sljit_uw page_mask = (sljit_uw)get_page_alignment();- sljit_uw start = (sljit_uw)from;- sljit_uw end = (sljit_uw)to;- DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE;-- SLJIT_ASSERT(start < end);-- start &= ~page_mask;- end = (end + page_mask) & ~page_mask;-- VirtualProtect((void*)start, end - start, prot, &oldprot);-}--#endif /* !windows */--SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)-{- /* This allocator does not keep unused memory for future allocations. */-}
+ src/c/pcre2/vms/stdint.h view
@@ -0,0 +1,9 @@+#ifndef MY_VMS_STDINT+#define MY_VMS_STDINT+#include <inttypes.h>+#include <limits.h>+#include <stdbool.h>+#define SIZE_MAX UINT_MAX+#define UINT32_MAX 4294967295u+#define UINT16_MAX (65535)+#endif
src/c/pcre2_chartables.c view
@@ -5,7 +5,8 @@ /* This file was automatically written by the pcre2_dftables auxiliary program. It contains character tables that are used when no external tables are passed to PCRE2 by the application that calls it. The tables-are used only for characters whose code values are less than 256. */+are used only for characters whose code values are less than 256, and+only relevant if not in UCP mode. */ /* This set of tables was written in the C locale. */ @@ -18,13 +19,6 @@ pcre2_dftables manually with the -L option to build tables using the LC_ALL locale. */ -/* The following #include is present because without it gcc 4.x may remove-the array definition from the final binary if PCRE2 is built into a static-library and dead code stripping is activated. This leads to link errors.-Pulling in the header ensures that the array gets flagged as "someone-outside this compilation unit might reference this" and so it will always-be supplied to the linker. */- #ifdef HAVE_CONFIG_H #include "config.h" #endif@@ -163,7 +157,7 @@ 0x02 letter 0x04 lower case letter 0x08 decimal digit- 0x10 alphanumeric or '_'+ 0x10 word (alphanumeric or '_') */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
src/hs/Text/Regex/Pcre2.hs view
@@ -6,11 +6,11 @@ Atop the low-level binding to the C API, we present a high-level interface to add regular expressions to Haskell programs. - All input and output strings are strict `Data.Text.Text`, which maps- directly to how PCRE2 operates on strings of 8-bit-wide code units.+ All input and output strings are strict `Data.Text.Text`, which maps to how+ PCRE2 operates in UTF-8 mode. The C API requires pattern strings to be compiled and the compiled patterns- to be executed on subject strings in discrete steps. We hide this+ to be executed on subject strings in discrete steps. We simplify this procedure, accepting pattern and subject as arguments in a single function, essentially: @@ -53,10 +53,10 @@ [Subject]: The string the compiled regular expression is executed on. [Regex]: A function of the form @`Data.Text.Text` -> result@, where the- argument is the subject. It is \"compiled\" via partial application as- discussed above. (Lens users: A regex has the more abstract form- @`Lens.Micro.Traversal'` `Data.Text.Text` result@, but the concept is the- same.)+ argument is the subject. It is \"compiled\" in the course of producing+ results and may be reused via partial application as discussed above. (Lens+ users: A regex has the more abstract form @`Lens.Micro.Traversal'`+ `Data.Text.Text` result@, but the concept is the same.) [Capture (or capture group)]: Any substrings of the subject matched by the pattern, meaning the whole pattern and any parenthesized groupings. The@@ -76,47 +76,14 @@ @(?\<foo\>...)@. Whether they have names or not, captures are always numbered as described above. - === __Performance__-- Each API function is designed such that, when a regex is obtained, the- underlying C data generated from the pattern and any options is reused for- that regex's lifetime. Care should be taken that the same regex is not- recreated /ex nihilo/ and discarded for each new subject:-- > isEmptyOrHas2Digits :: Text -> Bool- > isEmptyOrHas2Digits s = Text.null s || matches "\\d{2}" s -- bad, fully applied-- Instead, store it in a partially applied state:-- > isEmptyOrHas2Digits = (||) <$> Text.null <*> matches "\\d{2}" -- OK but abstruse-- When in doubt, always create regexes as top-level values:-- > has2Digits :: Text -> Bool- > has2Digits = matches "\\d{2}"- >- > isEmptyOrHas2Digits s = Text.null s || has2Digits s -- good-- Note: Template Haskell regexes are immune from this problem and may be- freely inlined; see below.-- Also of note is the optimization that, for each capture that's more than- half the length of the subject, a zero-copy `Data.Text.Text` is produced in- constant time and space. This can yield a large performance boost in many- cases, for example when splitting lines into key-value pairs as in- the [teaser](https://github.com/sjshuck/hs-pcre2#teasers). A downside,- however, is that retaining these slices in memory will carry the overhead- of the dead portions of the subject (still guaranteed to be less than the- slices in total size).- === __Handling results and errors__ In contrast to [other](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match) [APIs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll) where there are separate functions to request single versus global matching,- we accomplish this /(since 2.0.0)/ in a unified fashion using the- `Control.Applicative.Alternative` typeclass. Typically the user will- choose from two instances, `Maybe` and @[]@:+ we accomplish this in a unified fashion using the+ `Control.Applicative.Alternative` typeclass /(since 2.0.0)/. Typically the+ user will choose from two instances, `Maybe` and @[]@: > b2 :: (Alternative f) => Text -> f Text > b2 = match "b.."@@ -129,11 +96,7 @@ > findAllB2s :: Text -> [Text] > findAllB2s = b2 - Other instances exist for niche uses,- notably @[STM](https://hackage.haskell.org/package/stm/docs/Control-Monad-STM.html#t:STM)@,- that of [optparse-applicative](https://hackage.haskell.org/package/optparse-applicative/docs/Options-Applicative.html#t:Parser),- and those of parser combinator libraries such- as [megaparsec](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec.html#t:ParsecT).+ Other instances exist for niche uses, such as @[STM](https://hackage.haskell.org/package/stm/docs/Control-Monad-STM.html#t:STM)@. By contrast, user errors are thrown purely. If a user error is to be caught, it must be at the site where the match or substitution results are@@ -175,8 +138,8 @@ -- -- 1. A basic working understanding of optics. Many tutorials exist -- online, such as- -- [this](https://hackage.haskell.org/package/lens-tutorial-1.0.4/docs/Control-Lens-Tutorial.html),- -- and videos such as [this](https://www.youtube.com/watch?v=7fbziKgQjnw).+ -- [this](https://hackage.haskell.org/package/lens-tutorial-1.0.5/docs/Control-Lens-Tutorial.html),+ -- and videos such as [this](https://www.youtube.com/watch?v=geV8F59q48E). -- -- 2. A library providing combinators. For lens newcomers, it is -- recommended to grab@@ -190,8 +153,7 @@ -- full [lens](https://hackage.haskell.org/package/lens) library. -- -- We expose a set of traversals that focus on matched substrings within a- -- subject. Like the basic functional regexes, they should be \"compiled\"- -- and memoized, rather than created inline.+ -- subject. -- -- > _nee :: Traversal' Text Text -- > _nee = _matchOpt (Caseless <> MatchWord) "nee"@@ -215,8 +177,7 @@ -- * Compile-time validation --- -- | Despite whatever virtues, the API thus far has some fragility arising- -- from various scenarios:+ -- | The API thus far has some hazards: -- -- * pattern malformation such as mismatched parentheses /(runtime error)/ --@@ -234,8 +195,8 @@ -- backslash requires the sequence @\"\\\\\\\\\"@! -- -- Using a combination of language extensions and pattern introspection- -- features, we provide a Template Haskell API to mitigate these scenarios.- -- To make use of it these must be enabled:+ -- features, we provide a Template Haskell API to mitigate these. To make+ -- use of it these must be enabled: -- -- +--------------------+---------------------------------------+------------------------------+ -- | Extension | Required for | When |@@ -258,7 +219,7 @@ -- +--------------------+---------------------------------------+------------------------------+ -- -- The inspiration for this portion of the library is Ruby, which supports- -- regular expressions with [superior ergonomics](https://ruby-doc.org/core-2.7.2/Regexp.html#class-Regexp-label-Capturing).+ -- regular expressions with [superior ergonomics](https://docs.ruby-lang.org/en/master/Regexp.html#class-Regexp-label-Named+Captures). -- ** Quasi-quoters regex,
src/hs/Text/Regex/Pcre2/Foreign/TH.hs view
@@ -1,5 +1,8 @@+{-# LANGUAGE TemplateHaskellQuotes #-}+ module Text.Regex.Pcre2.Foreign.TH where +import Foreign (Ptr) import Language.Haskell.TH {-@@ -26,14 +29,8 @@ -} getter :: String -> TypeQ -> String -> DecsQ getter blockSuffix fieldTypeQ field = do- fieldType <- fieldTypeQ+ let blockName = mkName $ "Pcre2_" ++ blockSuffix+ ty <- [t| Ptr $(conT blockName) -> IO $(fieldTypeQ) |] let dec = ForeignD $ ImportF CApi Unsafe "getters.h" name ty name = mkName $ "pcre2_" ++ blockSuffix ++ "_" ++ field- ty = AppT- (AppT ArrowT $ AppT- (ConT $ mkName "Ptr")- (ConT $ mkName $ "Pcre2_" ++ blockSuffix))- (AppT- (ConT $ mkName "IO")- fieldType) return [dec]
src/hs/Text/Regex/Pcre2/Internal.hs view
@@ -26,9 +26,8 @@ import qualified Data.Text as Text import qualified Data.Text.Foreign as Text import Data.Typeable (cast)-import Data.Void (Void, absurd) import Foreign-import Foreign.C.Types (CInt(..), CUInt(..), CUChar)+import Foreign.C.Types (CInt(..), CUChar, CUInt(..)) import qualified Foreign.Concurrent as Conc import Lens.Micro import Lens.Micro.Extras (preview, view)@@ -77,14 +76,6 @@ fix1 :: a -> ((a -> b) -> a -> b) -> b fix1 x f = fix f x --- | Like `fix1`, but for a function of two arguments. Currently unused.-fix2 :: a -> b -> ((a -> b -> c) -> a -> b -> c) -> c-fix2 x y f = fix f x y---- | Like `fix1`, but for a function of three arguments. Currently unused.-fix3 :: a -> b -> c -> ((a -> b -> c -> d) -> a -> b -> c -> d) -> d-fix3 x y z f = fix f x y z- -- ** Fast @Text@ slicing data Slice = Slice@@ -113,9 +104,9 @@ -- forced when the outer `Maybe` constructor is forced. maybeSmartSlice :: Text -> Slice -> Maybe Text maybeSmartSlice text slice = f <$!> maybeThinSlice text slice where- f substring- | Text.length substring > Text.length text `div` 2 = substring- | otherwise = Text.copy substring+ f substring = if Text.lengthWord8 substring > Text.lengthWord8 text `div` 2+ then substring+ else Text.copy substring -- | Safe, type-restricted `castPtr`. fromCUs :: Ptr CUChar -> Ptr Word8@@ -128,20 +119,19 @@ -- ** Lens utilities -- | A more general `toListOf` that collects targets into any `Alternative`.-toAlternativeOf :: (Alternative f) => Getting (Alt f a) s a -> s -> f a-toAlternativeOf l = let alt = Alt . pure in getAlt . view (l . to alt)+altOf :: (Applicative f) => Getting (Alt f a) s a -> s -> f a+altOf l = let alt = Alt . pure in getAlt . view (l . to alt) _Identity :: Lens' (Identity a) a _Identity f (Identity x) = Identity <$> f x -- ** Streaming support --- | A @FreeT@-style stream that can short-circuit.+-- | A @FreeT@-style stream. data Stream b m a = StreamPure a | StreamYield b (Stream b m a) -- ^ Yield a value and keep going. | StreamEffect (m (Stream b m a)) -- ^ Have an effect and keep going.- | StreamStop -- ^ Short-circuit. deriving (Functor) instance (Functor m) => Applicative (Stream b m) where@@ -149,13 +139,11 @@ StreamPure f <*> sx = f <$> sx StreamYield y sf <*> sx = StreamYield y $ sf <*> sx StreamEffect msf <*> sx = StreamEffect $ msf <&> (<*> sx)- StreamStop <*> _ = StreamStop instance (Functor m) => Monad (Stream b m) where StreamPure x >>= f = f x StreamYield y sx >>= f = StreamYield y $ sx >>= f StreamEffect msx >>= f = StreamEffect $ msx <&> (>>= f)- StreamStop >>= _ = StreamStop instance MonadTrans (Stream b) where lift = StreamEffect . fmap StreamPure@@ -172,17 +160,13 @@ StreamPure x -> StreamPure x StreamYield y sx -> StreamEffect $ f y <&> \y' -> StreamYield y' $ go sx StreamEffect ms -> StreamEffect $ go <$> ms- StreamStop -> StreamStop -- | Unsafely, lazily tear down a `Stream` into a pure list of values yielded.--- The stream must be infinite in the sense of it only terminating due to--- explicit `StreamStop`.-unsafeLazyStreamToList :: Stream b IO Void -> [b]+unsafeLazyStreamToList :: Stream b IO a -> [b] unsafeLazyStreamToList = fix $ \continue -> \case- StreamPure v -> absurd v+ StreamPure _ -> [] StreamYield y s -> y : continue s StreamEffect ms -> continue $ unsafePerformIO ms- StreamStop -> [] -- * Assembling inputs into @Matcher@s and @Subber@s @@ -190,15 +174,15 @@ -- been \"compiled\". It takes a subject a produces a stream of match results -- corresponding to a global match. ----- The actual values of type @Ptr Pcre2_match_data@ will be equal within each--- global match; they represent the states of the C data at moments in time, and--- are intended to be composed with another streaming transformation before--- being subjected to teardown and `unsafePerformIO`.-type Matcher = Text -> Stream (Ptr Pcre2_match_data) IO Void+-- The actual yielded match data references will be equal within each global+-- match; they represent the states of the C data at moments in time, and are+-- intended to be composed with another streaming transformation before being+-- subjected to teardown and `unsafePerformIO`.+type Matcher = Text -> Stream MatchData IO () -- | A substitution function. It takes a subject and produces the number of--- substitutions performed (0 or 1, or more in the presence of `SubGlobal`)--- along with the transformed subject. Currently the number is unused.+-- substitutions performed (0 or 1, or more if `SubGlobal`) along with the+-- transformed subject. Currently the number is unused. type Subber = Text -> IO (CInt, Text) -- ** Options@@ -498,14 +482,14 @@ MatchWord -> [CompileExtraOption pcre2_EXTRA_MATCH_WORD] -- CompileContextOption- Bsr bsr -> unary- CompileContextOption pcre2_set_bsr (bsrToC bsr)- MaxPatternLength len -> unary- CompileContextOption pcre2_set_max_pattern_length (fromIntegral len)- Newline newline -> unary- CompileContextOption pcre2_set_newline (newlineToC newline)- ParensLimit limit -> unary- CompileContextOption pcre2_set_parens_nest_limit (fromIntegral limit)+ Bsr bsr -> ctxUpd CompileContextOption+ pcre2_set_bsr (bsrToC bsr)+ MaxPatternLength len -> ctxUpd CompileContextOption+ pcre2_set_max_pattern_length (fromIntegral len)+ Newline newline -> ctxUpd CompileContextOption+ pcre2_set_newline (newlineToC newline)+ ParensLimit limit -> ctxUpd CompileContextOption+ pcre2_set_parens_nest_limit (fromIntegral limit) -- CompileRecGuardOption UnsafeCompileRecGuard f -> [CompileRecGuardOption f]@@ -530,17 +514,18 @@ UnsafeSubCallout f -> [SubCalloutOption f] -- MatchContextOption- DepthLimit limit -> unary- MatchContextOption pcre2_set_depth_limit (fromIntegral limit)- HeapLimit limit -> unary- MatchContextOption pcre2_set_heap_limit (fromIntegral limit)- MatchLimit limit -> unary- MatchContextOption pcre2_set_match_limit (fromIntegral limit)- OffsetLimit limit -> CompileOption pcre2_USE_OFFSET_LIMIT : unary- MatchContextOption pcre2_set_offset_limit (fromIntegral limit)+ DepthLimit limit -> ctxUpd MatchContextOption+ pcre2_set_depth_limit (fromIntegral limit)+ HeapLimit limit -> ctxUpd MatchContextOption+ pcre2_set_heap_limit (fromIntegral limit)+ MatchLimit limit -> ctxUpd MatchContextOption+ pcre2_set_match_limit (fromIntegral limit)+ OffsetLimit limit ->+ CompileOption pcre2_USE_OFFSET_LIMIT :+ ctxUpd MatchContextOption pcre2_set_offset_limit (fromIntegral limit) where- unary ctor f x = [ctor $ \ctx -> withForeignPtr ctx applyAndCheck] where+ ctxUpd ctor f x = [ctor $ \ctx -> withForeignPtr ctx applyAndCheck] where applyAndCheck ctxPtr = f ctxPtr x >>= check (== 0) -- | Intermediate representation of options expressing what effect they'll have@@ -694,15 +679,20 @@ -- | A `MatchEnv` is sufficient to fully implement a matching function. matcherWithEnv :: MatchEnv -> Matcher-matcherWithEnv matchEnv@MatchEnv{..} subject = StreamEffect $- withForeignPtr matchEnvCode $ \codePtr ->- withMatchDataFromCode codePtr $ \matchDataPtr ->- Text.useAsPtr subject $ \subjPtr subjCUs -> do- MatchTempEnv{..} <- mkMatchTempEnv matchEnv subject+matcherWithEnv matchEnv@MatchEnv{..} subject = StreamEffect $ do+ (subjForeignPtr, subjCUs) <- Text.asForeignPtr subject+ matchData <- mkForeignPtr pcre2_match_data_free $+ withForeignPtr matchEnvCode $ \codePtr ->+ pcre2_match_data_create_from_pattern codePtr nullPtr+ MatchTempEnv{..} <- mkMatchTempEnv matchEnv subject - -- Loop over the subject, emitting match data until stopping.- return $ fix1 0 $ \continue curOff -> do- result <- liftIO $ withForeignOrNullPtr matchTempEnvCtx $ \ctxPtr ->+ -- Loop over the subject, emitting match data until stopping.+ return $ fix1 0 $ \continue curOff -> do+ result <- liftIO $+ withForeignPtr matchEnvCode $ \codePtr ->+ withForeignPtr subjForeignPtr $ \subjPtr ->+ withForeignPtr matchData $ \matchDataPtr ->+ withForeignOrNullPtr matchTempEnvCtx $ \ctxPtr -> pcre2_match codePtr (toCUs subjPtr)@@ -712,31 +702,24 @@ matchDataPtr ctxPtr - -- Handle no match and errors- when (result == pcre2_ERROR_NOMATCH) StreamStop+ -- Handle no match and errors+ unless (result == pcre2_ERROR_NOMATCH) $ do when (result == pcre2_ERROR_CALLOUT) $ liftIO $ maybeRethrow matchTempEnvRef liftIO $ check (> 0) result - streamYield matchDataPtr+ streamYield matchData -- Determine next starting offset nextOff <- liftIO $ do- ovecPtr <- pcre2_get_ovector_pointer matchDataPtr+ ovecPtr <- withForeignPtr matchData+ pcre2_get_ovector_pointer curOffEnd <- peekElemOff ovecPtr 1 -- Prevent infinite loop upon empty match return $ max curOffEnd (curOff + 1) -- Handle end of subject- when (nextOff > fromIntegral subjCUs) StreamStop-- continue nextOff-- where- withMatchDataFromCode codePtr action = do- matchData <- mkForeignPtr pcre2_match_data_free $- pcre2_match_data_create_from_pattern codePtr nullPtr- withForeignPtr matchData action+ unless (nextOff > fromIntegral subjCUs) $ continue nextOff -- | Helper to generate public matching functions. pureUserMatcher :: Option -> Text -> Matcher@@ -821,7 +804,7 @@ where -- Guess the size of the output to be <= 2x that of the subject.- initOutLen = Text.length subject * 2+ initOutLen = Text.lengthWord8 subject * 2 -- | Helper to generate substitution function. For consistency with -- `pureUserMatcher`.@@ -946,7 +929,7 @@ ovecPtr <- pcre2_callout_block_offset_vector blockPtr top <- pcre2_callout_block_capture_top blockPtr forM (0 :| [1 .. fromIntegral top - 1]) $ \n -> do- [start, end] <- forM [0, 1] $ \i ->+ (start, end) <- forOf each (0, 1) $ \i -> fromIntegral <$> peekElemOff ovecPtr (n * 2 + i) evaluate $ maybeSmartSlice calloutSubject $ Slice start end @@ -977,14 +960,14 @@ ovecPtr <- pcre2_substitute_callout_block_ovector blockPtr ovecCount <- pcre2_substitute_callout_block_oveccount blockPtr forM (0 :| [1 .. fromIntegral ovecCount - 1]) $ \n -> do- [start, end] <- forM [0, 1] $ \i ->+ (start, end) <- forOf each (0, 1) $ \i -> fromIntegral <$> peekElemOff ovecPtr (n * 2 + i) evaluate $ maybeSmartSlice subCalloutSubject $ Slice start end subCalloutReplacement <- do outPtr <- pcre2_substitute_callout_block_output blockPtr offsetsPtr <- pcre2_substitute_callout_block_output_offsets blockPtr- [start, end] <- forM [0, 1] $ peekElemOff offsetsPtr+ (start, end) <- forOf each (0, 1) $ peekElemOff offsetsPtr Text.fromPtr (fromCUs $ advancePtr outPtr $ fromIntegral start) (fromIntegral $ end - start)@@ -1027,7 +1010,7 @@ -- going, remembering where we are now. thinSlice subject (Slice prevOffEnd off) : c' : r offEnd termSegments off =- let offEnd = fromIntegral $ Text.length subject+ let offEnd = fromIntegral $ Text.lengthWord8 subject -- If the terminal segment is empty, omit it altogether. That way, -- Text.concat can just return the subject without copying anything in -- cases where no substring is changed.@@ -1049,18 +1032,19 @@ -- -- * @[]@ when we want to easily pattern match specific capture groups via -- Template Haskell-generated @ViewPatterns@.-type FromMatch t = Ptr Pcre2_match_data -> IO (t Slice)+type FromMatch t = MatchData -> IO (t Slice) -- | Read all specifically indexed captures' offsets from match results. getWhitelistedSlices :: (Traversable t) => t Int -> FromMatch t-getWhitelistedSlices whitelist matchDataPtr = do- ovecPtr <- pcre2_get_ovector_pointer matchDataPtr- let peekOvec :: Int -> IO Text.I8- peekOvec = fmap fromIntegral . peekElemOff ovecPtr+getWhitelistedSlices whitelist matchData =+ withForeignPtr matchData $ \matchDataPtr -> do+ ovecPtr <- pcre2_get_ovector_pointer matchDataPtr+ let peekOvec :: Int -> IO Text.I8+ peekOvec = fmap fromIntegral . peekElemOff ovecPtr - forM whitelist $ \i -> Slice- <$> peekOvec (i * 2)- <*> peekOvec (i * 2 + 1)+ forM whitelist $ \i -> Slice+ <$> peekOvec (i * 2)+ <*> peekOvec (i * 2 + 1) -- | Read just the 0th capture's offsets from match results. get0thSlice :: FromMatch Identity@@ -1068,11 +1052,11 @@ -- | Read all captures' offsets from match results. getAllSlices :: FromMatch NonEmpty-getAllSlices matchDataPtr = do- count <- fromIntegral <$> pcre2_get_ovector_count matchDataPtr+getAllSlices matchData = do+ count <- fromIntegral <$> withForeignPtr matchData pcre2_get_ovector_count let whitelist = 0 :| [1 .. count - 1] - getWhitelistedSlices whitelist matchDataPtr+ getWhitelistedSlices whitelist matchData -- | Placeholder for building a `Traversal'` to be passed to `has`. getNoSlices :: FromMatch Proxy@@ -1095,7 +1079,7 @@ -- -- @since 2.0.0 capturesOpt :: (Alternative f) => Option -> Text -> Text -> f (NonEmpty Text)-capturesOpt option patt = toAlternativeOf $ _capturesOpt option patt+capturesOpt option patt = altOf $ _capturesOpt option patt -- | Does the pattern match the subject at least once? matches :: Text -> Text -> Bool@@ -1117,13 +1101,13 @@ -- -- @since 2.0.0 matchOpt :: (Alternative f) => Option -> Text -> Text -> f Text-matchOpt option patt = toAlternativeOf $ _matchOpt option patt+matchOpt option patt = altOf $ _matchOpt option patt -- | Perform at most one substitution. See -- [the docs](https://pcre.org/current/doc/html/pcre2api.html#SEC36) for the -- special syntax of /replacement/. ----- >>> sub "(\\w+) calling the (\\w+)" "$2 calling the $1" "the pot calling the kettle black"+-- >>> sub "\\b(\\w+) calling the (\\w+)\\b" "$2 calling the $1" "the pot calling the kettle black" -- "the kettle calling the pot black" sub :: Text -- ^ pattern@@ -1230,6 +1214,7 @@ where tab = 20 pattLinesMaybeWithCaret+ -- FIXME Do not use Text.length since offsets are in code units | offset' == Text.length patt = pattLines | otherwise = insertCaretLine numberedPattLines offset' = fromIntegral offset
src/hs/Text/Regex/Pcre2/TH.hs view
@@ -16,10 +16,11 @@ import Control.Monad (forM) import Control.Monad.State.Strict (evalStateT) import Data.IORef-import qualified Data.IntMap.Strict as IM-import Data.List.NonEmpty (NonEmpty(..))+import Data.List (sortBy)+import Data.List.NonEmpty (NonEmpty) import Data.Map.Lazy (Map) import qualified Data.Map.Lazy as Map+import Data.Ord (comparing) import Data.Proxy (Proxy(..)) import Data.Text (Text) import qualified Data.Text as Text@@ -27,7 +28,7 @@ import Data.Type.Bool (If) import Data.Type.Equality (type (==)) import Foreign-import Foreign.C (CUInt, CUChar)+import Foreign.C (CUChar, CUInt) import GHC.TypeLits hiding (Text) import qualified GHC.TypeLits as TypeLits import Language.Haskell.TH@@ -45,7 +46,7 @@ -- This type is only intended to be created by `regex`\/`_regex` and consumed by -- `capture`\/`_capture`, relying on type inference. Specifying the @info@ -- explicitly in a type signature is not supported—the definition of--- `CapturesInfo` is not part of the public API and may change without warning.+-- `CapturesInfo` is not part of the public API and may change. -- -- After obtaining `Captures` it's recommended to immediately consume them and -- transform them into application-level data, to avoid leaking the types.@@ -60,16 +61,16 @@ -- | Look up the number of a capture at compile time, either by number or by -- name. Throw a helpful 'TypeError' if the index doesn't exist. type family CaptNum (i :: k) (info :: CapturesInfo) :: Nat where- CaptNum (num :: Nat) '(hi, _) = If (num `CmpNat` hi == 'GT)+ CaptNum (i :: Nat) '(hi, _) = If (i `CmpNat` hi == 'GT) -- then- (TypeError (TypeLits.Text "No capture numbered " :<>: ShowType num))+ (TypeError (TypeLits.Text "No capture numbered " :<>: ShowType i)) -- else- num+ i - CaptNum (name :: Symbol) '(_, '(name, num) ': _) = num- CaptNum (name :: Symbol) '(hi, _ ': kvs) = CaptNum name '(hi, kvs)- CaptNum (name :: Symbol) _ = TypeError- (TypeLits.Text "No capture named " :<>: ShowType name)+ CaptNum (i :: Symbol) '(_, '(i, num) ': _) = num+ CaptNum (i :: Symbol) '(hi, _ ': kvs) = CaptNum i '(hi, kvs)+ CaptNum (i :: Symbol) _ = TypeError+ (TypeLits.Text "No capture named " :<>: ShowType i) CaptNum _ _ = TypeError (TypeLits.Text "Capture index must be a number (Nat) or name (Symbol)")@@ -77,9 +78,9 @@ -- | Safely lookup a capture in a `Captures` result obtained from a Template -- Haskell-generated matching function. ----- The ugly type signature may be interpreted like this: /Given some capture/--- /group index @i@ and some @info@ about a regex, ensure that index exists and/--- /is resolved to the number @num@ at compile time. Then, at runtime, get a/+-- The type signature may be interpreted like this: /Given some capture group/+-- /index @i@ and some @info@ about a regex, ensure that index exists and is/+-- /resolved to the number @num@ at compile time. Then, at runtime, get a/ -- /capture group (numbered @num@) from a list of (at least @num@) captures./ -- -- In practice the variable @i@ is specified by type application and the other@@ -88,7 +89,7 @@ -- > capture @3 -- > capture @"bar" ----- Specifying a nonexistent number or name will result in a type error.+-- Specifying an invalid index will result in a type error. capture :: forall i info num. (CaptNum i info ~ num, KnownNat num) => Captures info -> Text capture = view $ _capture @i@@ -115,40 +116,37 @@ let matcher = pureUserMatcher mempty patt in (Map.insert patt matcher cache, matcher) --- | From options and pattern, determine parenthesized captures' names in order.-predictCaptureNames :: Option -> Text -> IO [Maybe Text]-predictCaptureNames option patt = do+-- | From options and pattern, determine number of parenthesized captures, along+-- with a list of their names (each indexed and in index order).+predictCapturesInfo :: Option -> Text -> IO (Int, [(Text, Int)])+predictCapturesInfo option patt = do code <- evalStateT (extractCompileEnv >>= extractCode patt) (applyOption option) - withForeignPtr code getCaptureNames---- | Get parenthesized captures' names in order.-getCaptureNames :: Ptr Pcre2_code -> IO [Maybe Text]-getCaptureNames codePtr = do- nameCount <- getCodeInfo @CUInt codePtr pcre2_INFO_NAMECOUNT- nameEntrySize <- getCodeInfo @CUInt codePtr pcre2_INFO_NAMEENTRYSIZE- nameTable <- getCodeInfo @PCRE2_SPTR codePtr pcre2_INFO_NAMETABLE+ withForeignPtr code $ \codePtr -> do+ count <- getCodeInfo @CUInt codePtr pcre2_INFO_NAMECOUNT+ entrySize <- getCodeInfo @CUInt codePtr pcre2_INFO_NAMEENTRYSIZE+ table <- getCodeInfo @PCRE2_SPTR codePtr pcre2_INFO_NAMETABLE - -- Can't do [0 .. nameCount - 1] because it underflows when nameCount == 0- let indexes = takeWhile (< nameCount) [0 ..]- names <- fmap IM.fromList $ forM indexes $ \i -> do- let entryPtr = nameTable `advancePtr` fromIntegral (i * nameEntrySize)- groupNamePtr = entryPtr `advancePtr` 2- groupNumber <- do- [hi, lo] <- forM [0, 1] $ \off ->- fromIntegral @CUChar <$> peekByteOff entryPtr off- return $ hi `shiftL` 8 + lo- groupNameLen <- lengthArray0 0 groupNamePtr- groupName <- Text.fromPtr- (fromCUs groupNamePtr)- (fromIntegral groupNameLen)- return (groupNumber, groupName)+ -- Can't do [0 .. count - 1] because it underflows when count == 0+ let indexes = takeWhile (< count) [0 ..]+ lookupTable <- forM indexes $ \i -> do+ let entryPtr = table `advancePtr` fromIntegral (i * entrySize)+ groupNamePtr = entryPtr `advancePtr` 2+ groupNumber <- do+ (hi, lo) <- forOf each (0, 1) $ \off ->+ fromIntegral @CUChar <$> peekByteOff entryPtr off+ return $ hi `shiftL` 8 + lo+ groupNameLen <- lengthArray0 0 groupNamePtr+ groupName <- Text.fromPtr+ (fromCUs groupNamePtr)+ (fromIntegral groupNameLen)+ return (groupName, groupNumber) - hiCaptNum <- getCodeInfo @CUInt codePtr pcre2_INFO_CAPTURECOUNT+ hiCaptNum <- getCodeInfo @CUInt codePtr pcre2_INFO_CAPTURECOUNT - return $ map (names IM.!?) [1 .. fromIntegral hiCaptNum]+ return (fromIntegral hiCaptNum, sortBy (comparing snd) lookupTable) -- | Low-level access to compiled pattern info, per the docs. getCodeInfo :: (Storable a) => Ptr Pcre2_code -> CUInt -> IO a@@ -156,44 +154,38 @@ pcre2_pattern_info codePtr what wherePtr >>= check (== 0) peek wherePtr --- | Predict parenthesized captures (maybe named) of a pattern at splice time.-predictCaptureNamesQ :: String -> Q [Maybe Text]-predictCaptureNamesQ = runIO . predictCaptureNames mempty . Text.pack---- | Get the indexes of `Just` the named captures.-toKVs :: [Maybe Text] -> [(Int, Text)]-toKVs names = [(number, name) | (number, Just name) <- zip [1 ..] names]+-- | Predict info about parenthesized captures of a pattern at splice time.+predictCapturesInfoQ :: String -> Q (Int, [(Text, Int)])+predictCapturesInfoQ = runIO . predictCapturesInfo mempty . Text.pack -- | Generate the data-kinded phantom type parameter of `Captures` of a pattern, -- if needed. capturesInfoQ :: String -> Q (Maybe Type)-capturesInfoQ s = predictCaptureNamesQ s >>= \case+capturesInfoQ s = predictCapturesInfoQ s >>= \case -- No parenthesized captures, so need for Captures, so no info.- [] -> return Nothing+ (0, _) -> return Nothing - -- One or more parenthesized captures. Present- -- [Just "foo", Nothing, Nothing, Just "bar", Nothing]- -- as+ -- One or more parenthesized captures. Produce -- '(5, '[ '("foo", 1), '("bar", 4)]).- captureNames -> Just <$> promotedTupleT 2 `appT` hiQ `appT` kvsQ where+ (len, lookupTable) -> Just <$> promotedTupleT 2 `appT` hiQ `appT` kvsQ where -- 5- hiQ = litT $ numTyLit $ fromIntegral $ length captureNames+ hiQ = litT $ numTyLit $ fromIntegral len -- '[ '("foo", 1), '("bar", 4)]- kvsQ = foldr f promotedNilT $ toKVs captureNames+ kvsQ = foldr f promotedNilT lookupTable -- '("foo", 1) ': ...- f (number, name) r = promotedConsT `appT` kvQ `appT` r where+ f (name, number) r = promotedConsT `appT` kvQ `appT` r where kvQ = promotedTupleT 2 -- '(,) `appT` litT (strTyLit $ Text.unpack name) -- "foo" `appT` litT (numTyLit $ fromIntegral number) -- 1 -- | Helper for `regex` with no parenthesized captures. matchTH :: (Alternative f) => Text -> Text -> f Text-matchTH patt = toAlternativeOf $ _matchTH patt+matchTH patt = altOf $ _matchTH patt -- | Helper for `regex` with parenthesized captures. capturesTH :: forall info f. (Alternative f) => Text -> Text -> f (Captures info)-capturesTH patt = toAlternativeOf $ _capturesTH patt+capturesTH patt = altOf $ _capturesTH patt -- | Helper for `regex` as a guard pattern. matchesTH :: Text -> Text -> Bool@@ -213,13 +205,25 @@ _capturesTH patt = _gcaptures (memoMatcher patt) getAllSlices . captured where captured f cs = f (Captures cs) <&> \(Captures cs') -> cs' +-- | Helper to generate a `Text` in code.+textQ :: String -> ExpQ+textQ s = [e| Text.pack $(stringE s) |]++-- | Helper to generate a `quoteExp` function, which either simply matches the+-- subject or produces captures depending on the pattern.+mkQuoteExp :: ExpQ -> ExpQ -> String -> ExpQ+mkQuoteExp matchE capturesE s = regexQ `appE` textQ s where+ regexQ = capturesInfoQ s >>= \case+ Nothing -> matchE+ Just info -> capturesE `appTypeE` return info+ -- | === As an expression -- -- @ -- regex :: (`Alternative` f) => String -> Text -> f (`Captures` info) -- @ ----- in the presence of parenthesized captures, or+-- if there are parenthesized captures, or -- -- > regex :: (Alternative f) => String -> Text -> f Text --@@ -235,13 +239,13 @@ -- > year = read @Int $ Text.unpack $ capture @"y" cs -- > ... ----- > forM_ ([regex|\s+$|] line :: Maybe Text) $ \spaces -> error $--- > "line has trailing spaces (" ++ show (Text.length spaces) ++ " characters)"+-- > forM_ @Maybe ([regex|\s+$|] line) $ \spaces ->+-- > printf "line has trailing spaces (%d characters)\n" (Text.length spaces) -- -- === As a pattern ----- This matches when the regex first matches, whereupon any named captures are--- bound to variables of the same names.+-- This matches when the regex first matches. Any named captures are bound to+-- variables of the same names. -- -- > case "submitted 2020-10-20" of -- > [regex|(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})|] ->@@ -254,35 +258,18 @@ -- If there are no named captures, this simply acts as a guard. regex :: QuasiQuoter regex = QuasiQuoter{- quoteExp = \s -> do- let regexQ = capturesInfoQ s >>= \case- Nothing -> [e| matchTH |]- Just info -> [e| capturesTH |] `appTypeE` return info- regexQ `appE` [e| Text.pack $(stringE s) |],-- quotePat = \s -> do- captureNames <- predictCaptureNamesQ s-- case toKVs captureNames of- -- No named captures. Test whether the string matches without- -- creating any new Text values.- [] -> viewP- [e| matchesTH (Text.pack $(stringE s)) |]- [p| True |]-- -- One or more named captures. Attempt to bind only those to local- -- variables of the same names.- numberedNames -> viewP e p where- (numbers, names) = unzip numberedNames- e = [e| capturesNumberedTH- (Text.pack $(stringE s))- $(liftData numbers) |]- p = foldr f wildP names- f name r = conP '(:) [varP $ mkName $ Text.unpack name, r],+ quoteExp = mkQuoteExp [e| matchTH |] [e| capturesTH |], - quoteType = const $ fail "regex: cannot produce a type",+ quotePat = \s -> predictCapturesInfoQ s >>= \info -> case snd info of+ [] -> viewP [e| matchesTH $(textQ s) |] [p| True |]+ lookupTable -> viewP e p where+ (names, numbers) = unzip lookupTable+ e = [e| capturesNumberedTH $(textQ s) $(liftData numbers) |]+ p = foldr f wildP names+ f name r = conP '(:) [varP $ mkName $ Text.unpack name, r], - quoteDec = const $ fail "regex: cannot produce declarations"}+ quoteType = \_ -> fail "regex: cannot produce a type",+ quoteDec = \_ -> fail "regex: cannot produce declarations"} -- | An optical variant of `regex`\/a type-annotated variant of `_captures`. Can -- only be used as an expression.@@ -301,14 +288,8 @@ -- > -- There are 15 competing standards _regex :: QuasiQuoter _regex = QuasiQuoter{- quoteExp = \s -> do- let _regexQ = capturesInfoQ s >>= \case- Nothing -> [e| _matchTH |]- Just info -> [e| _capturesTH |] `appTypeE` return info- _regexQ `appE` [e| Text.pack $(stringE s) |],-- quotePat = const $ fail "_regex: cannot produce a pattern",-- quoteType = const $ fail "_regex: cannot produce a type",+ quoteExp = mkQuoteExp [e| _matchTH |] [e| _capturesTH |], - quoteDec = const $ fail "_regex: cannot produce declarations"}+ quotePat = \_ -> fail "_regex: cannot produce a pattern",+ quoteType = \_ -> fail "_regex: cannot produce a type",+ quoteDec = \_ -> fail "_regex: cannot produce declarations"}
test/Spec.hs view
@@ -63,6 +63,10 @@ matchesOpt (Bsr BsrUnicode) "\\R$" "line separator: \x2028" `shouldBe` True + it ("doesn't use-after-free() for long matches" `issue` 39) $ do+ let subj = Text.replicate 20000 "a"+ length (captures @[] "." subj) `shouldBe` 20000+ describe "lens-powered matching" $ do let _nee :: Traversal' Text Text _nee = _matchOpt (Caseless <> MatchWord) "nee"